Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore empty selectors #95

Merged
merged 1 commit into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## v0.3.20 (TBA)

* Require Elixir 1.13
* `Premailex.CSSParser.parse/1` now ignores empty selectors

## v0.3.19 (2023-11-19)

Expand Down
18 changes: 17 additions & 1 deletion lib/premailex/css_parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule Premailex.CSSParser do
@moduledoc """
Module that handles CSS parsing with naive Regular Expression.
"""
require Logger

@type rule :: %{directive: String.t(), value: String.t(), important?: boolean}
@type rule_set :: %{rules: [rule], selector: String.t(), specificity: number}
Expand Down Expand Up @@ -65,12 +66,27 @@ defmodule Premailex.CSSParser do
selector
# Ignore escaped commas
|> String.split(~r/(?<!\\),/)
|> normalize_selectors(selector)
|> Enum.map(&parse_selector_rules(&1, rules))
end

defp normalize_selectors(selectors, original) do
Enum.reduce(selectors, [], fn selector, acc ->
case String.trim(selector) do
"" ->
Logger.debug("Empty selector found in #{inspect(String.trim(original))}. Ignoring.")

acc

selector ->
acc ++ [selector]
end
end)
end

defp parse_selector_rules(selector, rules) do
%{
selector: String.trim(selector),
selector: selector,
rules: parse_rules(rules),
specificity: calculate_specificity(selector)
}
Expand Down
12 changes: 11 additions & 1 deletion test/premailex/css_parser_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ defmodule Premailex.CSSParserTest do
use ExUnit.Case
doctest Premailex.CSSParser

alias ExUnit.CaptureLog

@input """
body, table {/* text-decoration:underline */background-color:#ffffff;background-image:url('http://example.com/image.png');color:#000000;}
div p > a:hover {color:#000000 !important;text-decoration:underline}
Expand All @@ -19,6 +21,7 @@ defmodule Premailex.CSSParserTest do
url("/fonts/OpenSans-Regular-webfont.woff") format("woff");
}
.with\\,escaped\\,commas {}
.with-empty-selector, {}
"""

@parsed [
Expand Down Expand Up @@ -60,10 +63,17 @@ defmodule Premailex.CSSParserTest do
rules: [],
selector: ".with\\,escaped\\,commas",
specificity: 1
},
%{
rules: [],
selector: ".with-empty-selector",
specificity: 1
}
]

test "parse/1" do
assert Premailex.CSSParser.parse(@input) == @parsed
assert CaptureLog.capture_log(fn ->
assert Premailex.CSSParser.parse(@input) == @parsed
end) =~ "Empty selector found in \".with-empty-selector,\". Ignoring."
end
end
1 change: 1 addition & 0 deletions test/premailex/html_inline_styles_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ defmodule Premailex.HTMLInlineStylesTest do

h1, h2, h3, h4, p {margin: 0; padding: 0;}
p:first-of-type {font-size:16px;font-weight:bold;}
.invalid-empty-selector, {}
"""

@css_inline_content """
Expand Down
Loading