@@ -2,24 +2,14 @@ defmodule Premailex.HTMLParser do
22 @ moduledoc """
33 Module that provide HTML parsing API using an underlying HTML parser library.
44
5- By default, premailex will try to use Floki, then Meeseeks, then LazyHTML
6- (in that order) based on what's available. You can also explicitly configure
7- which parser to use in your config:
5+ By default, premailex will try to use Floki, then LazyHTML, then Meeseeks
6+ (in that order) based on what's available.
87
9- config :premailex, html_parser: Premailex.HTMLParser.LazyHTML
8+ You can explicitly configure which parser to use in your config:
109
11- At least one HTML parser dependency must be available:
12- - `{:floki, "~> 0.19"}` (default if available)
13- - `{:meeseeks, "~> 0.11"}`
14- - `{:lazy_html, "~> 0.1.8"}`
10+ config :premailex, html_parser: Premailex.HTMLParser.LazyHTML
1511 """
1612
17- @ parsers_in_order [
18- Premailex.HTMLParser.Floki ,
19- Premailex.HTMLParser.Meeseeks ,
20- Premailex.HTMLParser.LazyHTML
21- ]
22-
2313 @ type html_tree :: tuple ( ) | list ( )
2414 @ type selector :: binary ( )
2515
@@ -38,7 +28,39 @@ defmodule Premailex.HTMLParser do
3828 {"html", [], [{"head", [], []}, {"body", [], [{"h1", [], ["Title"]}]}]}
3929 """
4030 @ spec parse ( binary ( ) ) :: html_tree ( )
41- def parse ( html ) , do: parser ( ) . parse ( html )
31+ def parse ( html ) , do: html_parser ( ) . parse ( html )
32+
33+ defp html_parser do
34+ case Application . get_env ( :premailex , :html_parser ) || default_html_parser! ( ) do
35+ mod when is_atom ( mod ) -> mod
36+ other -> raise "Invalid html_parser, got: #{ inspect ( other ) } "
37+ end
38+ end
39+
40+ defp default_html_parser! do
41+ cond do
42+ Code . ensure_loaded? ( Floki ) ->
43+ Premailex.HTMLParser.Floki
44+
45+ Code . ensure_loaded? ( LazyHTML ) ->
46+ Premailex.HTMLParser.LazyHTML
47+
48+ Code . ensure_loaded? ( Meeseeks ) ->
49+ Premailex.HTMLParser.Meeseeks
50+
51+ true ->
52+ raise """
53+ No HTML parser is available. Please add at least one of the following dependencies to your mix.exs:
54+
55+ - {:floki, "~> 0.19"}
56+ - {:meeseeks, "~> 0.11"}
57+ - {:lazy_html, "~> 0.1.8"}
58+
59+ Or explicitly configure a parser:
60+ config :premailex, html_parser: Premailex.HTMLParser.Floki
61+ """
62+ end
63+ end
4264
4365 @ doc """
4466 Searches an HTML tree for the selector.
@@ -49,7 +71,7 @@ defmodule Premailex.HTMLParser do
4971 [{"h1", [], ["Title"]}]
5072 """
5173 @ spec all ( html_tree ( ) , selector ( ) ) :: [ html_tree ( ) ]
52- def all ( tree , selector ) , do: parser ( ) . all ( tree , selector )
74+ def all ( tree , selector ) , do: html_parser ( ) . all ( tree , selector )
5375
5476 @ doc """
5577 Filters elements matching the selector from the HTML tree.
@@ -60,7 +82,7 @@ defmodule Premailex.HTMLParser do
6082 [{"html", [], [{"head", [], []}, {"body", [], []}]}]
6183 """
6284 @ spec filter ( html_tree ( ) , selector ( ) ) :: [ html_tree ( ) ]
63- def filter ( tree , selector ) , do: parser ( ) . filter ( tree , selector )
85+ def filter ( tree , selector ) , do: html_parser ( ) . filter ( tree , selector )
6486
6587 @ doc """
6688 Turns an HTML tree into a string.
@@ -71,7 +93,7 @@ defmodule Premailex.HTMLParser do
7193 "<html><head></head><body><h1>Title</h1></body></html>"
7294 """
7395 @ spec to_string ( html_tree ( ) ) :: binary ( )
74- def to_string ( tree ) , do: parser ( ) . to_string ( tree )
96+ def to_string ( tree ) , do: html_parser ( ) . to_string ( tree )
7597
7698 @ doc """
7799 Extracts text elements from the HTML tree.
@@ -82,66 +104,5 @@ defmodule Premailex.HTMLParser do
82104 "Title"
83105 """
84106 @ spec text ( html_tree ( ) ) :: binary ( )
85- def text ( tree ) , do: parser ( ) . text ( tree )
86-
87- defp parser do
88- case Application . get_env ( :premailex , :html_parser ) do
89- nil ->
90- # No explicit config, try to find an available parser
91- find_available_parser ( )
92-
93- configured_parser ->
94- # User explicitly configured a parser, verify it's available
95- if parser_available? ( configured_parser ) do
96- configured_parser
97- else
98- raise """
99- The configured HTML parser #{ inspect ( configured_parser ) } is not available.
100-
101- Please ensure the corresponding dependency is added to your mix.exs:
102- - For Floki: {:floki, "~> 0.19"}
103- - For Meeseeks: {:meeseeks, "~> 0.11"}
104- - For LazyHTML: {:lazy_html, "~> 0.1.8"}
105-
106- Or configure a different parser in your config:
107- config :premailex, html_parser: Premailex.HTMLParser.Floki
108- """
109- end
110- end
111- end
112-
113- # Find the first available parser in order of preference
114- defp find_available_parser do
115- case Enum . find ( @ parsers_in_order , & parser_available? / 1 ) do
116- nil ->
117- raise """
118- No HTML parser is available. Please add at least one of the following dependencies to your mix.exs:
119-
120- - {:floki, "~> 0.19"}
121- - {:meeseeks, "~> 0.11"}
122- - {:lazy_html, "~> 0.1.8"}
123-
124- Or explicitly configure a parser:
125- config :premailex, html_parser: Premailex.HTMLParser.Floki
126- """
127-
128- parser ->
129- parser
130- end
131- end
132-
133- # Check if a parser module is available by verifying its dependencies are loaded
134- defp parser_available? ( Premailex.HTMLParser.Floki ) do
135- Code . ensure_loaded? ( Floki )
136- end
137-
138- defp parser_available? ( Premailex.HTMLParser.Meeseeks ) do
139- Code . ensure_loaded? ( Meeseeks )
140- end
141-
142- defp parser_available? ( Premailex.HTMLParser.LazyHTML ) do
143- Code . ensure_loaded? ( LazyHTML )
144- end
145-
146- defp parser_available? ( _ ) , do: false
107+ def text ( tree ) , do: html_parser ( ) . text ( tree )
147108end
0 commit comments