Packages
floki
0.38.0
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
12
files changed
+514
additions
-376
deletions
| @@ -7,6 +7,53 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. | |
| 7 7 | |
| 8 8 | ## [Unreleased][unreleased] |
| 9 9 | |
| 10 | + ## [0.38.0] - 2025-06-14 |
| 11 | + |
| 12 | + ### Added |
| 13 | + |
| 14 | + - This version adds initial support for the `:has` pseudo-selector. |
| 15 | + It is a great addition that enables finding elements containing |
| 16 | + matching children. |
| 17 | + |
| 18 | + Examples for selectors: |
| 19 | + |
| 20 | + * `"div:has(h1)"` |
| 21 | + * `"div:has(h1, p, span)"` |
| 22 | + * `"div:has(p.foo)"` |
| 23 | + * `"div:has(img[src='https://example.com'])"` |
| 24 | + * `"tr:has(*:fl-contains('TEST'))"` |
| 25 | + |
| 26 | + Note that combinators like `">"` are not allowed yet. |
| 27 | + |
| 28 | + Thank you [@bvobart](https://github.com/bvobart) for this feature! |
| 29 | + |
| 30 | + ### Fixed |
| 31 | + |
| 32 | + - Add `:style` option documentation to `Floki.text/2`. |
| 33 | + Thanks [@s3cur3](https://github.com/s3cur3) for the fix. |
| 34 | + |
| 35 | + - Fix deprecation warnings for upcoming Elixir 1.19. |
| 36 | + |
| 37 | + - Prevent from crashing when selector is an empty string. |
| 38 | + |
| 39 | + ### Removed |
| 40 | + |
| 41 | + - Remove support for Elixir 1.14 and OTP 23. |
| 42 | + |
| 43 | + - Remove deprecated functions and function clauses |
| 44 | + that were accepting strings (binaries). |
| 45 | + |
| 46 | + Affected functions: |
| 47 | + |
| 48 | + * `parse/1` - removed function |
| 49 | + * `map/2` - removed function |
| 50 | + * `attr/4` - removed clause |
| 51 | + * `find/2` - removed clause |
| 52 | + * `text/3` - removed clause |
| 53 | + * `text/3` - removed clause |
| 54 | + * `attribute/2` - removed clause |
| 55 | + * `filter_out/2` - removed clause |
| 56 | + |
| 10 57 | ## [0.37.1] - 2025-03-22 |
| 11 58 | |
| 12 59 | ### Fixed |
| @@ -820,7 +867,8 @@ of the parent element inside HTML. | |
| 820 867 | |
| 821 868 | - Elixir version requirement from "~> 1.0.0" to ">= 1.0.0". |
| 822 869 | |
| 823 | - [unreleased]: https://github.com/philss/floki/compare/v0.37.1...HEAD |
| 870 | + [unreleased]: https://github.com/philss/floki/compare/v0.38.0...HEAD |
| 871 | + [0.38.0]: https://github.com/philss/floki/compare/v0.37.1...v0.38.0 |
| 824 872 | [0.37.1]: https://github.com/philss/floki/compare/v0.37.0...v0.37.1 |
| 825 873 | [0.37.0]: https://github.com/philss/floki/compare/v0.36.3...v0.37.0 |
| 826 874 | [0.36.3]: https://github.com/philss/floki/compare/v0.36.2...v0.36.3 |
| @@ -16,17 +16,17 @@ | |
| 16 16 | Take this HTML as an example: |
| 17 17 | |
| 18 18 | ```html |
| 19 | - <!doctype html> |
| 19 | + <!DOCTYPE html> |
| 20 20 | <html> |
| 21 | - <body> |
| 22 | - <section id="content"> |
| 23 | - <p class="headline">Floki</p> |
| 24 | - <span class="headline">Enables search using CSS selectors</span> |
| 25 | - <a href="https://github.com/philss/floki">Github page</a> |
| 26 | - <span data-model="user">philss</span> |
| 27 | - </section> |
| 28 | - <a href="https://hex.pm/packages/floki">Hex package</a> |
| 29 | - </body> |
| 21 | + <body> |
| 22 | + <section id="content"> |
| 23 | + <p class="headline">Floki</p> |
| 24 | + <span class="headline">Enables search using CSS selectors</span> |
| 25 | + <a href="https://github.com/philss/floki">Github page</a> |
| 26 | + <span data-model="user">philss</span> |
| 27 | + </section> |
| 28 | + <a href="https://hex.pm/packages/floki">Hex package</a> |
| 29 | + </body> |
| 30 30 | </html> |
| 31 31 | ``` |
| 32 32 | |
| @@ -40,7 +40,7 @@ Floki.find(document, "p.headline") | |
| 40 40 | |
| 41 41 | document |
| 42 42 | |> Floki.find("p.headline") |
| 43 | - |> Floki.raw_html |
| 43 | + |> Floki.raw_html() |
| 44 44 | # => <p class="headline">Floki</p> |
| 45 45 | ``` |
| 46 46 | |
| @@ -61,7 +61,7 @@ Add Floki to your `mix.exs`: | |
| 61 61 | ```elixir |
| 62 62 | defp deps do |
| 63 63 | [ |
| 64 | - {:floki, "~> 0.37.0"} |
| 64 | + {:floki, "~> 0.38.0"} |
| 65 65 | ] |
| 66 66 | end |
| 67 67 | ``` |
| @@ -72,7 +72,7 @@ If you are running on [Livebook](https://livebook.dev) or a script, you can inst | |
| 72 72 | |
| 73 73 | ```elixir |
| 74 74 | Mix.install([ |
| 75 | - {:floki, "~> 0.37.0"} |
| 75 | + {:floki, "~> 0.38.0"} |
| 76 76 | ]) |
| 77 77 | ``` |
| 78 78 | |
| @@ -128,8 +128,8 @@ you don't need to install anything to compile it thanks to [RustlerPrecompiled]( | |
| 128 128 | ```elixir |
| 129 129 | defp deps do |
| 130 130 | [ |
| 131 | - {:floki, "~> 0.37.0"}, |
| 132 | - {:html5ever, "~> 0.15.0"} |
| 131 | + {:floki, "~> 0.38.0"}, |
| 132 | + {:html5ever, "~> 0.16.0"} |
| 133 133 | ] |
| 134 134 | end |
| 135 135 | ``` |
| @@ -156,7 +156,7 @@ First, add `fast_html` to your dependencies: | |
| 156 156 | ```elixir |
| 157 157 | defp deps do |
| 158 158 | [ |
| 159 | - {:floki, "~> 0.37.0"}, |
| 159 | + {:floki, "~> 0.38.0"}, |
| 160 160 | {:fast_html, "~> 2.0"} |
| 161 161 | ] |
| 162 162 | end |
| @@ -201,7 +201,7 @@ To convert your node tree back to raw HTML (spaces are ignored): | |
| 201 201 | ```elixir |
| 202 202 | document |
| 203 203 | |> Floki.find(".example") |
| 204 | - |> Floki.raw_html |
| 204 | + |> Floki.raw_html() |
| 205 205 | # => <div class="example"></div> |
| 206 206 | ``` |
| 207 207 | |
| @@ -226,7 +226,7 @@ If you want to get the text from an element, try: | |
| 226 226 | ```elixir |
| 227 227 | document |
| 228 228 | |> Floki.find(".headline") |
| 229 | - |> Floki.text |
| 229 | + |> Floki.text() |
| 230 230 | |
| 231 231 | # => "Floki" |
| 232 232 | ``` |
| @@ -235,43 +235,50 @@ document | |
| 235 235 | |
| 236 236 | Here you find all the [CSS selectors](https://www.w3.org/TR/selectors/#selectors) supported in the current version: |
| 237 237 | |
| 238 | - | Pattern | Description | |
| 239 | - |-----------------|------------------------------| |
| 240 | - | * | any element | |
| 241 | - | E | an element of type `E` | |
| 242 | - | E[foo] | an `E` element with a "foo" attribute | |
| 243 | - | E[foo="bar"] | an E element whose "foo" attribute value is exactly equal to "bar" | |
| 244 | - | E[foo~="bar"] | an E element whose "foo" attribute value is a list of whitespace-separated values, one of which is exactly equal to "bar" | |
| 245 | - | E[foo^="bar"] | an E element whose "foo" attribute value begins exactly with the string "bar" | |
| 246 | - | E[foo$="bar"] | an E element whose "foo" attribute value ends exactly with the string "bar" | |
| 247 | - | E[foo*="bar"] | an E element whose "foo" attribute value contains the substring "bar" | |
| 248 | - | E[foo\|="en"] | an E element whose "foo" attribute has a hyphen-separated list of values beginning (from the left) with "en" | |
| 249 | - | E:nth-child(n) | an E element, the n-th child of its parent | |
| 250 | - | E:nth-last-child(n) | an E element, the n-th child of its parent, counting from bottom to up | |
| 251 | - | E:first-child | an E element, first child of its parent | |
| 252 | - | E:last-child | an E element, last child of its parent | |
| 253 | - | E:nth-of-type(n) | an E element, the n-th child of its type among its siblings | |
| 254 | - | E:nth-last-of-type(n) | an E element, the n-th child of its type among its siblings, counting from bottom to up | |
| 255 | - | E:first-of-type | an E element, first child of its type among its siblings | |
| 256 | - | E:last-of-type | an E element, last child of its type among its siblings | |
| 257 | - | E:checked | An E element (checkbox, radio, or option) that is checked | |
| 258 | - | E:disabled | An E element (button, input, select, textarea, or option) that is disabled | |
| 259 | - | E.warning | an E element whose class is "warning" | |
| 260 | - | E#myid | an E element with ID equal to "myid" (for ids containing periods, use `#my\\.id` or `[id="my.id"]`) | |
| 261 | - | E:not(s) | an E element that does not match simple selector s | |
| 262 | - | :root | the root node or nodes (in case of fragments) of the document. Most of the times this is the `html` tag | |
| 263 | - | E F | an F element descendant of an E element | |
| 264 | - | E > F | an F element child of an E element | |
| 265 | - | E + F | an F element immediately preceded by an E element | |
| 266 | - | E ~ F | an F element preceded by an E element | |
| 238 | + | Pattern | Description | |
| 239 | + | --------------------- | ------------------------------------------------------------------------------------------------------------------------- | |
| 240 | + | \* | any element | |
| 241 | + | E | an element of type `E` | |
| 242 | + | E[foo] | an `E` element with a "foo" attribute | |
| 243 | + | E[foo="bar"] | an E element whose "foo" attribute value is exactly equal to "bar" | |
| 244 | + | E[foo~="bar"] | an E element whose "foo" attribute value is a list of whitespace-separated values, one of which is exactly equal to "bar" | |
| 245 | + | E[foo^="bar"] | an E element whose "foo" attribute value begins exactly with the string "bar" | |
| 246 | + | E[foo$="bar"] | an E element whose "foo" attribute value ends exactly with the string "bar" | |
| 247 | + | E[foo*="bar"] | an E element whose "foo" attribute value contains the substring "bar" | |
| 248 | + | E[foo\|="en"] | an E element whose "foo" attribute has a hyphen-separated list of values beginning (from the left) with "en" | |
| 249 | + | E:nth-child(n) | an E element, the n-th child of its parent | |
| 250 | + | E:nth-last-child(n) | an E element, the n-th child of its parent, counting from bottom to up | |
| 251 | + | E:first-child | an E element, first child of its parent | |
| 252 | + | E:last-child | an E element, last child of its parent | |
| 253 | + | E:nth-of-type(n) | an E element, the n-th child of its type among its siblings | |
| 254 | + | E:nth-last-of-type(n) | an E element, the n-th child of its type among its siblings, counting from bottom to up | |
| 255 | + | E:first-of-type | an E element, first child of its type among its siblings | |
| 256 | + | E:last-of-type | an E element, last child of its type among its siblings | |
| 257 | + | E:checked | An E element (checkbox, radio, or option) that is checked | |
| 258 | + | E:disabled | An E element (button, input, select, textarea, or option) that is disabled | |
| 259 | + | E.warning | an E element whose class is "warning" | |
| 260 | + | E#myid | an E element with ID equal to "myid" (for ids containing periods, use `#my\\.id` or `[id="my.id"]`) | |
| 261 | + | E:not(s) | an E element that does not match simple selector s | |
| 262 | + | E:has(s) | an E element that has a child element that matches simple selector s | |
| 263 | + | E:has(s1, s2) | an E element that has a child element matching simple selector s1 OR s2 | |
| 264 | + | E:has(s1):has(s2) | An E element that has a child element matching simple selectors s1 AND s2 | |
| 265 | + | :root | the root node or nodes (in case of fragments) of the document. Most of the times this is the `html` tag | |
| 266 | + | E F | an F element descendant of an E element | |
| 267 | + | E > F | an F element child of an E element | |
| 268 | + | E + F | an F element immediately preceded by an E element | |
| 269 | + | E ~ F | an F element preceded by an E element | |
| 267 270 | |
| 268 271 | There are also some selectors based on non-standard specifications. They are: |
| 269 272 | |
| 270 273 | | Pattern | Description | |
| 271 | - |-----------------------|------------------------------------------------------------------------| |
| 274 | + | --------------------- | ---------------------------------------------------------------------- | |
| 272 275 | | E:fl-contains('foo') | an E element that contains "foo" inside a text node | |
| 273 276 | | E:fl-icontains('foo') | an E element that contains "foo" inside a text node (case insensitive) | |
| 274 277 | |
| 278 | + ### Simple selectors |
| 279 | + |
| 280 | + The pseudo-selectors `:has` and `:not` currently only support simple selectors. Simple selectors are all of the selectors except those that take another selector as an argument, so anything except `:not`, `:has`, `>`, `+` and `~`. |
| 281 | + |
| 275 282 | ## Suppressing log messages |
| 276 283 | |
| 277 284 | Floki may log debug messages related to problems in the parsing of selectors, or parsing of the HTML tree. |
| @@ -282,7 +289,7 @@ See https://hexdocs.pm/logger/Logger.html#module-compile-configuration for detai | |
| 282 289 | |
| 283 290 | ## Special thanks |
| 284 291 | |
| 285 | - * [@arasatasaygin](https://github.com/arasatasaygin) for Floki's logo from the [Open Logos project](http://openlogos.org/). |
| 292 | + - [@arasatasaygin](https://github.com/arasatasaygin) for Floki's logo from the [Open Logos project](http://openlogos.org/). |
| 286 293 | |
| 287 294 | ## License |
| @@ -3,10 +3,10 @@ | |
| 3 3 | {<<"GitHub">>,<<"https://github.com/philss/floki">>}, |
| 4 4 | {<<"Sponsor">>,<<"https://github.com/sponsors/philss">>}]}. |
| 5 5 | {<<"name">>,<<"floki">>}. |
| 6 | - {<<"version">>,<<"0.37.1">>}. |
| 6 | + {<<"version">>,<<"0.38.0">>}. |
| 7 7 | {<<"description">>, |
| 8 8 | <<"Floki is a simple HTML parser that enables search for nodes using CSS selectors.">>}. |
| 9 | - {<<"elixir">>,<<"~> 1.14">>}. |
| 9 | + {<<"elixir">>,<<"~> 1.15">>}. |
| 10 10 | {<<"app">>,<<"floki">>}. |
| 11 11 | {<<"licenses">>,[<<"MIT">>]}. |
| 12 12 | {<<"files">>, |
| @@ -1,8 +1,6 @@ | |
| 1 1 | defmodule Floki do |
| 2 2 | alias Floki.{Finder, FilterOut, HTMLTree} |
| 3 3 | |
| 4 | - require Logger |
| 5 | - |
| 6 4 | @moduledoc """ |
| 7 5 | Floki is a simple HTML parser that enables search for nodes using CSS selectors. |
| 8 6 | |
| @@ -82,26 +80,6 @@ defmodule Floki do | |
| 82 80 | (tuple_size(value) == 2 and elem(value, 0) in [:pi, :comment]) or |
| 83 81 | (tuple_size(value) == 4 and elem(value, 0) == :doctype) |
| 84 82 | |
| 85 | - @doc """ |
| 86 | - Parses a HTML Document from a String. |
| 87 | - |
| 88 | - The expect string is a valid HTML, but the parser will try |
| 89 | - to parse even with errors. |
| 90 | - """ |
| 91 | - |
| 92 | - @spec parse(binary()) :: html_tag() | html_tree() | String.t() |
| 93 | - |
| 94 | - @deprecated "Use `parse_document/1` or `parse_fragment/1` instead." |
| 95 | - def parse(html) do |
| 96 | - with {:ok, document} <- Floki.HTMLParser.parse_document(html) do |
| 97 | - if length(document) == 1 do |
| 98 | - hd(document) |
| 99 | - else |
| 100 | - document |
| 101 | - end |
| 102 | - end |
| 103 | - end |
| 104 | - |
| 105 83 | @doc """ |
| 106 84 | Parses an HTML document from a string. |
| 107 85 | |
| @@ -272,18 +250,7 @@ defmodule Floki do | |
| 272 250 | [{"a", [{"href", "https://google.com"}], ["Google"]}] |
| 273 251 | |
| 274 252 | """ |
| 275 | - |
| 276 | - @spec find(binary() | html_tree() | html_node(), css_selector()) :: html_tree |
| 277 | - def find(html, selector) when is_binary(html) do |
| 278 | - Logger.info( |
| 279 | - "deprecation: parse the HTML with parse_document or parse_fragment before using find/2" |
| 280 | - ) |
| 281 | - |
| 282 | - with {:ok, document} <- Floki.parse_document(html) do |
| 283 | - Finder.find(document, selector) |
| 284 | - end |
| 285 | - end |
| 286 | - |
| 253 | + @spec find(html_tree() | html_node(), css_selector()) :: html_tree() |
| 287 254 | def find(html_tree_as_tuple, selector) |
| 288 255 | when is_list(html_tree_as_tuple) or is_html_node(html_tree_as_tuple) do |
| 289 256 | Finder.find(html_tree_as_tuple, selector) |
| @@ -323,23 +290,11 @@ defmodule Floki do | |
| 323 290 | [{"div", [{"id", "b"}, {"class", "name"}], []}] |
| 324 291 | |
| 325 292 | """ |
| 326 | - @spec attr(binary | html_tree | html_node, css_selector(), binary, (binary -> binary)) :: |
| 327 | - html_tree |
| 328 | - |
| 293 | + @spec attr(html_tree() | html_node(), css_selector(), binary, (binary -> binary)) :: html_tree() |
| 329 294 | def attr(html_elem_tuple, selector, attribute_name, mutation) when is_tuple(html_elem_tuple) do |
| 330 295 | attr([html_elem_tuple], selector, attribute_name, mutation) |
| 331 296 | end |
| 332 297 | |
| 333 | - def attr(html, selector, attribute_name, mutation) when is_binary(html) do |
| 334 | - Logger.info( |
| 335 | - "deprecation: parse the HTML with parse_document or parse_fragment before using attr/4" |
| 336 | - ) |
| 337 | - |
| 338 | - with {:ok, document} <- Floki.parse_document(html) do |
| 339 | - attr(document, selector, attribute_name, mutation) |
| 340 | - end |
| 341 | - end |
| 342 | - |
| 343 298 | def attr(html_tree_list, selector, attribute_name, mutation) when is_list(html_tree_list) do |
| 344 299 | find_and_update(html_tree_list, selector, fn |
| 345 300 | {tag, attrs} -> |
| @@ -364,17 +319,6 @@ defmodule Floki do | |
| 364 319 | end) |
| 365 320 | end |
| 366 321 | |
| 367 | - @deprecated """ |
| 368 | - Use `find_and_update/3` or `Enum.map/2` instead. |
| 369 | - """ |
| 370 | - def map(_html_tree_or_list, _fun) |
| 371 | - |
| 372 | - def map(html_tree_list, fun) when is_list(html_tree_list) do |
| 373 | - Enum.map(html_tree_list, &Finder.map(&1, fun)) |
| 374 | - end |
| 375 | - |
| 376 | - def map(html_tree, fun), do: Finder.map(html_tree, fun) |
| 377 | - |
| 378 322 | @doc """ |
| 379 323 | Searches for elements inside the HTML tree and update those that matches the selector. |
| 380 324 | |
| @@ -529,7 +473,8 @@ defmodule Floki do | |
| 529 473 | |
| 530 474 | By default, it will perform a deep search through the HTML tree. |
| 531 475 | You can disable deep search with the option `deep` assigned to false. |
| 532 | - You can include content of script tags with the option `js` assigned to true. |
| 476 | + You can include content of script or style tags by setting the `:js` or |
| 477 | + `:style` flags, respectively, to true. |
| 533 478 | You can specify a separator between nodes content. |
| 534 479 | |
| 535 480 | ## Options |
| @@ -539,7 +484,10 @@ defmodule Floki do | |
| 539 484 | or the first level of the HTML document is going to be considered. |
| 540 485 | Defaults to `true`. |
| 541 486 | |
| 542 | - * `:js` - A boolean option to control if the contents of script tags |
| 487 | + * `:js` - A boolean option to control if the contents of `<script>` tags |
| 488 | + should be considered as text. Defaults to `false`. |
| 489 | + |
| 490 | + * `:style` - A boolean to control if the contents of `<style>` tags |
| 543 491 | should be considered as text. Defaults to `false`. |
| 544 492 | |
| 545 493 | * `:sep` - A separator string that is added between text nodes. |
| @@ -586,7 +534,7 @@ defmodule Floki do | |
| 586 534 | |
| 587 535 | """ |
| 588 536 | |
| 589 | - @spec text(html_tree | html_node | binary, Keyword.t()) :: binary |
| 537 | + @spec text(html_tree() | html_node(), Keyword.t()) :: binary() |
| 590 538 | |
| 591 539 | def text(html, opts \\ []) do |
| 592 540 | defaults = [deep: true, js: false, style: true, sep: "", include_inputs: false] |
| @@ -595,7 +543,6 @@ defmodule Floki do | |
| 595 543 | |
| 596 544 | cleaned_html_tree = |
| 597 545 | html |
| 598 | - |> maybe_parse_it() |
| 599 546 | |> clean_html_tree(:js, opts[:js]) |
| 600 547 | |> clean_html_tree(:style, opts[:style]) |
| 601 548 | |
| @@ -687,17 +634,7 @@ defmodule Floki do | |
| 687 634 | ["google"] |
| 688 635 | """ |
| 689 636 | |
| 690 | - @spec attribute(binary | html_tree | html_node, binary) :: list |
| 691 | - def attribute(html, attribute_name) when is_binary(html) do |
| 692 | - Logger.info( |
| 693 | - "deprecation: parse the HTML with parse_document or parse_fragment before using attribute/2" |
| 694 | - ) |
| 695 | - |
| 696 | - with {:ok, document} <- Floki.parse_document(html) do |
| 697 | - attribute_values(document, attribute_name) |
| 698 | - end |
| 699 | - end |
| 700 | - |
| 637 | + @spec attribute(html_tree() | html_node(), binary()) :: list(binary()) |
| 701 638 | def attribute(elements, attribute_name) do |
| 702 639 | attribute_values(elements, attribute_name) |
| 703 640 | end |
| @@ -738,17 +675,6 @@ defmodule Floki do | |
| 738 675 | ) |
| 739 676 | end |
| 740 677 | |
| 741 | - defp maybe_parse_it(html) when is_binary(html) do |
| 742 | - Logger.info( |
| 743 | - "deprecation: parse the HTML with parse_document or parse_fragment before using text/2" |
| 744 | - ) |
| 745 | - |
| 746 | - {:ok, document} = Floki.parse_document(html) |
| 747 | - document |
| 748 | - end |
| 749 | - |
| 750 | - defp maybe_parse_it(html), do: html |
| 751 | - |
| 752 678 | defp clean_html_tree(html_tree, :js, true), do: html_tree |
| 753 679 | defp clean_html_tree(html_tree, :js, _), do: filter_out(html_tree, "script") |
| 754 680 | |
| @@ -774,19 +700,8 @@ defmodule Floki do | |
| 774 700 | |
| 775 701 | """ |
| 776 702 | |
| 777 | - @spec filter_out(html_node() | html_tree() | binary(), :comment | :text | css_selector()) :: |
| 703 | + @spec filter_out(html_node() | html_tree(), :comment | :text | css_selector()) :: |
| 778 704 | html_node() | html_tree() |
| 779 | - |
| 780 | - def filter_out(html, selector) when is_binary(html) do |
| 781 | - Logger.info( |
| 782 | - "deprecation: parse the HTML with parse_document or parse_fragment before using filter_out/2" |
| 783 | - ) |
| 784 | - |
| 785 | - with {:ok, document} <- Floki.parse_document(html) do |
| 786 | - FilterOut.filter_out(document, selector) |
| 787 | - end |
| 788 | - end |
| 789 | - |
| 790 705 | def filter_out(elements, selector) do |
| 791 706 | FilterOut.filter_out(elements, selector) |
| 792 707 | end |
| @@ -42,10 +42,15 @@ defmodule Floki.Finder do | |
| 42 42 | |
| 43 43 | def find(html_tree, selector_as_string) when is_binary(selector_as_string) do |
| 44 44 | selectors = Selector.Parser.parse(selector_as_string) |
| 45 | - find(html_tree, selectors) |
| 45 | + |
| 46 | + if selectors != [] do |
| 47 | + find(html_tree, selectors) |
| 48 | + else |
| 49 | + [] |
| 50 | + end |
| 46 51 | end |
| 47 52 | |
| 48 | - def find(html_tree, selector = %Selector{}) do |
| 53 | + def find(html_tree, %Selector{} = selector) do |
| 49 54 | find(html_tree, [selector]) |
| 50 55 | end |
Loading more files…