Current section

86 Versions

Jump to

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]},