/* * Copyright (c) 2020-2021, the SerenityOS developers. * Copyright (c) 2021, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Web::CSS { class CSSStyleSheet; class CSSRule; class CSSStyleRule; struct StyleProperty; enum class PropertyID; class ParsingContext { public: ParsingContext() = default; explicit ParsingContext(DOM::Document const&); explicit ParsingContext(DOM::ParentNode&); bool in_quirks_mode() const; DOM::Document const* document() const { return m_document; } AK::URL complete_url(String const&) const; PropertyID current_property_id() const { return m_current_property_id; } void set_current_property_id(PropertyID property_id) { m_current_property_id = property_id; } private: DOM::Document const* m_document { nullptr }; PropertyID m_current_property_id { PropertyID::Invalid }; }; template class TokenStream { public: explicit TokenStream(Vector const&); ~TokenStream(); TokenStream(TokenStream const&) = delete; bool has_next_token(); T const& next_token(); T const& peek_token(int offset = 0); T const& current_token(); void reconsume_current_input_token(); int position() const { return m_iterator_offset; } void rewind_to_position(int); void skip_whitespace(); void dump_all_tokens(); private: Vector const& m_tokens; int m_iterator_offset { -1 }; T make_eof(); T m_eof; }; class Parser { public: Parser(ParsingContext const&, StringView input, String const& encoding = "utf-8"); ~Parser(); // The normal parser entry point, for parsing stylesheets. NonnullRefPtr parse_as_stylesheet(); // For the content of at-rules such as @media. It differs from "Parse a stylesheet" in the handling of and . NonnullRefPtrVector parse_as_list_of_rules(); // For use by the CSSStyleSheet#insertRule method, and similar functions which might exist, which parse text into a single rule. RefPtr parse_as_rule(); // Used in @supports conditions. [CSS3-CONDITIONAL] Optional parse_as_declaration(); // For the contents of a style attribute, which parses text into the contents of a single style rule. RefPtr parse_as_list_of_declarations(); // For things that need to consume a single value, like the parsing rules for attr(). Optional 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 parse_as_list_of_component_values(); Vector> parse_as_comma_separated_list_of_component_values(); // Contrary to the name, these parse a comma-separated list of selectors, according to the spec. Optional parse_as_selector(); Optional parse_as_relative_selector(); NonnullRefPtrVector parse_as_media_query_list(); RefPtr parse_as_media_query(); RefPtr parse_as_supports(); RefPtr parse_as_css_value(PropertyID); private: enum class ParsingResult { Done, IncludesIgnoredVendorPrefix, SyntaxError, }; template NonnullRefPtr parse_a_stylesheet(TokenStream&); template NonnullRefPtrVector parse_a_list_of_rules(TokenStream&); template RefPtr parse_a_rule(TokenStream&); template Optional parse_a_declaration(TokenStream&); template RefPtr parse_a_list_of_declarations(TokenStream&); template Optional parse_a_component_value(TokenStream&); template Vector parse_a_list_of_component_values(TokenStream&); template Vector> parse_a_comma_separated_list_of_component_values(TokenStream&); template Result parse_a_selector(TokenStream&); template Result parse_a_relative_selector(TokenStream&); template Result parse_a_selector_list(TokenStream&); template Result parse_a_relative_selector_list(TokenStream&); template NonnullRefPtrVector parse_a_media_query_list(TokenStream&); template RefPtr parse_a_supports(TokenStream&); Optional parse_a_n_plus_b_pattern(TokenStream&); template [[nodiscard]] NonnullRefPtrVector consume_a_list_of_rules(TokenStream&, bool top_level); template [[nodiscard]] NonnullRefPtr consume_an_at_rule(TokenStream&); template [[nodiscard]] RefPtr consume_a_qualified_rule(TokenStream&); template [[nodiscard]] Vector consume_a_list_of_declarations(TokenStream&); template [[nodiscard]] Optional consume_a_declaration(TokenStream&); template [[nodiscard]] StyleComponentValueRule consume_a_component_value(TokenStream&); template [[nodiscard]] NonnullRefPtr consume_a_simple_block(TokenStream&); template [[nodiscard]] NonnullRefPtr consume_a_function(TokenStream&); [[nodiscard]] Optional parse_general_enclosed(TokenStream&); [[nodiscard]] RefPtr convert_to_rule(NonnullRefPtr); [[nodiscard]] RefPtr convert_to_declaration(NonnullRefPtr); [[nodiscard]] Optional convert_to_style_property(StyleDeclarationRule const&); Optional parse_color(StyleComponentValueRule const&); Optional parse_length(StyleComponentValueRule const&); enum class AllowedDataUrlType { None, Image, }; Optional parse_url_function(StyleComponentValueRule const&, AllowedDataUrlType = AllowedDataUrlType::None); Result, ParsingResult> parse_css_value(PropertyID, TokenStream&); RefPtr parse_css_value(StyleComponentValueRule const&); RefPtr parse_builtin_value(StyleComponentValueRule const&); RefPtr parse_dynamic_value(StyleComponentValueRule const&); RefPtr parse_length_value(StyleComponentValueRule const&); RefPtr parse_numeric_value(StyleComponentValueRule const&); RefPtr parse_identifier_value(StyleComponentValueRule const&); RefPtr parse_color_value(StyleComponentValueRule const&); RefPtr parse_string_value(StyleComponentValueRule const&); RefPtr parse_image_value(StyleComponentValueRule const&); template RefPtr parse_comma_separated_value_list(Vector const&, ParseFunction); RefPtr parse_simple_comma_separated_value_list(Vector const&); RefPtr parse_background_value(Vector const&); RefPtr parse_single_background_position_value(TokenStream&); RefPtr parse_single_background_repeat_value(TokenStream&); RefPtr parse_single_background_size_value(TokenStream&); RefPtr parse_border_value(Vector const&); RefPtr parse_border_radius_value(Vector const&); RefPtr parse_border_radius_shorthand_value(Vector const&); RefPtr parse_box_shadow_value(Vector const&); RefPtr parse_flex_value(Vector const&); RefPtr parse_flex_flow_value(Vector const&); RefPtr parse_font_value(Vector const&); RefPtr parse_font_family_value(Vector const&, size_t start_index = 0); RefPtr parse_list_style_value(Vector const&); RefPtr parse_overflow_value(Vector const&); RefPtr parse_text_decoration_value(Vector const&); RefPtr parse_transform_value(Vector const&); // calc() parsing, according to https://www.w3.org/TR/css-values-3/#calc-syntax OwnPtr parse_calc_sum(TokenStream&); OwnPtr parse_calc_product(TokenStream&); Optional parse_calc_value(TokenStream&); OwnPtr parse_calc_number_sum(TokenStream&); OwnPtr parse_calc_number_product(TokenStream&); Optional parse_calc_number_value(TokenStream&); OwnPtr parse_calc_product_part_with_operator(TokenStream&); OwnPtr parse_calc_sum_part_with_operator(TokenStream&); OwnPtr parse_calc_number_product_part_with_operator(TokenStream& tokens); OwnPtr parse_calc_number_sum_part_with_operator(TokenStream&); OwnPtr parse_calc_expression(Vector const&); Result, ParsingResult> parse_complex_selector(TokenStream&, bool allow_starting_combinator); Result parse_compound_selector(TokenStream&); Optional parse_selector_combinator(TokenStream&); Result parse_simple_selector(TokenStream&); NonnullRefPtr parse_media_query(TokenStream&); OwnPtr consume_media_condition(TokenStream&); Optional consume_media_feature(TokenStream&); Optional consume_media_type(TokenStream&); OwnPtr parse_supports_condition(TokenStream&); Optional parse_supports_in_parens(TokenStream&); Optional parse_supports_feature(TokenStream&); static bool has_ignored_vendor_prefix(StringView); ParsingContext m_context; Tokenizer m_tokenizer; Vector m_tokens; TokenStream m_token_stream; }; } namespace Web { RefPtr parse_css(CSS::ParsingContext const&, StringView); RefPtr parse_css_declaration(CSS::ParsingContext const&, StringView); RefPtr parse_css_value(CSS::ParsingContext const&, StringView, CSS::PropertyID property_id = CSS::PropertyID::Invalid); Optional parse_selector(CSS::ParsingContext const&, StringView); RefPtr parse_css_rule(CSS::ParsingContext const&, StringView); RefPtr parse_media_query(CSS::ParsingContext const&, StringView); NonnullRefPtrVector parse_media_query_list(CSS::ParsingContext const&, StringView); RefPtr parse_css_supports(CSS::ParsingContext const&, StringView); RefPtr parse_html_length(DOM::Document const&, StringView); }