Current section

86 Versions

Jump to

Compare versions

6 files changed
+62 additions
-29 deletions
  @@ -3,6 +3,7 @@
3 3 [![Build status](https://travis-ci.org/philss/floki.svg?branch=master)](https://travis-ci.org/philss/floki)
4 4 [![Floki version](https://img.shields.io/hexpm/v/floki.svg)](https://hex.pm/packages/floki)
5 5 [![Hex.pm](https://img.shields.io/hexpm/dt/floki.svg)](https://hex.pm/packages/floki)
6 + [![Deps Status](https://beta.hexfaktor.org/badge/all/github/philss/floki.svg)](https://beta.hexfaktor.org/github/philss/floki)
6 7 [![Inline docs](http://inch-ci.org/github/philss/floki.svg?branch=master)](http://inch-ci.org/github/philss/floki)
7 8
8 9 Floki is a simple HTML parser that enables search for nodes using CSS selectors.
  @@ -18,8 +18,8 @@
18 18 {<<"maintainers">>,[<<"Philip Sampaio Silva">>]}.
19 19 {<<"name">>,<<"floki">>}.
20 20 {<<"requirements">>,
21 - [{<<"mochiweb_html">>,
22 - [{<<"app">>,<<"mochiweb_html">>},
23 - {<<"optional">>,false},
24 - {<<"requirement">>,<<"~> 2.15">>}]}]}.
25 - {<<"version">>,<<"0.8.1">>}.
21 + [[{<<"app">>,<<"mochiweb_html">>},
22 + {<<"name">>,<<"mochiweb_html">>},
23 + {<<"optional">>,false},
24 + {<<"requirement">>,<<"~> 2.15">>}]]}.
25 + {<<"version">>,<<"0.9.0">>}.
  @@ -135,6 +135,9 @@ defmodule Floki do
135 135 iex> Floki.find("<p><a href='https://google.com'>Google</a></p>", "a")
136 136 [{"a", [{"href", "https://google.com"}], ["Google"]}]
137 137
138 + iex> Floki.find([{ "div", [], [{"a", [{"href", "https://google.com"}], ["Google"]}]}], "div a")
139 + [{"a", [{"href", "https://google.com"}], ["Google"]}]
140 +
138 141 """
139 142
140 143 @spec find(binary | html_tree, binary) :: html_tree
  @@ -151,6 +154,7 @@ defmodule Floki do
151 154 By default, it will perform a deep search through the HTML tree.
152 155 You can disable deep search with the option `deep` assigned to false.
153 156 You can include content of script tags with the option `js` assigned to true.
157 + You can specify a separator between nodes content.
154 158
155 159 ## Examples
156 160
  @@ -166,11 +170,17 @@ defmodule Floki do
166 170 iex> Floki.text("<div><script>hello</script> world</div>", js: true)
167 171 "hello world"
168 172
173 + iex> Floki.text("<ul><li>hello</li><li>world</li></ul>", sep: " ")
174 + "hello world"
175 +
176 + iex> Floki.text([{"div", [], ["hello world"]}])
177 + "hello world"
178 +
169 179 """
170 180
171 181 @spec text(html_tree | binary) :: binary
172 182
173 - def text(html, opts \\ [deep: true, js: false]) do
183 + def text(html, opts \\ [deep: true, js: false, sep: ""]) do
174 184 html_tree =
175 185 if is_binary(html) do
176 186 parse(html)
  @@ -190,7 +200,11 @@ defmodule Floki do
190 200 _ -> Floki.DeepText
191 201 end
192 202
193 - search_strategy.get(cleaned_html_tree)
203 + case opts[:sep] do
204 + nil -> search_strategy.get(cleaned_html_tree)
205 + sep -> search_strategy.get(cleaned_html_tree, sep)
206 + end
207 +
194 208 end
195 209
196 210 @doc """
  @@ -201,6 +215,9 @@ defmodule Floki do
201 215 iex> Floki.attribute("<a href='https://google.com'>Google</a>", "a", "href")
202 216 ["https://google.com"]
203 217
218 + iex> Floki.attribute([{"a", [{"href", "https://google.com"}], ["Google"]}], "a", "href")
219 + ["https://google.com"]
220 +
204 221 """
205 222
206 223 @spec attribute(binary | html_tree, binary, binary) :: list
  @@ -219,6 +236,9 @@ defmodule Floki do
219 236 iex> Floki.attribute("<a href=https://google.com>Google</a>", "href")
220 237 ["https://google.com"]
221 238
239 + iex> Floki.attribute([{"a", [{"href", "https://google.com"}], ["Google"]}], "href")
240 + ["https://google.com"]
241 +
222 242 """
223 243
224 244 @spec attribute(binary | html_tree, binary) :: list
  @@ -6,7 +6,7 @@ defmodule Floki.DeepText do
6 6
7 7 @type html_tree :: tuple | list
8 8
9 - @spec get(html_tree) :: binary
9 + @spec get(html_tree, binary) :: binary
10 10
11 11 @doc """
12 12 Get text nodes from a deep tree of HTML nodes.
  @@ -17,20 +17,24 @@ defmodule Floki.DeepText do
17 17 iex> Floki.DeepText.get([{"a", [], ["The meaning of life is...", {"strong", [], ["something else"]}] }])
18 18 "The meaning of life is...something else"
19 19
20 + iex> Floki.DeepText.get([{"a", [], ["The meaning of life is...", {"strong", [], ["something else"]}] }], " ")
21 + "The meaning of life is... something else"
22 +
20 23 """
21 - def get(html_tree) do
22 - get_text(html_tree, "")
24 + def get(html_tree, sep \\ "") do
25 + get_text(html_tree, "", sep)
23 26 end
24 27
25 - defp get_text(text, acc) when is_binary(text), do: acc <> text
26 - defp get_text(nodes, acc) when is_list(nodes) do
28 + defp get_text(text, "", _sep) when is_binary(text), do: text
29 + defp get_text(text, acc, sep) when is_binary(text), do: Enum.join([acc, text], sep)
30 + defp get_text(nodes, acc, sep) when is_list(nodes) do
27 31 Enum.reduce nodes, acc, fn(child, istr) ->
28 - get_text(child, istr)
32 + get_text(child, istr, sep)
29 33 end
30 34 end
31 - defp get_text({:comment, _}, acc), do: acc
32 - defp get_text({"br", _, _}, acc), do: acc <> "\n"
33 - defp get_text({_, _, nodes}, acc) do
34 - get_text(nodes, acc)
35 + defp get_text({:comment, _}, acc, _), do: acc
36 + defp get_text({"br", _, _}, acc, _), do: acc <> "\n"
37 + defp get_text({_, _, nodes}, acc, sep) do
38 + get_text(nodes, acc, sep)
35 39 end
36 40 end
  @@ -6,7 +6,7 @@ defmodule Floki.FlatText do
6 6
7 7 @type html_tree :: tuple | list
8 8
9 - @spec get(html_tree) :: binary
9 + @spec get(html_tree, binary) :: binary
10 10
11 11 @doc """
12 12 Get text nodes from first level of HTML nodes.
  @@ -17,22 +17,30 @@ defmodule Floki.FlatText do
17 17 iex> Floki.FlatText.get([{"a", [], ["The meaning of life is...", {"strong", [], ["something else"]}] }])
18 18 "The meaning of life is..."
19 19
20 + iex> Floki.FlatText.get([{"a", [], ["The meaning of life is...", {"strong", [], ["something else"]}] }], " ")
21 + "The meaning of life is..."
22 +
20 23 """
21 - def get(html_nodes) when is_list(html_nodes) do
24 + def get(html_nodes, sep \\ "")
25 + def get(html_nodes, sep) when is_list(html_nodes) do
22 26 Enum.reduce(html_nodes, "", fn(html_node, acc) ->
23 - text_from_node(html_node, acc)
27 + text_from_node(html_node, acc, sep)
24 28 end)
25 29 end
26 - def get(html_node) do
27 - text_from_node(html_node, "")
30 + def get(html_node, sep) do
31 + text_from_node(html_node, "", sep)
28 32 end
29 33
30 - defp text_from_node({ _tag, _attrs, html_nodes}, acc) do
31 - Enum.reduce(html_nodes, acc, &capture_text/2)
34 + defp text_from_node({ _tag, _attrs, html_nodes}, acc, sep) do
35 + Enum.reduce(html_nodes, acc, fn(node, acc) ->
36 + capture_text(node, acc, sep)
37 + end)
32 38 end
33 - defp text_from_node(text, acc) when is_binary(text), do: acc <> text
34 - defp text_from_node(_, acc), do: acc
39 + defp text_from_node(text, "", _sep) when is_binary(text), do: text
40 + defp text_from_node(text, acc, sep) when is_binary(text), do: Enum.join([acc, text], sep)
41 + defp text_from_node(_, acc, _), do: acc
35 42
36 - defp capture_text(text, acc) when is_binary(text), do: acc <> text
37 - defp capture_text(_html_node, acc), do: acc
43 + defp capture_text(text, "", _sep) when is_binary(text), do: text
44 + defp capture_text(text, acc, sep) when is_binary(text), do: Enum.join([acc, text], sep)
45 + defp capture_text(_html_node, acc, _), do: acc
38 46 end
Loading more files…