Packages
floki
0.36.2
0.38.4
0.38.3
0.38.2
0.38.1
0.38.0
0.37.1
0.37.0
0.36.3
0.36.2
0.36.1
0.36.0
0.35.4
0.35.3
0.35.2
0.35.1
0.35.0
0.34.3
0.34.2
0.34.1
0.34.0
0.33.1
0.33.0
0.32.1
0.32.0
0.31.0
0.30.1
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.1
0.23.0
0.22.0
0.21.0
0.20.4
0.20.3
0.20.2
0.20.1
0.20.0
0.19.3
0.19.2
0.19.1
0.19.0
0.18.1
0.18.0
0.17.2
0.17.1
0.17.0
0.16.0
0.15.0
0.14.0
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.0
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.0
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.1
0.1.0
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
Floki is a simple HTML parser that enables search for nodes using CSS selectors.
Current section
86 Versions
Jump to
Current section
86 Versions
Compare versions
5
files changed
+127
additions
-42
deletions
| @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. | |
| 7 7 | |
| 8 8 | ## [Unreleased][unreleased] |
| 9 9 | |
| 10 | + ## [0.36.2] - 2024-04-26 |
| 11 | + |
| 12 | + ### Added |
| 13 | + |
| 14 | + - Implement the `Inspect` protocol for the `Floki.HTMLTree` struct. |
| 15 | + This struct is currently private. Thank you [@vittoriabitton](https://github.com/vittoriabitton). |
| 16 | + |
| 17 | + ### Fixed |
| 18 | + |
| 19 | + - Fix regression to respect config option `:encode` in `Floki.raw_html/2`. |
| 20 | + Thanks [@Sgoettschkes](https://github.com/Sgoettschkes). |
| 21 | + |
| 22 | + - Make the `Floki.raw_html/2` treat the contents of the `<title>` tag as plain text. |
| 23 | + The idea is to align with `parse_document/2`. |
| 24 | + Thank you [@aymanosman](https://github.com/aymanosman). |
| 25 | + |
| 10 26 | ## [0.36.1] - 2024-03-18 |
| 11 27 | |
| 12 28 | ### Fixed |
| @@ -770,7 +786,8 @@ of the parent element inside HTML. | |
| 770 786 | |
| 771 787 | - Elixir version requirement from "~> 1.0.0" to ">= 1.0.0". |
| 772 788 | |
| 773 | - [unreleased]: https://github.com/philss/floki/compare/v0.36.1...HEAD |
| 789 | + [unreleased]: https://github.com/philss/floki/compare/v0.36.2...HEAD |
| 790 | + [0.36.2]: https://github.com/philss/floki/compare/v0.36.1...v0.36.2 |
| 774 791 | [0.36.1]: https://github.com/philss/floki/compare/v0.36.0...v0.36.1 |
| 775 792 | [0.36.0]: https://github.com/philss/floki/compare/v0.35.4...v0.36.0 |
| 776 793 | [0.35.4]: https://github.com/philss/floki/compare/v0.35.3...v0.35.4 |
| @@ -1,37 +1,36 @@ | |
| 1 | + {<<"app">>,<<"floki">>}. |
| 2 | + {<<"build_tools">>,[<<"mix">>]}. |
| 3 | + {<<"description">>, |
| 4 | + <<"Floki is a simple HTML parser that enables search for nodes using CSS selectors.">>}. |
| 5 | + {<<"elixir">>,<<"~> 1.13">>}. |
| 6 | + {<<"files">>, |
| 7 | + [<<"lib/floki">>,<<"lib/floki/html_tree.ex">>,<<"lib/floki/html_parser">>, |
| 8 | + <<"lib/floki/html_parser/html5ever.ex">>, |
| 9 | + <<"lib/floki/html_parser/mochiweb.ex">>, |
| 10 | + <<"lib/floki/html_parser/fast_html.ex">>,<<"lib/floki/traversal.ex">>, |
| 11 | + <<"lib/floki/html_tree">>,<<"lib/floki/html_tree/text.ex">>, |
| 12 | + <<"lib/floki/html_tree/html_node.ex">>,<<"lib/floki/html_tree/comment.ex">>, |
| 13 | + <<"lib/floki/html_tree/id_seeder.ex">>,<<"lib/floki/selector.ex">>, |
| 14 | + <<"lib/floki/entities.ex">>,<<"lib/floki/deep_text.ex">>, |
| 15 | + <<"lib/floki/flat_text.ex">>,<<"lib/floki/finder.ex">>, |
| 16 | + <<"lib/floki/entities">>,<<"lib/floki/entities/codepoints.ex">>, |
| 17 | + <<"lib/floki/filter_out.ex">>,<<"lib/floki/html_parser.ex">>, |
| 18 | + <<"lib/floki/selector">>,<<"lib/floki/selector/pseudo_class.ex">>, |
| 19 | + <<"lib/floki/selector/attribute_selector.ex">>, |
| 20 | + <<"lib/floki/selector/functional.ex">>, |
| 21 | + <<"lib/floki/selector/combinator.ex">>,<<"lib/floki/selector/parser.ex">>, |
| 22 | + <<"lib/floki/selector/tokenizer.ex">>,<<"lib/floki/raw_html.ex">>, |
| 23 | + <<"lib/floki/html">>,<<"lib/floki/html/numeric_charref.ex">>, |
| 24 | + <<"lib/floki/html/tokenizer.ex">>,<<"lib/floki/text_extractor.ex">>, |
| 25 | + <<"lib/floki/parse_error.ex">>,<<"lib/floki.ex">>, |
| 26 | + <<"src/floki_selector_lexer.xrl">>,<<"src/floki_mochi_html.erl">>, |
| 27 | + <<"mix.exs">>,<<"README.md">>,<<"LICENSE">>,<<"CODE_OF_CONDUCT.md">>, |
| 28 | + <<"CONTRIBUTING.md">>,<<"CHANGELOG.md">>]}. |
| 29 | + {<<"licenses">>,[<<"MIT">>]}. |
| 1 30 | {<<"links">>, |
| 2 31 | [{<<"Changelog">>,<<"https://hexdocs.pm/floki/changelog.html">>}, |
| 3 32 | {<<"GitHub">>,<<"https://github.com/philss/floki">>}, |
| 4 33 | {<<"Sponsor">>,<<"https://github.com/sponsors/philss">>}]}. |
| 5 34 | {<<"name">>,<<"floki">>}. |
| 6 | - {<<"version">>,<<"0.36.1">>}. |
| 7 | - {<<"description">>, |
| 8 | - <<"Floki is a simple HTML parser that enables search for nodes using CSS selectors.">>}. |
| 9 | - {<<"elixir">>,<<"~> 1.13">>}. |
| 10 | - {<<"app">>,<<"floki">>}. |
| 11 | - {<<"licenses">>,[<<"MIT">>]}. |
| 12 | - {<<"files">>, |
| 13 | - [<<"lib/floki">>,<<"lib/floki/html_parser">>, |
| 14 | - <<"lib/floki/html_parser/html5ever.ex">>, |
| 15 | - <<"lib/floki/html_parser/fast_html.ex">>, |
| 16 | - <<"lib/floki/html_parser/mochiweb.ex">>,<<"lib/floki/traversal.ex">>, |
| 17 | - <<"lib/floki/text_extractor.ex">>,<<"lib/floki/raw_html.ex">>, |
| 18 | - <<"lib/floki/selector.ex">>,<<"lib/floki/selector">>, |
| 19 | - <<"lib/floki/selector/combinator.ex">>, |
| 20 | - <<"lib/floki/selector/attribute_selector.ex">>, |
| 21 | - <<"lib/floki/selector/tokenizer.ex">>,<<"lib/floki/selector/parser.ex">>, |
| 22 | - <<"lib/floki/selector/functional.ex">>, |
| 23 | - <<"lib/floki/selector/pseudo_class.ex">>,<<"lib/floki/html_tree">>, |
| 24 | - <<"lib/floki/html_tree/id_seeder.ex">>,<<"lib/floki/html_tree/comment.ex">>, |
| 25 | - <<"lib/floki/html_tree/html_node.ex">>,<<"lib/floki/html_tree/text.ex">>, |
| 26 | - <<"lib/floki/finder.ex">>,<<"lib/floki/filter_out.ex">>, |
| 27 | - <<"lib/floki/html_tree.ex">>,<<"lib/floki/html">>, |
| 28 | - <<"lib/floki/html/numeric_charref.ex">>,<<"lib/floki/html/tokenizer.ex">>, |
| 29 | - <<"lib/floki/html_parser.ex">>,<<"lib/floki/deep_text.ex">>, |
| 30 | - <<"lib/floki/entities.ex">>,<<"lib/floki/flat_text.ex">>, |
| 31 | - <<"lib/floki/parse_error.ex">>,<<"lib/floki/entities">>, |
| 32 | - <<"lib/floki/entities/codepoints.ex">>,<<"lib/floki.ex">>, |
| 33 | - <<"src/floki_selector_lexer.xrl">>,<<"src/floki_mochi_html.erl">>, |
| 34 | - <<"mix.exs">>,<<"README.md">>,<<"LICENSE">>,<<"CODE_OF_CONDUCT.md">>, |
| 35 | - <<"CONTRIBUTING.md">>,<<"CHANGELOG.md">>]}. |
| 36 35 | {<<"requirements">>,[]}. |
| 37 | - {<<"build_tools">>,[<<"mix">>]}. |
| 36 | + {<<"version">>,<<"0.36.2">>}. |
| @@ -328,4 +328,77 @@ defmodule Floki.HTMLTree do | |
| 328 328 | do_reduce(tree, fun.(head_node, acc), fun) |
| 329 329 | end |
| 330 330 | end |
| 331 | + |
| 332 | + defimpl Inspect do |
| 333 | + import Inspect.Algebra |
| 334 | + |
| 335 | + def inspect(html_tree, opts) do |
| 336 | + open = "#Floki.HTMLTree[" |
| 337 | + close = "]" |
| 338 | + container_opts = [separator: "", break: :flex] |
| 339 | + |
| 340 | + container_doc( |
| 341 | + open, |
| 342 | + nodes_with_tree(html_tree, html_tree.root_nodes_ids), |
| 343 | + close, |
| 344 | + opts, |
| 345 | + &fun/2, |
| 346 | + container_opts |
| 347 | + ) |
| 348 | + end |
| 349 | + |
| 350 | + defp fun({html_tree, %HTMLNode{} = html_node}, opts) do |
| 351 | + {open, close, container_opts} = build_node(html_node, opts) |
| 352 | + |
| 353 | + container_doc( |
| 354 | + open, |
| 355 | + nodes_with_tree(html_tree, html_node.children_nodes_ids), |
| 356 | + close, |
| 357 | + opts, |
| 358 | + &fun/2, |
| 359 | + container_opts |
| 360 | + ) |
| 361 | + end |
| 362 | + |
| 363 | + defp fun(%Comment{content: comment}, opts), |
| 364 | + do: color(concat(["<!-- ", comment, " -->"]), :comment, opts) |
| 365 | + |
| 366 | + defp fun(%Text{content: text}, opts), do: color(text, :string, opts) |
| 367 | + |
| 368 | + defp nodes_with_tree(html_tree, nodes_ids) do |
| 369 | + nodes_ids |
| 370 | + |> Enum.reverse() |
| 371 | + |> Enum.map(fn node_id -> |
| 372 | + with %HTMLNode{} = html_node <- Map.get(html_tree.nodes, node_id) do |
| 373 | + {html_tree, html_node} |
| 374 | + end |
| 375 | + end) |
| 376 | + end |
| 377 | + |
| 378 | + defp build_node(%HTMLNode{} = node, opts) do |
| 379 | + tag_color = :map |
| 380 | + attribute_color = :map |
| 381 | + |
| 382 | + built_attributes = |
| 383 | + for {name, value} <- node.attributes do |
| 384 | + concat([ |
| 385 | + color(" #{name}=", attribute_color, opts), |
| 386 | + color("\"#{value}\"", :string, opts) |
| 387 | + ]) |
| 388 | + end |
| 389 | + |> concat() |
| 390 | + |
| 391 | + open = |
| 392 | + concat([ |
| 393 | + color("<#{node.type}", tag_color, opts), |
| 394 | + built_attributes, |
| 395 | + color(">", tag_color, opts) |
| 396 | + ]) |
| 397 | + |
| 398 | + close = color("</#{node.type}>", tag_color, opts) |
| 399 | + container_opts = [separator: "", break: :strict] |
| 400 | + |
| 401 | + {open, close, container_opts} |
| 402 | + end |
| 403 | + end |
| 331 404 | end |
| @@ -35,13 +35,12 @@ defmodule Floki.RawHTML do | |
| 35 35 | @no_encoder &Function.identity/1 |
| 36 36 | |
| 37 37 | def raw_html(html_tree, opts) do |
| 38 | - opts = Keyword.validate!(opts, encode: true, pretty: false) |
| 38 | + opts = Keyword.validate!(opts, encode: use_default_encoder?(), pretty: false) |
| 39 39 | |
| 40 40 | encoder = |
| 41 41 | case opts[:encode] do |
| 42 42 | true -> @encoder |
| 43 43 | false -> @no_encoder |
| 44 | - :error -> default_encoder() |
| 45 44 | end |
| 46 45 | |
| 47 46 | padding = |
| @@ -178,6 +177,7 @@ defmodule Floki.RawHTML do | |
| 178 177 | case type do |
| 179 178 | "script" -> @no_encoder |
| 180 179 | "style" -> @no_encoder |
| 180 | + "title" -> @no_encoder |
| 181 181 | _ -> encoder |
| 182 182 | end |
| 183 183 | |
| @@ -195,12 +195,8 @@ defmodule Floki.RawHTML do | |
| 195 195 | ] |
| 196 196 | end |
| 197 197 | |
| 198 | - defp default_encoder do |
| 199 | - if Application.get_env(:floki, :encode_raw_html, true) do |
| 200 | - @encoder |
| 201 | - else |
| 202 | - @no_encoder |
| 203 | - end |
| 198 | + defp use_default_encoder? do |
| 199 | + Application.get_env(:floki, :encode_raw_html, true) |
| 204 200 | end |
| 205 201 | |
| 206 202 | # helpers |
| @@ -3,7 +3,7 @@ defmodule Floki.Mixfile do | |
| 3 3 | |
| 4 4 | @description "Floki is a simple HTML parser that enables search for nodes using CSS selectors." |
| 5 5 | @source_url "https://github.com/philss/floki" |
| 6 | - @version "0.36.1" |
| 6 | + @version "0.36.2" |
| 7 7 | |
| 8 8 | def project do |
| 9 9 | [ |
| @@ -45,7 +45,7 @@ defmodule Floki.Mixfile do | |
| 45 45 | [ |
| 46 46 | {:jason, "~> 1.1", only: [:dev, :test, :docs]}, |
| 47 47 | {:earmark, "~> 1.2", only: :dev}, |
| 48 | - {:ex_doc, "~> 0.31.0", only: :dev, runtime: false}, |
| 48 | + {:ex_doc, "~> 0.32.0", only: :dev, runtime: false}, |
| 49 49 | {:benchee, "~> 1.3.0", only: :dev}, |
| 50 50 | {:benchee_html, "~> 1.0", only: :dev}, |
| 51 51 | {:credo, ">= 0.0.0", only: [:dev, :test]}, |