diff options
author | Sam Atkins <atkinssj@gmail.com> | 2021-07-01 14:54:27 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-11 23:19:56 +0200 |
commit | 29d78bba4bd0fa2768a63f365f15f2ad4cfb05e6 (patch) | |
tree | 7ee1da5a2e1b5be673dc4dbb1c4e32f5dd0b0913 | |
parent | 89bfde29dc2d9fd27fceb5b1de9cdd7bb5389f3a (diff) | |
download | serenity-29d78bba4bd0fa2768a63f365f15f2ad4cfb05e6.zip |
LibWeb: Use StyleComponentValueRules for StyleBlockRule's values
Noticed while doing this that attribute selectors have two different
ways of saying "starts with", and so AttributeMatchType::StartsWith
needs a better name. But I'll change that when I add the missing
types.
These class names are a mouthful to fit in a commit message. :^)
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 64 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/StyleBlockRule.h | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/StyleRules.cpp | 2 |
3 files changed, 55 insertions, 16 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 4411a6ee32..fa945f30a6 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -152,31 +152,69 @@ Vector<CSS::Selector::ComplexSelector> Parser::parse_selectors(Vector<StyleCompo // FIXME: Attribute selectors want to be their own Selector::SimpleSelector::Type according to the spec. if (current_value.is_block() && current_value.block().is_square()) { - Vector<String> attribute_parts = current_value.block().values(); + Vector<StyleComponentValueRule> const& attribute_parts = current_value.block().values(); + + // FIXME: Handle namespace prefix for attribute name. + auto& attribute_part = attribute_parts.first(); + if (!attribute_part.is(Token::TokenType::Ident)) { + dbgln("Expected ident for attribute name, got: '{}'", attribute_part.to_string()); + return {}; + } simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::HasAttribute; - simple_selector.attribute_name = attribute_parts.first(); + simple_selector.attribute_name = attribute_part.token().ident(); size_t attribute_index = 1; - if (attribute_index >= attribute_parts.size()) - return simple_selector; + while (attribute_parts.at(attribute_index).is(Token::TokenType::Whitespace)) { + attribute_index++; + if (attribute_index >= attribute_parts.size()) + return simple_selector; + } - if (attribute_parts.at(attribute_index) == " =") { + auto& delim_part = attribute_parts.at(attribute_index); + if (!delim_part.is(Token::TokenType::Delim)) { + dbgln("Expected a delim for attribute comparison, got: '{}'", delim_part.to_string()); + return {}; + } + + if (delim_part.token().delim() == "=") { simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::ExactValueMatch; attribute_index++; + } else { + attribute_index++; + auto& delim_second_part = attribute_parts.at(attribute_index); + if (!(delim_part.is(Token::TokenType::Delim) && delim_part.token().delim() == "=")) { + dbgln("Expected a double delim for attribute comparison, got: '{}{}'", delim_part.to_string(), delim_second_part.to_string()); + return {}; + } + + if (delim_part.token().delim() == "~") { + simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::Contains; + attribute_index++; + } + + if (delim_part.token().delim() == "|") { + simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::StartsWith; + attribute_index++; + } } - if (attribute_parts.at(attribute_index) == " ~") { - simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::Contains; - attribute_index += 2; + while (attribute_parts.at(attribute_index).is(Token::TokenType::Whitespace)) { + attribute_index++; + if (attribute_index >= attribute_parts.size()) { + dbgln("Attribute selector ended without a value to match."); + return {}; + } } - if (attribute_parts.at(attribute_index) == " |") { - simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::StartsWith; - attribute_index += 2; + auto& value_part = attribute_parts.at(attribute_index); + if (!value_part.is(Token::TokenType::Ident) && !value_part.is(Token::TokenType::String)) { + dbgln("Expected a string or ident for the value to match attribute against, got: '{}'", value_part.to_string()); + return {}; } + simple_selector.attribute_value = value_part.token().is_ident() ? value_part.token().ident() : value_part.token().string(); - simple_selector.attribute_value = attribute_parts.at(attribute_index); + // FIXME: Handle case-sensitivity suffixes. https://www.w3.org/TR/selectors-4/#attribute-case return simple_selector; } @@ -495,7 +533,7 @@ NonnullRefPtr<StyleBlockRule> Parser::consume_a_simple_block() continue; } } - block->m_values.append(value.to_string()); + block->m_values.append(value); } } diff --git a/Userland/Libraries/LibWeb/CSS/Parser/StyleBlockRule.h b/Userland/Libraries/LibWeb/CSS/Parser/StyleBlockRule.h index a270351671..63f6cf047b 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/StyleBlockRule.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/StyleBlockRule.h @@ -9,6 +9,7 @@ #include <AK/RefCounted.h> #include <AK/Vector.h> +#include <LibWeb/CSS/Parser/StyleComponentValueRule.h> #include <LibWeb/CSS/Parser/Token.h> namespace Web::CSS { @@ -24,12 +25,12 @@ public: bool is_paren() const { return m_token.is_open_paren(); } bool is_square() const { return m_token.is_open_square(); } - Vector<String> const& values() const { return m_values; } + Vector<StyleComponentValueRule> const& values() const { return m_values; } String to_string() const; private: Token m_token; - Vector<String> m_values; + Vector<StyleComponentValueRule> m_values; }; } diff --git a/Userland/Libraries/LibWeb/CSS/Parser/StyleRules.cpp b/Userland/Libraries/LibWeb/CSS/Parser/StyleRules.cpp index 3c21c712d0..7080e21466 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/StyleRules.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/StyleRules.cpp @@ -119,7 +119,7 @@ String StyleBlockRule::to_string() const StringBuilder builder; builder.append(m_token.bracket_string()); - append_raw(builder, ", ", m_values); + append_with_to_string(builder, ", ", m_values); builder.append(m_token.bracket_mirror_string()); return builder.to_string(); |