Skip to content

Commit

Permalink
Add Floki.get_by_id/2 (#548)
Browse files Browse the repository at this point in the history
  • Loading branch information
SteffenDE committed Mar 1, 2024
1 parent 8709bd7 commit bceb0e7
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 0 deletions.
26 changes: 26 additions & 0 deletions lib/floki.ex
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,32 @@ defmodule Floki do
Finder.find(html_tree_as_tuple, selector)
end

@doc """
Finds the first element in an HTML tree by id.
Returns `nil` if no element is found.
This is useful when there are IDs that contain special characters that
are invalid when passed as is as a CSS selector.
It is similar to the `getElementById` method in the browser.
## Examples
iex> {:ok, html} = Floki.parse_fragment(~s[<p><span class="hint" id="id?foo_special:chars">hello</span></p>])
iex> Floki.get_by_id(html, "id?foo_special:chars")
{"span", [{"class", "hint"}, {"id", "id?foo_special:chars"}], ["hello"]}
iex> Floki.get_by_id(html, "does-not-exist")
nil
"""
@spec get_by_id(html_tree() | html_node(), String.t()) :: html_tree
def get_by_id(html_tree_as_tuple, id)
when is_list(html_tree_as_tuple) or is_html_node(html_tree_as_tuple) do
html_tree_as_tuple
|> Finder.find(%Floki.Selector{id: id})
|> List.first()
end

@doc """
Changes the attribute values of the elements matched by `selector`
with the function `mutation` and returns the whole element tree.
Expand Down
16 changes: 16 additions & 0 deletions test/floki_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -1594,6 +1594,22 @@ defmodule FlokiTest do
Floki.Finder.find(html_tree, [selector_struct_1, selector_struct_2])
end

# Floki.get_by_id/2

test "get_by_id finds element with special characters" do
html =
document!(
html_body(~s"""
<div id="my-id?with_special!char:acters">Hello</div>
""")
)

assert {"div", [{"id", "my-id?with_special!char:acters"}], ["Hello"]} =
Floki.get_by_id(html, "my-id?with_special!char:acters")

refute Floki.get_by_id(html, "doesn't exist")
end

# Floki.children/2

test "returns the children elements of an element including the text" do
Expand Down

0 comments on commit bceb0e7

Please sign in to comment.