Files
ladybird/Userland/Libraries/LibWeb/CSS/Parser/Parser.h
Sam Atkins 87a30418bf LibWeb: Add CSS 'Supports' class
The name is a little awkward, but this corresponds to the condition of a
`@supports` rule or the `CSS.supports("")` function.

A supports query only gets evaluated once, since its condition cannot
change during runtime. (We either support something or we don't, and the
spec specifically mentions that user preferences that disable features
do not affect the result here.) We keep a representation of it around
though, so that it can be serialized if needed. This is a little awkward
since we hold onto a `StyleDeclarationRule` which should be an internal
Parser class. This means making some Parser functions more public.

Potentially we could evaluate the Supports inside the Parser, and have
it only store a String representation of itself. But this works for now.
:^)
2021-10-08 23:02:57 +02:00

261 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Copyright (c) 2020-2021, the SerenityOS developers.
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/NonnullOwnPtrVector.h>
#include <AK/NonnullRefPtrVector.h>
#include <AK/RefPtr.h>
#include <AK/Result.h>
#include <AK/Vector.h>
#include <LibWeb/CSS/MediaQuery.h>
#include <LibWeb/CSS/Parser/DeclarationOrAtRule.h>
#include <LibWeb/CSS/Parser/StyleBlockRule.h>
#include <LibWeb/CSS/Parser/StyleComponentValueRule.h>
#include <LibWeb/CSS/Parser/StyleDeclarationRule.h>
#include <LibWeb/CSS/Parser/StyleFunctionRule.h>
#include <LibWeb/CSS/Parser/StyleRule.h>
#include <LibWeb/CSS/Parser/Tokenizer.h>
#include <LibWeb/CSS/Selector.h>
#include <LibWeb/CSS/StyleValue.h>
namespace Web::CSS {
class CSSStyleSheet;
class CSSRule;
class CSSStyleRule;
struct StyleProperty;
enum class PropertyID;
class ParsingContext {
public:
ParsingContext() = default;
explicit ParsingContext(DOM::Document&);
explicit ParsingContext(DOM::ParentNode&);
bool in_quirks_mode() const;
DOM::Document* 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* m_document { nullptr };
PropertyID m_current_property_id { PropertyID::Invalid };
};
template<typename T>
class TokenStream {
public:
explicit TokenStream(Vector<T> const&);
~TokenStream();
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<T> const& m_tokens;
int m_iterator_offset { -1 };
T make_eof();
T m_eof;
};
class Parser {
public:
Parser(ParsingContext const&, StringView const& input, String const& encoding = "utf-8");
~Parser();
// The normal parser entry point, for parsing stylesheets.
NonnullRefPtr<CSSStyleSheet> parse_as_stylesheet();
// For the content of at-rules such as @media. It differs from "Parse a stylesheet" in the handling of <CDO-token> and <CDC-token>.
NonnullRefPtrVector<CSSRule> 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<CSSRule> parse_as_rule();
// 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();
// 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 declarations 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();
// Contrary to the name, these parse a comma-separated list of selectors, according to the spec.
Optional<SelectorList> parse_as_selector();
Optional<SelectorList> parse_as_relative_selector();
NonnullRefPtrVector<MediaQuery> parse_as_media_query_list();
RefPtr<MediaQuery> parse_as_media_query();
RefPtr<StyleValue> parse_as_css_value(PropertyID);
// FIXME: This is a hack, while CSS::Supports is using a StyleDeclarationRule
[[nodiscard]] Optional<StyleProperty> convert_to_style_property(StyleDeclarationRule const&);
private:
enum class ParsingResult {
Done,
IncludesIgnoredVendorPrefix,
SyntaxError,
};
template<typename T>
NonnullRefPtr<CSSStyleSheet> parse_a_stylesheet(TokenStream<T>&);
template<typename T>
NonnullRefPtrVector<CSSRule> parse_a_list_of_rules(TokenStream<T>&);
template<typename T>
RefPtr<CSSRule> parse_a_rule(TokenStream<T>&);
template<typename T>
Optional<StyleProperty> parse_a_declaration(TokenStream<T>&);
template<typename T>
RefPtr<PropertyOwningCSSStyleDeclaration> parse_a_list_of_declarations(TokenStream<T>&);
template<typename T>
Optional<StyleComponentValueRule> parse_a_component_value(TokenStream<T>&);
template<typename T>
Vector<StyleComponentValueRule> parse_a_list_of_component_values(TokenStream<T>&);
template<typename T>
Vector<Vector<StyleComponentValueRule>> parse_a_comma_separated_list_of_component_values(TokenStream<T>&);
template<typename T>
Result<SelectorList, ParsingResult> parse_a_selector(TokenStream<T>&);
template<typename T>
Result<SelectorList, ParsingResult> parse_a_relative_selector(TokenStream<T>&);
template<typename T>
Result<SelectorList, ParsingResult> parse_a_selector_list(TokenStream<T>&);
template<typename T>
Result<SelectorList, ParsingResult> parse_a_relative_selector_list(TokenStream<T>&);
template<typename T>
NonnullRefPtrVector<MediaQuery> parse_a_media_query_list(TokenStream<T>&);
Optional<Selector::SimpleSelector::ANPlusBPattern> parse_a_n_plus_b_pattern(TokenStream<StyleComponentValueRule>&);
[[nodiscard]] NonnullRefPtrVector<StyleRule> consume_a_list_of_rules(bool top_level);
template<typename T>
[[nodiscard]] NonnullRefPtrVector<StyleRule> consume_a_list_of_rules(TokenStream<T>&, bool top_level);
[[nodiscard]] NonnullRefPtr<StyleRule> consume_an_at_rule();
template<typename T>
[[nodiscard]] NonnullRefPtr<StyleRule> consume_an_at_rule(TokenStream<T>&);
[[nodiscard]] RefPtr<StyleRule> consume_a_qualified_rule();
template<typename T>
[[nodiscard]] RefPtr<StyleRule> consume_a_qualified_rule(TokenStream<T>&);
[[nodiscard]] Vector<DeclarationOrAtRule> consume_a_list_of_declarations();
template<typename T>
[[nodiscard]] Vector<DeclarationOrAtRule> consume_a_list_of_declarations(TokenStream<T>&);
[[nodiscard]] Optional<StyleDeclarationRule> consume_a_declaration();
template<typename T>
[[nodiscard]] Optional<StyleDeclarationRule> consume_a_declaration(TokenStream<T>&);
[[nodiscard]] StyleComponentValueRule consume_a_component_value();
template<typename T>
[[nodiscard]] StyleComponentValueRule consume_a_component_value(TokenStream<T>&);
[[nodiscard]] NonnullRefPtr<StyleBlockRule> consume_a_simple_block();
template<typename T>
[[nodiscard]] NonnullRefPtr<StyleBlockRule> consume_a_simple_block(TokenStream<T>&);
[[nodiscard]] NonnullRefPtr<StyleFunctionRule> consume_a_function();
template<typename T>
[[nodiscard]] NonnullRefPtr<StyleFunctionRule> consume_a_function(TokenStream<T>&);
[[nodiscard]] RefPtr<CSSRule> convert_to_rule(NonnullRefPtr<StyleRule>);
[[nodiscard]] RefPtr<PropertyOwningCSSStyleDeclaration> convert_to_declaration(NonnullRefPtr<StyleBlockRule>);
static Optional<float> try_parse_float(StringView string);
static Optional<Color> parse_color(ParsingContext const&, StyleComponentValueRule const&);
static Optional<Length> parse_length(ParsingContext const&, StyleComponentValueRule const&);
static Optional<AK::URL> parse_url_function(ParsingContext const&, StyleComponentValueRule const&);
Result<NonnullRefPtr<StyleValue>, ParsingResult> parse_css_value(PropertyID, TokenStream<StyleComponentValueRule>&);
static RefPtr<StyleValue> parse_css_value(ParsingContext const&, StyleComponentValueRule const&);
static RefPtr<StyleValue> parse_builtin_value(ParsingContext const&, StyleComponentValueRule const&);
static RefPtr<StyleValue> parse_dynamic_value(ParsingContext const&, StyleComponentValueRule const&);
static RefPtr<StyleValue> parse_length_value(ParsingContext const&, StyleComponentValueRule const&);
static RefPtr<StyleValue> parse_numeric_value(ParsingContext const&, StyleComponentValueRule const&);
static RefPtr<StyleValue> parse_identifier_value(ParsingContext const&, StyleComponentValueRule const&);
static RefPtr<StyleValue> parse_color_value(ParsingContext const&, StyleComponentValueRule const&);
static RefPtr<StyleValue> parse_string_value(ParsingContext const&, StyleComponentValueRule const&);
static RefPtr<StyleValue> parse_image_value(ParsingContext const&, StyleComponentValueRule const&);
static RefPtr<StyleValue> parse_background_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_background_image_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_background_repeat_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_border_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_border_radius_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_border_radius_shorthand_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_box_shadow_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_flex_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_flex_flow_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_font_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_font_family_value(ParsingContext const&, Vector<StyleComponentValueRule> const&, size_t start_index = 0);
static RefPtr<StyleValue> parse_list_style_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_overflow_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_text_decoration_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
static RefPtr<StyleValue> parse_transform_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
// calc() parsing, according to https://www.w3.org/TR/css-values-3/#calc-syntax
static OwnPtr<CalculatedStyleValue::CalcSum> parse_calc_sum(ParsingContext const&, TokenStream<StyleComponentValueRule>&);
static OwnPtr<CalculatedStyleValue::CalcProduct> parse_calc_product(ParsingContext const&, TokenStream<StyleComponentValueRule>&);
static Optional<CalculatedStyleValue::CalcValue> parse_calc_value(ParsingContext const&, TokenStream<StyleComponentValueRule>&);
static OwnPtr<CalculatedStyleValue::CalcNumberSum> parse_calc_number_sum(ParsingContext const&, TokenStream<StyleComponentValueRule>&);
static OwnPtr<CalculatedStyleValue::CalcNumberProduct> parse_calc_number_product(ParsingContext const&, TokenStream<StyleComponentValueRule>&);
static Optional<CalculatedStyleValue::CalcNumberValue> parse_calc_number_value(ParsingContext const&, TokenStream<StyleComponentValueRule>&);
static OwnPtr<CalculatedStyleValue::CalcProductPartWithOperator> parse_calc_product_part_with_operator(ParsingContext const&, TokenStream<StyleComponentValueRule>&);
static OwnPtr<CalculatedStyleValue::CalcSumPartWithOperator> parse_calc_sum_part_with_operator(ParsingContext const&, TokenStream<StyleComponentValueRule>&);
static OwnPtr<CalculatedStyleValue::CalcNumberProductPartWithOperator> parse_calc_number_product_part_with_operator(ParsingContext const&, TokenStream<StyleComponentValueRule>& tokens);
static OwnPtr<CalculatedStyleValue::CalcNumberSumPartWithOperator> parse_calc_number_sum_part_with_operator(ParsingContext const&, TokenStream<StyleComponentValueRule>&);
static OwnPtr<CalculatedStyleValue::CalcSum> parse_calc_expression(ParsingContext const&, Vector<StyleComponentValueRule> const&);
Result<NonnullRefPtr<Selector>, ParsingResult> parse_complex_selector(TokenStream<StyleComponentValueRule>&, bool allow_starting_combinator);
Result<Selector::CompoundSelector, ParsingResult> parse_compound_selector(TokenStream<StyleComponentValueRule>&);
Optional<Selector::Combinator> parse_selector_combinator(TokenStream<StyleComponentValueRule>&);
Result<Selector::SimpleSelector, ParsingResult> parse_simple_selector(TokenStream<StyleComponentValueRule>&);
NonnullRefPtr<MediaQuery> parse_media_query(TokenStream<StyleComponentValueRule>&);
OwnPtr<MediaQuery::MediaCondition> consume_media_condition(TokenStream<StyleComponentValueRule>&);
Optional<MediaQuery::MediaFeature> consume_media_feature(TokenStream<StyleComponentValueRule>&);
Optional<MediaQuery::MediaType> consume_media_type(TokenStream<StyleComponentValueRule>&);
static bool has_ignored_vendor_prefix(StringView const&);
ParsingContext m_context;
Tokenizer m_tokenizer;
Vector<Token> m_tokens;
TokenStream<Token> m_token_stream;
};
}
namespace Web {
RefPtr<CSS::CSSStyleSheet> parse_css(CSS::ParsingContext const&, StringView const&);
RefPtr<CSS::PropertyOwningCSSStyleDeclaration> parse_css_declaration(CSS::ParsingContext const&, StringView const&);
RefPtr<CSS::StyleValue> parse_css_value(CSS::ParsingContext const&, StringView const&, CSS::PropertyID property_id = CSS::PropertyID::Invalid);
Optional<CSS::SelectorList> parse_selector(CSS::ParsingContext const&, StringView const&);
RefPtr<CSS::CSSRule> parse_css_rule(CSS::ParsingContext const&, StringView);
RefPtr<CSS::MediaQuery> parse_media_query(CSS::ParsingContext const&, StringView const&);
NonnullRefPtrVector<CSS::MediaQuery> parse_media_query_list(CSS::ParsingContext const&, StringView const&);
RefPtr<CSS::StyleValue> parse_html_length(DOM::Document const&, StringView const&);
}