From 22750be70f85abbcc4b927541daeab43d053c92c Mon Sep 17 00:00:00 2001 From: Jonathan del Strother Date: Wed, 30 Aug 2023 17:36:23 +0100 Subject: [PATCH] Fix parsing space-less media-features Previously, `@media (width: 500px)` would be successfully parsed, but not `@media(width: 500px)` - it would tokenize to `@media(width:` and then get discarded. Fixes #139 --- CHANGELOG.md | 2 ++ lib/css_parser/parser.rb | 13 +++++++++++-- test/test_css_parser_media_types.rb | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bb0959..4c75f13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Unreleased + * Fix parsing space-less media query features like `@media(width:123px)` [#141](https://github.com/premailer/css_parser/pull/141) + ### Version v1.15.0 * Fix parsing background shorthands in ruby 3.2 [#140](https://github.com/premailer/css_parser/pull/140) diff --git a/lib/css_parser/parser.rb b/lib/css_parser/parser.rb index cce0029..1d463c8 100644 --- a/lib/css_parser/parser.rb +++ b/lib/css_parser/parser.rb @@ -329,7 +329,7 @@ def parse_block_into_rule_sets!(block, options = {}) # :nodoc: rule_start = nil offset = nil - block.scan(/\s+|\\{2,}|\\?[{}\s"]|.[^\s"{}\\]*/) do |token| + block.scan(/\s+|\\{2,}|\\?[{}\s"]|[()]|.[^\s"{}()\\]*/) do |token| # save the regex offset so that we know where in the file we are offset = Regexp.last_match.offset(0) if options[:capture_offsets] @@ -391,7 +391,16 @@ def parse_block_into_rule_sets!(block, options = {}) # :nodoc: current_media_query = String.new else token.strip! - current_media_query << token << ' ' + # special-case the ( and ) tokens to remove inner-whitespace + # (eg we'd prefer '(width: 500px)' to '( width: 500px )' ) + case token + when '(' + current_media_query << token + when ')' + current_media_query.sub!(/ ?$/, token) + else + current_media_query << token << ' ' + end end elsif in_charset or token =~ /@charset/i # iterate until we are out of the charset declaration diff --git a/test/test_css_parser_media_types.rb b/test/test_css_parser_media_types.rb index 6f3ff27..0784ae2 100644 --- a/test/test_css_parser_media_types.rb +++ b/test/test_css_parser_media_types.rb @@ -46,6 +46,25 @@ def test_finding_by_media_type assert_equal 'color: blue;', @cp.find_by_selector('body', 'print and resolution > 90dpi'.to_sym).join(' ') end + def test_with_parenthesized_media_features + @cp.add_block!(<<-CSS) + body { color: black } + @media(prefers-color-scheme: dark) { + body { color: white } + } + @media(min-width: 500px) { + body { color: blue } + } + @media screen and (width > 500px) { + body { color: red } + } + CSS + assert_equal [:all, :'(prefers-color-scheme: dark)', :'(min-width: 500px)', :'screen and (width > 500px)'], @cp.rules_by_media_query.keys + assert_equal 'color: white;', @cp.find_by_selector('body', :'(prefers-color-scheme: dark)').join(' ') + assert_equal 'color: blue;', @cp.find_by_selector('body', :'(min-width: 500px)').join(' ') + assert_equal 'color: red;', @cp.find_by_selector('body', :'screen and (width > 500px)').join(' ') + end + def test_finding_by_multiple_media_types @cp.add_block!(<<-CSS) @media print {