Current section

86 Versions

Jump to

Compare versions

5 files changed
+98 additions
-84 deletions
  @@ -4,20 +4,23 @@
4 4 <<"Floki is a simple HTML parser that enables search for nodes using CSS selectors.">>}.
5 5 {<<"elixir">>,<<">= 1.3.0">>}.
6 6 {<<"files">>,
7 - [<<"lib/floki.ex">>,<<"lib/floki/deep_text.ex">>,
8 - <<"lib/floki/filter_out.ex">>,<<"lib/floki/finder.ex">>,
9 - <<"lib/floki/flat_text.ex">>,<<"lib/floki/html_parser.ex">>,
7 + [<<"lib">>,<<"lib/floki">>,<<"lib/floki.ex">>,<<"lib/floki/.parser.ex.swp">>,
8 + <<"lib/floki/deep_text.ex">>,<<"lib/floki/filter_out.ex">>,
9 + <<"lib/floki/finder.ex">>,<<"lib/floki/flat_text.ex">>,
10 + <<"lib/floki/html_parser">>,<<"lib/floki/html_parser.ex">>,
10 11 <<"lib/floki/html_parser/html5ever.ex">>,
11 - <<"lib/floki/html_parser/mochiweb.ex">>,<<"lib/floki/html_tree.ex">>,
12 - <<"lib/floki/html_tree/comment.ex">>,<<"lib/floki/html_tree/html_node.ex">>,
12 + <<"lib/floki/html_parser/mochiweb.ex">>,<<"lib/floki/html_tree">>,
13 + <<"lib/floki/html_tree.ex">>,<<"lib/floki/html_tree/comment.ex">>,
14 + <<"lib/floki/html_tree/html_node.ex">>,
13 15 <<"lib/floki/html_tree/id_seeder.ex">>,<<"lib/floki/html_tree/text.ex">>,
16 + <<"lib/floki/raw_html.ex">>,<<"lib/floki/selector">>,
14 17 <<"lib/floki/selector.ex">>,<<"lib/floki/selector/attribute_selector.ex">>,
15 18 <<"lib/floki/selector/combinator.ex">>,
16 19 <<"lib/floki/selector/functional.ex">>,<<"lib/floki/selector/parser.ex">>,
17 20 <<"lib/floki/selector/pseudo_class.ex">>,
18 - <<"lib/floki/selector/tokenizer.ex">>,<<"src/floki_selector_lexer.xrl">>,
19 - <<"mix.exs">>,<<"README.md">>,<<"LICENSE">>,<<"CODE_OF_CONDUCT.md">>,
20 - <<"CONTRIBUTING.md">>]}.
21 + <<"lib/floki/selector/tokenizer.ex">>,<<"lib/floki/xpath_selector">>,
22 + <<"src/floki_selector_lexer.xrl">>,<<"mix.exs">>,<<"README.md">>,
23 + <<"LICENSE">>,<<"CODE_OF_CONDUCT.md">>,<<"CONTRIBUTING.md">>]}.
21 24 {<<"licenses">>,[<<"MIT">>]}.
22 25 {<<"links">>,[{<<"GitHub">>,<<"https://github.com/philss/floki">>}]}.
23 26 {<<"maintainers">>,[<<"Philip Sampaio Silva">>]}.
  @@ -26,9 +29,11 @@
26 29 [[{<<"app">>,<<"html_entities">>},
27 30 {<<"name">>,<<"html_entities">>},
28 31 {<<"optional">>,false},
32 + {<<"repository">>,<<"hexpm">>},
29 33 {<<"requirement">>,<<"~> 0.4.0">>}],
30 34 [{<<"app">>,<<"mochiweb">>},
31 35 {<<"name">>,<<"mochiweb">>},
32 36 {<<"optional">>,false},
37 + {<<"repository">>,<<"hexpm">>},
33 38 {<<"requirement">>,<<"~> 2.15">>}]]}.
34 - {<<"version">>,<<"0.19.2">>}.
39 + {<<"version">>,<<"0.19.3">>}.
  @@ -66,31 +66,12 @@ defmodule Floki do
66 66
67 67 """
68 68
69 - @spec parse(binary) :: html_tree
69 + @spec parse(binary) :: html_tree | String.t()
70 70
71 71 def parse(html) do
72 72 HTMLParser.parse(html)
73 73 end
74 74
75 - @self_closing_tags [
76 - "area",
77 - "base",
78 - "br",
79 - "col",
80 - "command",
81 - "embed",
82 - "hr",
83 - "img",
84 - "input",
85 - "keygen",
86 - "link",
87 - "meta",
88 - "param",
89 - "source",
90 - "track",
91 - "wbr"
92 - ]
93 -
94 75 @doc """
95 76 Converts HTML tree to raw HTML.
96 77 Note that the resultant HTML may be different from the original one.
  @@ -105,59 +86,7 @@ defmodule Floki do
105 86
106 87 @spec raw_html(html_tree | binary) :: binary
107 88
108 - def raw_html(html_tree), do: raw_html(html_tree, "")
109 - defp raw_html([], html), do: html
110 - defp raw_html(string, _html) when is_binary(string), do: HtmlEntities.encode(string)
111 - defp raw_html(tuple, html) when is_tuple(tuple), do: raw_html([tuple], html)
112 -
113 - defp raw_html([string | tail], html) when is_binary(string) do
114 - raw_html(tail, html <> HtmlEntities.encode(string))
115 - end
116 -
117 - defp raw_html([{:comment, comment} | tail], html),
118 - do: raw_html(tail, html <> "<!--#{comment}-->")
119 -
120 - defp raw_html([{:pi, "xml", attrs} | tail], html) do
121 - raw_html(tail, html <> "<?xml " <> tag_attrs(attrs) <> "?>")
122 - end
123 -
124 - defp raw_html([{:doctype, type, public, system} | tail], html) do
125 - attr =
126 - case {public, system} do
127 - {"", ""} -> ""
128 - {"", system} -> " SYSTEM \"#{system}\""
129 - {public, system} -> " PUBLIC \"#{public}\" \"#{system}\""
130 - end
131 -
132 - raw_html(tail, html <> "<!DOCTYPE #{type}#{attr}>")
133 - end
134 -
135 - defp raw_html([{type, attrs, children} | tail], html) do
136 - raw_html(tail, html <> tag_for(type, tag_attrs(attrs), children))
137 - end
138 -
139 - defp tag_attrs(attr_list) do
140 - attr_list
141 - |> Enum.reduce("", &build_attrs/2)
142 - |> String.trim()
143 - end
144 -
145 - defp build_attrs({attr, value}, attrs), do: ~s(#{attrs} #{attr}="#{value}")
146 - defp build_attrs(attr, attrs), do: "#{attrs} #{attr}"
147 -
148 - defp tag_for(type, attrs, []) when type in @self_closing_tags do
149 - case attrs do
150 - "" -> "<#{type}/>"
151 - _ -> "<#{type} #{attrs}/>"
152 - end
153 - end
154 -
155 - defp tag_for(type, attrs, children) do
156 - case attrs do
157 - "" -> "<#{type}>#{raw_html(children)}</#{type}>"
158 - _ -> "<#{type} #{attrs}>#{raw_html(children)}</#{type}>"
159 - end
160 - end
89 + defdelegate raw_html(html_tree), to: Floki.RawHTML
161 90
162 91 @doc """
163 92 Find elements inside a HTML tree or string.
  @@ -0,0 +1,80 @@
1 + defmodule Floki.RawHTML do
2 + @self_closing_tags [
3 + "area",
4 + "base",
5 + "br",
6 + "col",
7 + "command",
8 + "embed",
9 + "hr",
10 + "img",
11 + "input",
12 + "keygen",
13 + "link",
14 + "meta",
15 + "param",
16 + "source",
17 + "track",
18 + "wbr"
19 + ]
20 +
21 + def raw_html(html_tree), do: raw_html(html_tree, "")
22 + defp raw_html([], html), do: html
23 + defp raw_html(string, _html) when is_binary(string), do: HtmlEntities.encode(string)
24 + defp raw_html(tuple, html) when is_tuple(tuple), do: raw_html([tuple], html)
25 +
26 + defp raw_html([string | tail], html) when is_binary(string) do
27 + raw_html(tail, html <> HtmlEntities.encode(string))
28 + end
29 +
30 + defp raw_html([{:comment, comment} | tail], html),
31 + do: raw_html(tail, html <> "<!--#{comment}-->")
32 +
33 + defp raw_html([{:pi, "xml", attrs} | tail], html) do
34 + raw_html(tail, html <> "<?xml " <> tag_attrs(attrs) <> "?>")
35 + end
36 +
37 + defp raw_html([{:doctype, type, public, system} | tail], html) do
38 + attr =
39 + case {public, system} do
40 + {"", ""} -> ""
41 + {"", system} -> " SYSTEM \"#{system}\""
42 + {public, system} -> " PUBLIC \"#{public}\" \"#{system}\""
43 + end
44 +
45 + raw_html(tail, html <> "<!DOCTYPE #{type}#{attr}>")
46 + end
47 +
48 + defp raw_html([{type, attrs, children} | tail], html) do
49 + raw_html(tail, html <> tag_for(type, attrs, children))
50 + end
51 +
52 + defp tag_attrs(attr_list) do
53 + attr_list
54 + |> Enum.reduce("", &build_attrs/2)
55 + |> String.trim()
56 + end
57 +
58 + defp tag_with_attrs(type, [], children), do: "<#{type}" <> close_open_tag(type, children)
59 +
60 + defp tag_with_attrs(type, attrs, children) do
61 + "<#{type} #{tag_attrs(attrs)}" <> close_open_tag(type, children)
62 + end
63 +
64 + defp close_open_tag(type, []) when type in @self_closing_tags, do: "/>"
65 + defp close_open_tag(_type, _), do: ">"
66 +
67 + defp close_end_tag(type, []) when type in @self_closing_tags, do: ""
68 + defp close_end_tag(type, _), do: "</#{type}>"
69 +
70 + defp build_attrs({attr, value}, attrs), do: ~s(#{attrs} #{attr}="#{value}")
71 + defp build_attrs(attr, attrs), do: "#{attrs} #{attr}"
72 +
73 + defp tag_for(type, attrs, content) when type in ["script", "style"] do
74 + tag_with_attrs(type, attrs, []) <> Enum.join(content) <> "</#{type}>"
75 + end
76 +
77 + defp tag_for(type, attrs, children) do
78 + tag_with_attrs(type, attrs, children) <> raw_html(children) <> close_end_tag(type, children)
79 + end
80 + end
  @@ -2,7 +2,7 @@ defmodule Floki.Mixfile do
2 2 use Mix.Project
3 3
4 4 @description "Floki is a simple HTML parser that enables search for nodes using CSS selectors."
5 - @version "0.19.2"
5 + @version "0.19.3"
6 6
7 7 def project do
8 8 [
  @@ -19,7 +19,7 @@ defmodule Floki.Mixfile do
19 19 end
20 20
21 21 def application do
22 - [applications: [:logger, :mochiweb]]
22 + [applications: [:logger, :mochiweb, :html_entities]]
23 23 end
24 24
25 25 defp deps do