diff options
author | Sam Atkins <atkinssj@gmail.com> | 2021-07-07 17:47:17 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-11 23:19:56 +0200 |
commit | 7e4f75c78c348f6d7768fec8fa977595a506722e (patch) | |
tree | 3b59f735a4726c84b2216f4a8bb3085d1fd9b39b /Userland/Libraries/LibWeb | |
parent | 57f6d86996e56e0da2c9c0fdb76d658db1d8a22d (diff) | |
download | serenity-7e4f75c78c348f6d7768fec8fa977595a506722e.zip |
LibWeb: Fix whitespace handling in CSS selectors
Whitespace marks the end of a compound-selector, no matter where
it occurs. `check_for_eof_or_whitespace()` reconsumes the whitespace
token for convenience.
Diffstat (limited to 'Userland/Libraries/LibWeb')
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 52 |
1 files changed, 31 insertions, 21 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 72e16f15c4..1d4a416d59 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -218,9 +218,21 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is Vector<Selector::ComplexSelector> selectors; + auto check_for_eof_or_whitespace = [&](T& current_value) -> bool { + if (current_value.is(Token::Type::EndOfFile)) + return true; + + if (current_value.is(Token::Type::Whitespace)) { + tokens.reconsume_current_input_token(); + return true; + } + return false; + }; + auto parse_simple_selector = [&]() -> Optional<Selector::SimpleSelector> { auto current_value = tokens.next_token(); - if (current_value.is(Token::Type::EndOfFile)) + dbgln("parse_simple_selector, start token: {}", current_value.to_string()); + if (check_for_eof_or_whitespace(current_value)) return {}; Selector::SimpleSelector::Type type; @@ -245,7 +257,7 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is value = ((Token)current_value).m_value.to_string(); } else if (current_value.is(Token::Type::Delim) && ((Token)current_value).delim() == ".") { current_value = tokens.next_token(); - if (current_value.is(Token::Type::EndOfFile)) + if (check_for_eof_or_whitespace(current_value)) return {}; if (!current_value.is(Token::Type::Ident)) { @@ -267,7 +279,7 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is simple_selector.value = value; current_value = tokens.next_token(); - if (current_value.is(Token::Type::EndOfFile)) + if (check_for_eof_or_whitespace(current_value)) return simple_selector; // FIXME: Attribute selectors want to be their own Selector::SimpleSelector::Type according to the spec. @@ -337,14 +349,6 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is } } - while (attribute_parts.at(attribute_index).is(Token::Type::Whitespace)) { - attribute_index++; - if (attribute_index >= attribute_parts.size()) { - dbgln("Attribute selector ended without a value to match."); - return {}; - } - } - if (attribute_index >= attribute_parts.size()) { dbgln("Attribute selector ended without a value to match."); return {}; @@ -366,13 +370,13 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is bool is_pseudo = false; current_value = tokens.next_token(); - if (current_value.is(Token::Type::EndOfFile)) + if (check_for_eof_or_whitespace(current_value)) return {}; if (current_value.is(Token::Type::Colon)) { is_pseudo = true; current_value = tokens.next_token(); - if (current_value.is(Token::Type::EndOfFile)) + if (check_for_eof_or_whitespace(current_value)) return {}; } @@ -382,7 +386,7 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is return {}; current_value = tokens.next_token(); - if (current_value.is(Token::Type::EndOfFile)) + if (check_for_eof_or_whitespace(current_value)) return simple_selector; if (current_value.is(Token::Type::Ident)) { @@ -452,6 +456,8 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is auto parse_complex_selector = [&]() -> Optional<Selector::ComplexSelector> { auto relation = Selector::ComplexSelector::Relation::Descendant; + tokens.skip_whitespace(); + auto current_value = tokens.peek_token(); if (current_value.is(Token::Type::Delim)) { auto delim = ((Token)current_value).delim(); @@ -475,12 +481,20 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is relation = Selector::ComplexSelector::Relation::Column; tokens.next_token(); } + } else { + dbgln("Unrecognized relation delimiter: '{}'", delim); } } + tokens.skip_whitespace(); + Vector<Selector::SimpleSelector> simple_selectors; for (;;) { + auto current_value = tokens.peek_token(); + if (current_value.is(Token::Type::EndOfFile) || current_value.is(Token::Type::Whitespace)) + break; + auto component = parse_simple_selector(); if (!component.has_value()) break; @@ -495,17 +509,13 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is }; for (;;) { - auto complex = parse_complex_selector(); - if (complex.has_value()) - selectors.append(complex.value()); - auto current_value = tokens.peek_token(); if (current_value.is(Token::Type::EndOfFile)) break; - if (current_value.is(Token::Type::Comma)) - break; - tokens.next_token(); + auto complex = parse_complex_selector(); + if (complex.has_value()) + selectors.append(complex.value()); } if (selectors.is_empty()) |