Packages
floki
0.30.1
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
+58
additions
-35
deletions
| @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. | |
| 7 7 | |
| 8 8 | ## [Unreleased][unreleased] |
| 9 9 | |
| 10 | + ## [0.30.1] - 2021-03-29 |
| 11 | + |
| 12 | + ### Fixed |
| 13 | + |
| 14 | + - Fix typespecs of `Floki.traverse_and_update/2` to make clear that it does not accept text nodes directly. |
| 15 | + |
| 10 16 | ## [0.30.0] - 2021-02-06 |
| 11 17 | |
| 12 18 | ### Added |
| @@ -569,7 +575,8 @@ of the parent element inside HTML. | |
| 569 575 | |
| 570 576 | - Elixir version requirement from "~> 1.0.0" to ">= 1.0.0". |
| 571 577 | |
| 572 | - [unreleased]: https://github.com/philss/floki/compare/v0.30.0...HEAD |
| 578 | + [unreleased]: https://github.com/philss/floki/compare/v0.30.1...HEAD |
| 579 | + [0.30.1]: https://github.com/philss/floki/compare/v0.30.0...v0.30.1 |
| 573 580 | [0.30.0]: https://github.com/philss/floki/compare/v0.29.0...v0.30.0 |
| 574 581 | [0.29.0]: https://github.com/philss/floki/compare/v0.28.0...v0.29.0 |
| 575 582 | [0.28.0]: https://github.com/philss/floki/compare/v0.27.0...v0.28.0 |
| @@ -4,29 +4,31 @@ | |
| 4 4 | <<"Floki is a simple HTML parser that enables search for nodes using CSS selectors.">>}. |
| 5 5 | {<<"elixir">>,<<"~> 1.8">>}. |
| 6 6 | {<<"files">>, |
| 7 | - [<<"lib">>,<<"lib/floki.ex">>,<<"lib/floki">>,<<"lib/floki/html_tree.ex">>, |
| 8 | - <<"lib/floki/html_parser">>,<<"lib/floki/html_parser/html5ever.ex">>, |
| 7 | + [<<"lib">>,<<"lib/floki">>,<<"lib/floki/html_parser.ex">>, |
| 8 | + <<"lib/floki/html_parser">>,<<"lib/floki/html_parser/fast_html.ex">>, |
| 9 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/deep_text.ex">>,<<"lib/floki/flat_text.ex">>, |
| 15 | - <<"lib/floki/finder.ex">>,<<"lib/floki/filter_out.ex">>, |
| 16 | - <<"lib/floki/html_parser.ex">>,<<"lib/floki/selector">>, |
| 17 | - <<"lib/floki/selector/pseudo_class.ex">>, |
| 10 | + <<"lib/floki/html_parser/html5ever.ex">>,<<"lib/floki/selector">>, |
| 11 | + <<"lib/floki/selector/functional.ex">>,<<"lib/floki/selector/parser.ex">>, |
| 18 12 | <<"lib/floki/selector/attribute_selector.ex">>, |
| 19 | - <<"lib/floki/selector/functional.ex">>, |
| 20 | - <<"lib/floki/selector/combinator.ex">>,<<"lib/floki/selector/parser.ex">>, |
| 21 | - <<"lib/floki/selector/tokenizer.ex">>,<<"lib/floki/raw_html.ex">>, |
| 22 | - <<"lib/floki/parse_error.ex">>,<<"src/floki_selector_lexer.xrl">>, |
| 23 | - <<"src/floki_mochi_html.erl">>,<<"src/floki.gleam">>,<<"mix.exs">>, |
| 24 | - <<"README.md">>,<<"LICENSE">>,<<"CODE_OF_CONDUCT.md">>, |
| 25 | - <<"CONTRIBUTING.md">>,<<"CHANGELOG.md">>]}. |
| 13 | + <<"lib/floki/selector/pseudo_class.ex">>, |
| 14 | + <<"lib/floki/selector/tokenizer.ex">>, |
| 15 | + <<"lib/floki/selector/combinator.ex">>,<<"lib/floki/deep_text.ex">>, |
| 16 | + <<"lib/floki/filter_out.ex">>,<<"lib/floki/flat_text.ex">>, |
| 17 | + <<"lib/floki/finder.ex">>,<<"lib/floki/traversal.ex">>, |
| 18 | + <<"lib/floki/raw_html.ex">>,<<"lib/floki/parse_error.ex">>, |
| 19 | + <<"lib/floki/html_tree">>,<<"lib/floki/html_tree/id_seeder.ex">>, |
| 20 | + <<"lib/floki/html_tree/comment.ex">>,<<"lib/floki/html_tree/text.ex">>, |
| 21 | + <<"lib/floki/html_tree/html_node.ex">>,<<"lib/floki/selector.ex">>, |
| 22 | + <<"lib/floki/html_tree.ex">>,<<"lib/floki.ex">>, |
| 23 | + <<"src/floki_selector_lexer.xrl">>,<<"src/floki_mochi_html.erl">>, |
| 24 | + <<"src/floki.gleam">>,<<"mix.exs">>,<<"README.md">>,<<"LICENSE">>, |
| 25 | + <<"CODE_OF_CONDUCT.md">>,<<"CONTRIBUTING.md">>,<<"CHANGELOG.md">>]}. |
| 26 26 | {<<"licenses">>,[<<"MIT">>]}. |
| 27 27 | {<<"links">>, |
| 28 28 | [{<<"Changelog">>,<<"https://hexdocs.pm/floki/changelog.html">>}, |
| 29 | - {<<"GitHub">>,<<"https://github.com/philss/floki">>}]}. |
| 29 | + {<<"GitHub">>,<<"https://github.com/philss/floki">>}, |
| 30 | + {<<"Sponsor">>, |
| 31 | + <<"https://www.paypal.com/donate?business=EMDBKWVHVEB7Q¤cy_code=USD">>}]}. |
| 30 32 | {<<"name">>,<<"floki">>}. |
| 31 33 | {<<"requirements">>, |
| 32 34 | [[{<<"app">>,<<"html_entities">>}, |
| @@ -34,4 +36,4 @@ | |
| 34 36 | {<<"optional">>,false}, |
| 35 37 | {<<"repository">>,<<"hexpm">>}, |
| 36 38 | {<<"requirement">>,<<"~> 0.5.0">>}]]}. |
| 37 | - {<<"version">>,<<"0.30.0">>}. |
| 39 | + {<<"version">>,<<"0.30.1">>}. |
| @@ -67,8 +67,10 @@ defmodule Floki do | |
| 67 67 | @type html_comment :: {:comment, String.t()} |
| 68 68 | @type html_doctype :: {:doctype, String.t(), String.t(), String.t()} |
| 69 69 | @type html_attribute :: {String.t(), String.t()} |
| 70 | - @type html_tag :: {String.t(), [html_attribute()], [html_tag() | String.t() | html_comment()]} |
| 71 | - @type html_node :: html_comment() | html_doctype() | html_tag() | html_declaration() |
| 70 | + @type html_text :: String.t() |
| 71 | + @type html_tag :: {String.t(), [html_attribute()], [html_node()]} |
| 72 | + @type html_node :: |
| 73 | + html_tag() | html_comment() | html_doctype() | html_declaration() | html_text() |
| 72 74 | @type html_tree :: [html_node()] |
| 73 75 | |
| 74 76 | @type css_selector :: String.t() | Floki.Selector.t() | [Floki.Selector.t()] |
| @@ -366,8 +368,9 @@ defmodule Floki do | |
| 366 368 | Traverses and updates a HTML tree structure. |
| 367 369 | |
| 368 370 | This function returns a new tree structure that is the result of applying the |
| 369 | - given `fun` on all nodes. The tree is traversed in a post-walk fashion, where |
| 370 | - the children are traversed before the parent. |
| 371 | + given `fun` on all nodes except text nodes. |
| 372 | + The tree is traversed in a post-walk fashion, where the children are traversed |
| 373 | + before the parent. |
| 371 374 | |
| 372 375 | When the function `fun` encounters HTML tag, it receives a tuple with |
| 373 376 | `{name, attributes, children}`, and should either return a similar tuple or |
| @@ -378,6 +381,9 @@ defmodule Floki do | |
| 378 381 | documentation for `t:html_comment/0`, `t:html_doctype/0` and |
| 379 382 | `t:html_declaration/0` for details. |
| 380 383 | |
| 384 | + **Note**: this won't update text nodes, but you can transform them when working |
| 385 | + with children nodes. |
| 386 | + |
| 381 387 | ## Examples |
| 382 388 | |
| 383 389 | iex> html = [{"div", [], ["hello"]}] |
| @@ -396,7 +402,10 @@ defmodule Floki do | |
| 396 402 | [{"div", [], [{"span", [], "I am comment"}]}] |
| 397 403 | """ |
| 398 404 | |
| 399 | - @spec traverse_and_update(html_tree(), (html_node() -> html_node() | nil)) :: html_tree() |
| 405 | + @spec traverse_and_update( |
| 406 | + html_tree(), |
| 407 | + (html_tag() | html_comment() | html_doctype() | html_declaration() -> html_node() | nil) |
| 408 | + ) :: html_tree() |
| 400 409 | |
| 401 410 | defdelegate traverse_and_update(html_tree, fun), to: Floki.Traversal |
| 402 411 | |
| @@ -404,9 +413,9 @@ defmodule Floki do | |
| 404 413 | Traverses and updates a HTML tree structure with an accumulator. |
| 405 414 | |
| 406 415 | This function returns a new tree structure and the final value of accumulator |
| 407 | - which are the result of applying the given `fun` on all nodes. The tree is |
| 408 | - traversed in a post-walk fashion, where the children are traversed before |
| 409 | - the parent. |
| 416 | + which are the result of applying the given `fun` on all nodes except text nodes. |
| 417 | + The tree is traversed in a post-walk fashion, where the children are traversed |
| 418 | + before the parent. |
| 410 419 | |
| 411 420 | When the function `fun` encounters HTML tag, it receives a tuple with |
| 412 421 | `{name, attributes, children}` and an accumulator. It and should return a |
| @@ -419,6 +428,9 @@ defmodule Floki do | |
| 419 428 | documentation for `t:html_comment/0`, `t:html_doctype/0` and |
| 420 429 | `t:html_declaration/0` for details. |
| 421 430 | |
| 431 | + **Note**: this won't update text nodes, but you can transform them when working |
| 432 | + with children nodes. |
| 433 | + |
| 422 434 | ## Examples |
| 423 435 | |
| 424 436 | iex> html = [{"div", [], [{:comment, "I am a comment"}, "hello"]}, {"div", [], ["world"]}] |
| @@ -445,14 +457,15 @@ defmodule Floki do | |
| 445 457 | @spec traverse_and_update( |
| 446 458 | html_tree(), |
| 447 459 | traverse_acc, |
| 448 | - (html_node(), traverse_acc -> {html_node() | nil, traverse_acc}) |
| 460 | + (html_tag() | html_comment() | html_doctype() | html_declaration(), traverse_acc -> |
| 461 | + {html_node() | nil, traverse_acc}) |
| 449 462 | ) :: {html_node(), traverse_acc} |
| 450 463 | when traverse_acc: any() |
| 451 | - |
| 452 464 | defdelegate traverse_and_update(html_tree, acc, fun), to: Floki.Traversal |
| 453 465 | |
| 454 466 | @doc """ |
| 455 467 | Returns the text nodes from a HTML tree. |
| 468 | + |
| 456 469 | By default, it will perform a deep search through the HTML tree. |
| 457 470 | You can disable deep search with the option `deep` assigned to false. |
| 458 471 | You can include content of script tags with the option `js` assigned to true. |
| @@ -10,9 +10,9 @@ defmodule Floki.Traversal do | |
| 10 10 | def traverse_and_update(html_node, acc, fun) |
| 11 11 | def traverse_and_update([], acc, _fun), do: {[], acc} |
| 12 12 | def traverse_and_update(text, acc, _fun) when is_binary(text), do: {text, acc} |
| 13 | - def traverse_and_update(xml_tag = {:pi, _, _}, acc, fun), do: fun.(xml_tag, acc) |
| 14 | - def traverse_and_update({:comment, children}, acc, fun), do: fun.({:comment, children}, acc) |
| 15 | - def traverse_and_update(doctype = {:doctype, _, _, _}, acc, fun), do: fun.(doctype, acc) |
| 13 | + def traverse_and_update({:pi, _, _} = xml_tag, acc, fun), do: fun.(xml_tag, acc) |
| 14 | + def traverse_and_update({:comment, _children} = comment, acc, fun), do: fun.(comment, acc) |
| 15 | + def traverse_and_update({:doctype, _, _, _} = doctype, acc, fun), do: fun.(doctype, acc) |
| 16 16 | |
| 17 17 | def traverse_and_update([head | tail], acc, fun) do |
| 18 18 | case traverse_and_update(head, acc, fun) do |
| @@ -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.30.0" |
| 6 | + @version "0.30.1" |
| 7 7 | |
| 8 8 | def project do |
| 9 9 | [ |
| @@ -57,7 +57,7 @@ defmodule Floki.Mixfile do | |
| 57 57 | [ |
| 58 58 | {:html_entities, "~> 0.5.0"}, |
| 59 59 | {:earmark, "~> 1.2", only: :dev}, |
| 60 | - {:ex_doc, "~> 0.23.0", only: :dev, runtime: false}, |
| 60 | + {:ex_doc, "~> 0.24.1", only: :dev, runtime: false}, |
| 61 61 | {:benchee, "~> 1.0.1", only: :dev}, |
| 62 62 | {:credo, ">= 0.0.0", only: [:dev, :test]}, |
| 63 63 | {:dialyxir, "~> 1.0", only: [:dev], runtime: false}, |
| @@ -117,6 +117,7 @@ defmodule Floki.Mixfile do | |
| 117 117 | ], |
| 118 118 | links: %{ |
| 119 119 | "Changelog" => "https://hexdocs.pm/floki/changelog.html", |
| 120 | + "Sponsor" => "https://www.paypal.com/donate?business=EMDBKWVHVEB7Q¤cy_code=USD", |
| 120 121 | "GitHub" => @source_url |
| 121 122 | } |
| 122 123 | } |