diff options
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 80 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 8 |
2 files changed, 51 insertions, 37 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index c45ab5b609..4756203878 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -1902,39 +1902,20 @@ Optional<StyleProperty> Parser::parse_a_declaration(TokenStream<T>& tokens) return {}; } -RefPtr<PropertyOwningCSSStyleDeclaration> Parser::parse_as_list_of_declarations() +Vector<DeclarationOrAtRule> Parser::parse_as_list_of_declarations() { return parse_a_list_of_declarations(m_token_stream); } +// 5.3.8. Parse a list of declarations +// https://www.w3.org/TR/css-syntax-3/#parse-list-of-declarations template<typename T> -RefPtr<PropertyOwningCSSStyleDeclaration> Parser::parse_a_list_of_declarations(TokenStream<T>& tokens) +Vector<DeclarationOrAtRule> Parser::parse_a_list_of_declarations(TokenStream<T>& tokens) { - auto declarations_and_at_rules = consume_a_list_of_declarations(tokens); - - Vector<StyleProperty> properties; - HashMap<String, StyleProperty> custom_properties; - - for (auto& declaration_or_at_rule : declarations_and_at_rules) { - if (declaration_or_at_rule.is_at_rule()) { - dbgln_if(CSS_PARSER_DEBUG, "!!! CSS at-rule is not allowed here!"); - continue; - } - - auto& declaration = declaration_or_at_rule.m_declaration; - - auto maybe_property = convert_to_style_property(declaration); - if (maybe_property.has_value()) { - auto property = maybe_property.value(); - if (property.property_id == PropertyID::Custom) { - custom_properties.set(property.custom_name, property); - } else { - properties.append(property); - } - } - } - - return PropertyOwningCSSStyleDeclaration::create(move(properties), move(custom_properties)); + // To parse a list of declarations from input: + // 1. Normalize input, and set input to the result. + // 2. Consume a list of declarations from input, and return the result. + return consume_a_list_of_declarations(tokens); } Optional<StyleComponentValueRule> Parser::parse_as_component_value() @@ -2015,6 +1996,12 @@ Vector<Vector<StyleComponentValueRule>> Parser::parse_a_comma_separated_list_of_ return lists; } +RefPtr<PropertyOwningCSSStyleDeclaration> Parser::parse_as_style_attribute() +{ + auto declarations_and_at_rules = parse_a_list_of_declarations(m_token_stream); + return convert_to_style_declaration(declarations_and_at_rules); +} + Optional<AK::URL> Parser::parse_url_function(StyleComponentValueRule const& component_value, AllowedDataUrlType allowed_data_url_type) { // FIXME: Handle list of media queries. https://www.w3.org/TR/css-cascade-3/#conditional-import @@ -2156,7 +2143,13 @@ RefPtr<CSSRule> Parser::convert_to_rule(NonnullRefPtr<StyleRule> rule) return {}; } - auto declaration = convert_to_declaration(*rule->m_block); + if (!rule->block()->is_curly()) + return {}; + + auto stream = TokenStream(rule->block()->values()); + auto declarations_and_at_rules = parse_a_list_of_declarations(stream); + + auto declaration = convert_to_style_declaration(declarations_and_at_rules); if (!declaration) { dbgln_if(CSS_PARSER_DEBUG, "CSSParser: style rule declaration invalid; discarding."); return {}; @@ -2168,13 +2161,31 @@ RefPtr<CSSRule> Parser::convert_to_rule(NonnullRefPtr<StyleRule> rule) return {}; } -RefPtr<PropertyOwningCSSStyleDeclaration> Parser::convert_to_declaration(NonnullRefPtr<StyleBlockRule> block) +RefPtr<PropertyOwningCSSStyleDeclaration> Parser::convert_to_style_declaration(Vector<DeclarationOrAtRule> declarations_and_at_rules) { - if (!block->is_curly()) - return {}; + Vector<StyleProperty> properties; + HashMap<String, StyleProperty> custom_properties; + + for (auto& declaration_or_at_rule : declarations_and_at_rules) { + if (declaration_or_at_rule.is_at_rule()) { + dbgln_if(CSS_PARSER_DEBUG, "!!! CSS at-rule is not allowed here!"); + continue; + } + + auto& declaration = declaration_or_at_rule.m_declaration; - auto stream = TokenStream(block->m_values); - return parse_a_list_of_declarations(stream); + auto maybe_property = convert_to_style_property(declaration); + if (maybe_property.has_value()) { + auto property = maybe_property.value(); + if (property.property_id == PropertyID::Custom) { + custom_properties.set(property.custom_name, property); + } else { + properties.append(property); + } + } + } + + return PropertyOwningCSSStyleDeclaration::create(move(properties), move(custom_properties)); } Optional<StyleProperty> Parser::convert_to_style_property(StyleDeclarationRule const& declaration) @@ -5086,10 +5097,11 @@ RefPtr<CSS::CSSStyleSheet> parse_css(CSS::ParsingContext const& context, StringV RefPtr<CSS::PropertyOwningCSSStyleDeclaration> parse_css_style_attribute(CSS::ParsingContext const& context, StringView css) { + // FIXME: We could save some effort by creating an ElementInlineCSSStyleDeclaration right here. if (css.is_empty()) return CSS::PropertyOwningCSSStyleDeclaration::create({}, {}); CSS::Parser parser(context, css); - return parser.parse_as_list_of_declarations(); + return parser.parse_as_style_attribute(); } RefPtr<CSS::StyleValue> parse_css_value(CSS::ParsingContext const& context, StringView string, CSS::PropertyID property_id) diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index 0f2533117e..c417bb6778 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -98,13 +98,15 @@ public: // Used in @supports conditions. [CSS3-CONDITIONAL] Optional<StyleProperty> parse_as_declaration(); // For the contents of a style attribute, which parses text into the contents of a single style rule. - RefPtr<PropertyOwningCSSStyleDeclaration> parse_as_list_of_declarations(); + Vector<DeclarationOrAtRule> parse_as_list_of_declarations(); // For things that need to consume a single value, like the parsing rules for attr(). Optional<StyleComponentValueRule> parse_as_component_value(); // For the contents of presentational attributes, which parse text into a single declaration’s value, or for parsing a stand-alone selector [SELECT] or list of Media Queries [MEDIAQ], as in Selectors API or the media HTML attribute. Vector<StyleComponentValueRule> parse_as_list_of_component_values(); Vector<Vector<StyleComponentValueRule>> parse_as_comma_separated_list_of_component_values(); + RefPtr<PropertyOwningCSSStyleDeclaration> parse_as_style_attribute(); + enum class SelectorParsingMode { Standard, // `<forgiving-selector-list>` and `<forgiving-relative-selector-list>` @@ -141,7 +143,7 @@ private: template<typename T> Optional<StyleProperty> parse_a_declaration(TokenStream<T>&); template<typename T> - RefPtr<PropertyOwningCSSStyleDeclaration> parse_a_list_of_declarations(TokenStream<T>&); + Vector<DeclarationOrAtRule> parse_a_list_of_declarations(TokenStream<T>&); template<typename T> Optional<StyleComponentValueRule> parse_a_component_value(TokenStream<T>&); template<typename T> @@ -187,7 +189,7 @@ private: [[nodiscard]] Optional<GeneralEnclosed> parse_general_enclosed(TokenStream<StyleComponentValueRule>&); [[nodiscard]] RefPtr<CSSRule> convert_to_rule(NonnullRefPtr<StyleRule>); - [[nodiscard]] RefPtr<PropertyOwningCSSStyleDeclaration> convert_to_declaration(NonnullRefPtr<StyleBlockRule>); + [[nodiscard]] RefPtr<PropertyOwningCSSStyleDeclaration> convert_to_style_declaration(Vector<DeclarationOrAtRule> declarations); [[nodiscard]] Optional<StyleProperty> convert_to_style_property(StyleDeclarationRule const&); class Dimension { |