Skip to content

Commit

Permalink
Improve docs and typespecs about traverse_and_update
Browse files Browse the repository at this point in the history
The intention is to make clear that we don't allow the function to
update text nodes, but the user can update text nodes inside children.

This closes #338
  • Loading branch information
philss committed Mar 8, 2021
1 parent 484565c commit fd88a28
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 13 deletions.
33 changes: 23 additions & 10 deletions lib/floki.ex
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ defmodule Floki do
@type html_comment :: {:comment, String.t()}
@type html_doctype :: {:doctype, String.t(), String.t(), String.t()}
@type html_attribute :: {String.t(), String.t()}
@type html_tag :: {String.t(), [html_attribute()], [html_tag() | String.t() | html_comment()]}
@type html_node :: html_comment() | html_doctype() | html_tag() | html_declaration()
@type html_text :: String.t()
@type html_tag :: {String.t(), [html_attribute()], [html_node()]}
@type html_node ::
html_tag() | html_comment() | html_doctype() | html_declaration() | html_text()
@type html_tree :: [html_node()]

@type css_selector :: String.t() | Floki.Selector.t() | [Floki.Selector.t()]
Expand Down Expand Up @@ -366,8 +368,9 @@ defmodule Floki do
Traverses and updates a HTML tree structure.
This function returns a new tree structure that is the result of applying the
given `fun` on all nodes. The tree is traversed in a post-walk fashion, where
the children are traversed before the parent.
given `fun` on all nodes except text nodes.
The tree is traversed in a post-walk fashion, where the children are traversed
before the parent.
When the function `fun` encounters HTML tag, it receives a tuple with
`{name, attributes, children}`, and should either return a similar tuple or
Expand All @@ -378,6 +381,9 @@ defmodule Floki do
documentation for `t:html_comment/0`, `t:html_doctype/0` and
`t:html_declaration/0` for details.
**Note**: this won't update text nodes, but you can transform them when working
with children nodes.
## Examples
iex> html = [{"div", [], ["hello"]}]
Expand All @@ -396,17 +402,20 @@ defmodule Floki do
[{"div", [], [{"span", [], "I am comment"}]}]
"""

@spec traverse_and_update(html_tree(), (html_node() -> html_node() | nil)) :: html_tree()
@spec traverse_and_update(
html_tree(),
(html_tag() | html_comment() | html_doctype() | html_declaration() -> html_node() | nil)
) :: html_tree()

defdelegate traverse_and_update(html_tree, fun), to: Floki.Traversal

@doc """
Traverses and updates a HTML tree structure with an accumulator.
This function returns a new tree structure and the final value of accumulator
which are the result of applying the given `fun` on all nodes. The tree is
traversed in a post-walk fashion, where the children are traversed before
the parent.
which are the result of applying the given `fun` on all nodes except text nodes.
The tree is traversed in a post-walk fashion, where the children are traversed
before the parent.
When the function `fun` encounters HTML tag, it receives a tuple with
`{name, attributes, children}` and an accumulator. It and should return a
Expand All @@ -419,6 +428,9 @@ defmodule Floki do
documentation for `t:html_comment/0`, `t:html_doctype/0` and
`t:html_declaration/0` for details.
**Note**: this won't update text nodes, but you can transform them when working
with children nodes.
## Examples
iex> html = [{"div", [], [{:comment, "I am a comment"}, "hello"]}, {"div", [], ["world"]}]
Expand All @@ -445,14 +457,15 @@ defmodule Floki do
@spec traverse_and_update(
html_tree(),
traverse_acc,
(html_node(), traverse_acc -> {html_node() | nil, traverse_acc})
(html_tag() | html_comment() | html_doctype() | html_declaration(), traverse_acc ->
{html_node() | nil, traverse_acc})
) :: {html_node(), traverse_acc}
when traverse_acc: any()

defdelegate traverse_and_update(html_tree, acc, fun), to: Floki.Traversal

@doc """
Returns the text nodes from a HTML tree.
By default, it will perform a deep search through the HTML tree.
You can disable deep search with the option `deep` assigned to false.
You can include content of script tags with the option `js` assigned to true.
Expand Down
6 changes: 3 additions & 3 deletions lib/floki/traversal.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ defmodule Floki.Traversal do
def traverse_and_update(html_node, acc, fun)
def traverse_and_update([], acc, _fun), do: {[], acc}
def traverse_and_update(text, acc, _fun) when is_binary(text), do: {text, acc}
def traverse_and_update(xml_tag = {:pi, _, _}, acc, fun), do: fun.(xml_tag, acc)
def traverse_and_update({:comment, children}, acc, fun), do: fun.({:comment, children}, acc)
def traverse_and_update(doctype = {:doctype, _, _, _}, acc, fun), do: fun.(doctype, acc)
def traverse_and_update({:pi, _, _} = xml_tag, acc, fun), do: fun.(xml_tag, acc)
def traverse_and_update({:comment, _children} = comment, acc, fun), do: fun.(comment, acc)
def traverse_and_update({:doctype, _, _, _} = doctype, acc, fun), do: fun.(doctype, acc)

def traverse_and_update([head | tail], acc, fun) do
case traverse_and_update(head, acc, fun) do
Expand Down

0 comments on commit fd88a28

Please sign in to comment.