diff --git a/Libraries/LibWeb/CSS/CSSStyleValue.cpp b/Libraries/LibWeb/CSS/CSSStyleValue.cpp index a86a6a39fc7..7f935cfa231 100644 --- a/Libraries/LibWeb/CSS/CSSStyleValue.cpp +++ b/Libraries/LibWeb/CSS/CSSStyleValue.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -428,6 +429,13 @@ bool CSSStyleValue::has_auto() const return is_keyword() && as_keyword().keyword() == Keyword::Auto; } +Vector CSSStyleValue::tokenize() const +{ + // This is an inefficient way of producing ComponentValues, but it's guaranteed to work for types that round-trip. + // FIXME: Implement better versions in the subclasses. + return Parser::Parser::create(Parser::ParsingParams {}, to_string(SerializationMode::Normal)).parse_as_list_of_component_values(); +} + int CSSStyleValue::to_font_weight() const { if (is_keyword()) { diff --git a/Libraries/LibWeb/CSS/CSSStyleValue.h b/Libraries/LibWeb/CSS/CSSStyleValue.h index 44270280333..c4315e45d91 100644 --- a/Libraries/LibWeb/CSS/CSSStyleValue.h +++ b/Libraries/LibWeb/CSS/CSSStyleValue.h @@ -397,6 +397,7 @@ public: Keyword to_keyword() const; virtual String to_string(SerializationMode) const = 0; + virtual Vector tokenize() const; [[nodiscard]] int to_font_weight() const; [[nodiscard]] int to_font_slope() const; diff --git a/Libraries/LibWeb/CSS/StyleValues/CSSKeywordValue.cpp b/Libraries/LibWeb/CSS/StyleValues/CSSKeywordValue.cpp index d31abe32497..5e825dcaed9 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CSSKeywordValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/CSSKeywordValue.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2021, Tobias Christiansen - * Copyright (c) 2021-2024, Sam Atkins + * Copyright (c) 2021-2025, Sam Atkins * Copyright (c) 2022-2023, MacDue * * SPDX-License-Identifier: BSD-2-Clause @@ -349,4 +349,9 @@ Optional CSSKeywordValue::to_color(Optional } } +Vector CSSKeywordValue::tokenize() const +{ + return { Parser::Token::create_ident(FlyString::from_utf8_without_validation(string_from_keyword(m_keyword).bytes())) }; +} + } diff --git a/Libraries/LibWeb/CSS/StyleValues/CSSKeywordValue.h b/Libraries/LibWeb/CSS/StyleValues/CSSKeywordValue.h index 6dc79386250..8dc65b5b290 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CSSKeywordValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/CSSKeywordValue.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2021, Tobias Christiansen - * Copyright (c) 2021-2024, Sam Atkins + * Copyright (c) 2021-2025, Sam Atkins * Copyright (c) 2022-2023, MacDue * * SPDX-License-Identifier: BSD-2-Clause @@ -53,6 +53,7 @@ public: virtual bool has_color() const override; virtual Optional to_color(Optional node, CalculationResolutionContext const&) const override; virtual String to_string(SerializationMode) const override; + virtual Vector tokenize() const override; bool properties_equal(CSSKeywordValue const& other) const { return m_keyword == other.m_keyword; } diff --git a/Libraries/LibWeb/CSS/StyleValues/CSSUnitValue.h b/Libraries/LibWeb/CSS/StyleValues/CSSUnitValue.h index 92177c736d0..22e28e3c722 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CSSUnitValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/CSSUnitValue.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Sam Atkins + * Copyright (c) 2024-2025, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,6 +7,8 @@ #pragma once #include +#include +#include #include namespace Web::CSS { @@ -18,6 +20,10 @@ public: virtual double value() const = 0; virtual StringView unit() const = 0; + virtual Vector tokenize() const override + { + return { Parser::Token::create_dimension(value(), FlyString::from_utf8_without_validation(unit().bytes())) }; + } protected: explicit CSSUnitValue(Type type) diff --git a/Libraries/LibWeb/CSS/StyleValues/CustomIdentStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/CustomIdentStyleValue.h index d1ec7e32903..c5979271bea 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CustomIdentStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/CustomIdentStyleValue.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Sam Atkins + * Copyright (c) 2023-2025, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -8,6 +8,7 @@ #include #include +#include namespace Web::CSS { @@ -23,6 +24,10 @@ public: FlyString const& custom_ident() const { return m_custom_ident; } virtual String to_string(SerializationMode) const override { return m_custom_ident.to_string(); } + virtual Vector tokenize() const override + { + return { Parser::Token::create_ident(m_custom_ident) }; + } bool properties_equal(CustomIdentStyleValue const& other) const { return m_custom_ident == other.m_custom_ident; } diff --git a/Libraries/LibWeb/CSS/StyleValues/GuaranteedInvalidStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/GuaranteedInvalidStyleValue.h index 71df96ae515..0f6f60bdfba 100644 --- a/Libraries/LibWeb/CSS/StyleValues/GuaranteedInvalidStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/GuaranteedInvalidStyleValue.h @@ -20,6 +20,10 @@ public: } virtual ~GuaranteedInvalidStyleValue() override = default; virtual String to_string(SerializationMode) const override { return {}; } + virtual Vector tokenize() const override + { + return { Parser::ComponentValue { Parser::GuaranteedInvalidValue {} } }; + } bool properties_equal(GuaranteedInvalidStyleValue const&) const { return true; } diff --git a/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.cpp index 968cdebe8c5..1c3b984654a 100644 --- a/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Sam Atkins + * Copyright (c) 2023-2025, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -13,4 +13,9 @@ String IntegerStyleValue::to_string(SerializationMode) const return String::number(m_value); } +Vector IntegerStyleValue::tokenize() const +{ + return { Parser::Token::create_number(Number { Number::Type::Integer, value() }) }; +} + } diff --git a/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.h index 825701743bc..866f484ce64 100644 --- a/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024, Sam Atkins + * Copyright (c) 2023-2025, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -22,6 +22,7 @@ public: virtual StringView unit() const override { return "number"sv; } virtual String to_string(SerializationMode) const override; + virtual Vector tokenize() const override; bool equals(CSSStyleValue const& other) const override { diff --git a/Libraries/LibWeb/CSS/StyleValues/NumberStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/NumberStyleValue.cpp index cd2cb714941..051fe0a3806 100644 --- a/Libraries/LibWeb/CSS/StyleValues/NumberStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/NumberStyleValue.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2021, Tobias Christiansen - * Copyright (c) 2021-2023, Sam Atkins + * Copyright (c) 2021-2025, Sam Atkins * Copyright (c) 2022-2023, MacDue * * SPDX-License-Identifier: BSD-2-Clause @@ -16,4 +16,9 @@ String NumberStyleValue::to_string(SerializationMode) const return String::number(m_value); } +Vector NumberStyleValue::tokenize() const +{ + return { Parser::Token::create_number(Number { Number::Type::Number, m_value }) }; +} + } diff --git a/Libraries/LibWeb/CSS/StyleValues/NumberStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/NumberStyleValue.h index 4ea8000d7f7..f55076589ae 100644 --- a/Libraries/LibWeb/CSS/StyleValues/NumberStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/NumberStyleValue.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2021, Tobias Christiansen - * Copyright (c) 2021-2024, Sam Atkins + * Copyright (c) 2021-2025, Sam Atkins * Copyright (c) 2022-2023, MacDue * * SPDX-License-Identifier: BSD-2-Clause @@ -25,6 +25,7 @@ public: virtual StringView unit() const override { return "number"sv; } virtual String to_string(SerializationMode) const override; + virtual Vector tokenize() const override; bool equals(CSSStyleValue const& other) const override { diff --git a/Libraries/LibWeb/CSS/StyleValues/PendingSubstitutionStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/PendingSubstitutionStyleValue.h index 10b43012d60..95aae26f515 100644 --- a/Libraries/LibWeb/CSS/StyleValues/PendingSubstitutionStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/PendingSubstitutionStyleValue.h @@ -20,6 +20,11 @@ public: } virtual ~PendingSubstitutionStyleValue() override = default; virtual String to_string(SerializationMode) const override { return {}; } + virtual Vector tokenize() const override + { + // Not sure what to do here, but this isn't valid so returning GIV seems the most correct. + return { Parser::ComponentValue { Parser::GuaranteedInvalidValue {} } }; + } // We shouldn't need to compare these, but in case we do: The nature of them is that their value is unknown, so // consider them all to be unique. diff --git a/Libraries/LibWeb/CSS/StyleValues/RatioStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/RatioStyleValue.h index 0d5af0c0bef..0738060d208 100644 --- a/Libraries/LibWeb/CSS/StyleValues/RatioStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/RatioStyleValue.h @@ -23,6 +23,16 @@ public: Ratio& ratio() { return m_ratio; } virtual String to_string(SerializationMode) const override { return m_ratio.to_string(); } + Vector tokenize() const override + { + return { + Parser::Token::create_number(Number { Number::Type::Number, m_ratio.numerator() }), + Parser::Token::create_whitespace(" "_string), + Parser::Token::create_delim('/'), + Parser::Token::create_whitespace(" "_string), + Parser::Token::create_number(Number { Number::Type::Number, m_ratio.denominator() }), + }; + } bool properties_equal(RatioStyleValue const& other) const { return m_ratio == other.m_ratio; } diff --git a/Libraries/LibWeb/CSS/StyleValues/StringStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/StringStyleValue.h index 4f779259fb0..83e23c80ba4 100644 --- a/Libraries/LibWeb/CSS/StyleValues/StringStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/StringStyleValue.h @@ -22,6 +22,10 @@ public: FlyString const& string_value() const { return m_string; } virtual String to_string(SerializationMode) const override { return serialize_a_string(m_string); } + virtual Vector tokenize() const override + { + return { Parser::Token::create_string(m_string) }; + } bool properties_equal(StringStyleValue const& other) const { return m_string == other.m_string; } diff --git a/Libraries/LibWeb/CSS/StyleValues/StyleValueList.cpp b/Libraries/LibWeb/CSS/StyleValues/StyleValueList.cpp index d958c0387ab..8d8de019c08 100644 --- a/Libraries/LibWeb/CSS/StyleValues/StyleValueList.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/StyleValueList.cpp @@ -8,6 +8,7 @@ */ #include "StyleValueList.h" +#include namespace Web::CSS { @@ -46,4 +47,22 @@ void StyleValueList::set_style_sheet(GC::Ptr style_sheet) const_cast(*value).set_style_sheet(style_sheet); } +Vector StyleValueList::tokenize() const +{ + Vector component_values; + bool first = true; + for (auto const& value : m_properties.values) { + if (first) { + first = false; + } else { + if (m_properties.separator == Separator::Comma) + component_values.empend(Parser::Token::create(Parser::Token::Type::Comma)); + component_values.empend(Parser::Token::create_whitespace(" "_string)); + } + component_values.extend(value->tokenize()); + } + + return component_values; +} + } diff --git a/Libraries/LibWeb/CSS/StyleValues/StyleValueList.h b/Libraries/LibWeb/CSS/StyleValues/StyleValueList.h index 27e6d9a5e35..a8d624148c9 100644 --- a/Libraries/LibWeb/CSS/StyleValues/StyleValueList.h +++ b/Libraries/LibWeb/CSS/StyleValues/StyleValueList.h @@ -34,6 +34,7 @@ public: } virtual String to_string(SerializationMode) const override; + virtual Vector tokenize() const override; bool properties_equal(StyleValueList const& other) const { return m_properties == other.m_properties; } diff --git a/Libraries/LibWeb/CSS/StyleValues/UnresolvedStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/UnresolvedStyleValue.h index aafef9f33a5..4c24f853692 100644 --- a/Libraries/LibWeb/CSS/StyleValues/UnresolvedStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/UnresolvedStyleValue.h @@ -24,6 +24,7 @@ public: virtual ~UnresolvedStyleValue() override = default; virtual String to_string(SerializationMode) const override; + virtual Vector tokenize() const override { return m_values; } Vector const& values() const { return m_values; } bool contains_arbitrary_substitution_function() const { return m_contains_arbitrary_substitution_function; }