diff --git a/Libraries/LibWeb/CSS/CSSCounterStyleRule.cpp b/Libraries/LibWeb/CSS/CSSCounterStyleRule.cpp index 4b46de9534d..04f427d9c97 100644 --- a/Libraries/LibWeb/CSS/CSSCounterStyleRule.cpp +++ b/Libraries/LibWeb/CSS/CSSCounterStyleRule.cpp @@ -16,12 +16,12 @@ namespace Web::CSS { GC_DEFINE_ALLOCATOR(CSSCounterStyleRule); -GC::Ref CSSCounterStyleRule::create(JS::Realm& realm, FlyString name, RefPtr system, RefPtr negative, RefPtr prefix, RefPtr suffix, RefPtr range) +GC::Ref CSSCounterStyleRule::create(JS::Realm& realm, FlyString name, RefPtr system, RefPtr negative, RefPtr prefix, RefPtr suffix, RefPtr range, RefPtr pad) { - return realm.create(realm, name, move(system), move(negative), move(prefix), move(suffix), move(range)); + return realm.create(realm, name, move(system), move(negative), move(prefix), move(suffix), move(range), move(pad)); } -CSSCounterStyleRule::CSSCounterStyleRule(JS::Realm& realm, FlyString name, RefPtr system, RefPtr negative, RefPtr prefix, RefPtr suffix, RefPtr range) +CSSCounterStyleRule::CSSCounterStyleRule(JS::Realm& realm, FlyString name, RefPtr system, RefPtr negative, RefPtr prefix, RefPtr suffix, RefPtr range, RefPtr pad) : CSSRule(realm, Type::CounterStyle) , m_name(move(name)) , m_system(move(system)) @@ -29,6 +29,7 @@ CSSCounterStyleRule::CSSCounterStyleRule(JS::Realm& realm, FlyString name, RefPt , m_prefix(move(prefix)) , m_suffix(move(suffix)) , m_range(move(range)) + , m_pad(move(pad)) { } @@ -67,6 +68,12 @@ String CSSCounterStyleRule::serialized() const builder.append(';'); } + if (m_pad) { + builder.append(" pad: "sv); + m_pad->serialize(builder, SerializationMode::Normal); + builder.append(';'); + } + builder.append(" }"sv); return MUST(builder.to_string()); } @@ -185,6 +192,22 @@ void CSSCounterStyleRule::set_range(FlyString const& range) m_range = value; } +FlyString CSSCounterStyleRule::pad() const +{ + if (!m_pad) + return ""_fly_string; + + return m_pad->to_string(SerializationMode::Normal); +} + +void CSSCounterStyleRule::set_pad(FlyString const& pad) +{ + Parser::ParsingParams parsing_params { realm() }; + + if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, CSS::DescriptorID::Pad, pad)) + m_pad = value; +} + void CSSCounterStyleRule::initialize(JS::Realm& realm) { WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSCounterStyleRule); diff --git a/Libraries/LibWeb/CSS/CSSCounterStyleRule.h b/Libraries/LibWeb/CSS/CSSCounterStyleRule.h index b6a135c7c17..d8410c2be5d 100644 --- a/Libraries/LibWeb/CSS/CSSCounterStyleRule.h +++ b/Libraries/LibWeb/CSS/CSSCounterStyleRule.h @@ -16,7 +16,7 @@ class CSSCounterStyleRule : public CSSRule { GC_DECLARE_ALLOCATOR(CSSCounterStyleRule); public: - static GC::Ref create(JS::Realm&, FlyString name, RefPtr system, RefPtr negative, RefPtr prefix, RefPtr suffix, RefPtr range); + static GC::Ref create(JS::Realm&, FlyString name, RefPtr system, RefPtr negative, RefPtr prefix, RefPtr suffix, RefPtr range, RefPtr pad); virtual ~CSSCounterStyleRule() = default; virtual String serialized() const override; @@ -39,6 +39,9 @@ public: FlyString range() const; void set_range(FlyString const& range); + FlyString pad() const; + void set_pad(FlyString const& pad); + // https://drafts.csswg.org/css-counter-styles-3/#non-overridable-counter-style-names static bool matches_non_overridable_counter_style_name(FlyString const& name) { @@ -47,7 +50,7 @@ public: } protected: - CSSCounterStyleRule(JS::Realm&, FlyString name, RefPtr system, RefPtr negative, RefPtr prefix, RefPtr suffix, RefPtr range); + CSSCounterStyleRule(JS::Realm&, FlyString name, RefPtr system, RefPtr negative, RefPtr prefix, RefPtr suffix, RefPtr range, RefPtr pad); FlyString m_name; RefPtr m_system; @@ -55,6 +58,7 @@ protected: RefPtr m_prefix; RefPtr m_suffix; RefPtr m_range; + RefPtr m_pad; virtual void initialize(JS::Realm&) override; }; diff --git a/Libraries/LibWeb/CSS/CSSCounterStyleRule.idl b/Libraries/LibWeb/CSS/CSSCounterStyleRule.idl index 6f6c749f9df..09544c64d9b 100644 --- a/Libraries/LibWeb/CSS/CSSCounterStyleRule.idl +++ b/Libraries/LibWeb/CSS/CSSCounterStyleRule.idl @@ -11,7 +11,7 @@ interface CSSCounterStyleRule : CSSRule { attribute CSSOMString prefix; attribute CSSOMString suffix; attribute CSSOMString range; - [FIXME] attribute CSSOMString pad; + attribute CSSOMString pad; [FIXME] attribute CSSOMString speakAs; [FIXME] attribute CSSOMString fallback; }; diff --git a/Libraries/LibWeb/CSS/Descriptors.json b/Libraries/LibWeb/CSS/Descriptors.json index 7c006ee5a0d..1a3fc24bc15 100644 --- a/Libraries/LibWeb/CSS/Descriptors.json +++ b/Libraries/LibWeb/CSS/Descriptors.json @@ -222,6 +222,12 @@ "syntax": [ "" ] + }, + "pad": { + "initial": "0 \"\"", + "syntax": [ + "" + ] } } } diff --git a/Libraries/LibWeb/CSS/Parser/DescriptorParsing.cpp b/Libraries/LibWeb/CSS/Parser/DescriptorParsing.cpp index 78f9a5fcb0c..df7ebeed74c 100644 --- a/Libraries/LibWeb/CSS/Parser/DescriptorParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/DescriptorParsing.cpp @@ -104,6 +104,11 @@ Parser::ParseErrorOr> Parser::parse_descriptor_v return StyleValueList::create({ first_symbol.release_nonnull(), second_symbol.release_nonnull() }, StyleValueList::Separator::Space, StyleValueList::Collapsible::No); } + case DescriptorMetadata::ValueType::CounterStylePad: { + // https://drafts.csswg.org/css-counter-styles-3/#counter-style-pad + // && + return parse_nonnegative_integer_symbol_pair_value(tokens); + } case DescriptorMetadata::ValueType::CounterStyleRange: { // https://drafts.csswg.org/css-counter-styles-3/#counter-style-range // [ [ | infinite ]{2} ]# | auto diff --git a/Libraries/LibWeb/CSS/Parser/Parser.h b/Libraries/LibWeb/CSS/Parser/Parser.h index 60bd7f7127f..1569cdac45c 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Libraries/LibWeb/CSS/Parser/Parser.h @@ -411,6 +411,7 @@ private: RefPtr parse_counter_value(TokenStream&); Optional parse_counter_style_name(TokenStream&); RefPtr parse_symbol_value(TokenStream&); + RefPtr parse_nonnegative_integer_symbol_pair_value(TokenStream&); enum class AllowReversed { No, Yes, diff --git a/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp b/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp index c0953830fde..f35f8e18c3d 100644 --- a/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp @@ -877,6 +877,7 @@ GC::Ptr Parser::convert_to_counter_style_rule(AtRule const& RefPtr prefix; RefPtr suffix; RefPtr range; + RefPtr pad; rule.for_each_as_declaration_list([&](auto& declaration) { auto const& descriptor = convert_to_descriptor(AtRuleID::CounterStyle, declaration); @@ -899,12 +900,15 @@ GC::Ptr Parser::convert_to_counter_style_rule(AtRule const& case DescriptorID::Range: range = descriptor->value; break; + case DescriptorID::Pad: + pad = descriptor->value; + break; default: VERIFY_NOT_REACHED(); } }); - return CSSCounterStyleRule::create(realm(), name.release_value(), move(system), move(negative), move(prefix), move(suffix), move(range)); + return CSSCounterStyleRule::create(realm(), name.release_value(), move(system), move(negative), move(prefix), move(suffix), move(range), move(pad)); } GC::Ptr Parser::convert_to_font_face_rule(AtRule const& rule) diff --git a/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp b/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp index 623ca3d8d4a..18962d2cf2f 100644 --- a/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp @@ -2733,6 +2733,48 @@ RefPtr Parser::parse_symbol_value(TokenStream& return nullptr; } +RefPtr Parser::parse_nonnegative_integer_symbol_pair_value(TokenStream& tokens) +{ + auto transaction = tokens.begin_transaction(); + tokens.discard_whitespace(); + + RefPtr integer; + RefPtr symbol; + + while (tokens.has_next_token()) { + if (auto integer_value = parse_integer_value(tokens)) { + if (integer) + return nullptr; + + // FIXME: Do we need to support CalculatedStyleValue here? + if (!integer_value->is_integer() || integer_value->as_integer().integer() < 0) + return nullptr; + + integer = integer_value; + tokens.discard_whitespace(); + continue; + } + + if (auto symbol_value = parse_symbol_value(tokens)) { + if (symbol) + return nullptr; + + symbol = symbol_value; + tokens.discard_whitespace(); + continue; + } + + break; + } + + if (!integer || !symbol) + return nullptr; + + transaction.commit(); + + return StyleValueList::create({ integer.release_nonnull(), symbol.release_nonnull() }, StyleValueList::Separator::Space); +} + RefPtr Parser::parse_ratio_value(TokenStream& tokens) { if (auto ratio = parse_ratio(tokens); ratio.has_value()) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSDescriptors.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSDescriptors.cpp index 3e355984c65..bdc8f8226a1 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSDescriptors.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSDescriptors.cpp @@ -119,6 +119,7 @@ struct DescriptorMetadata { // FIXME: Parse the grammar instead of hard-coding all the options! CounterStyleSystem, CounterStyleNegative, + CounterStylePad, CounterStyleRange, CropOrCross, FamilyName, @@ -411,6 +412,8 @@ DescriptorMetadata get_descriptor_metadata(AtRuleID at_rule_id, DescriptorID des return "Symbol"_string; if (syntax_string == ""sv) return "CounterStyleRange"_string; + if (syntax_string == ""sv) + return "CounterStylePad"_string; dbgln("Unrecognized value type: `{}`", syntax_string); VERIFY_NOT_REACHED(); }(); diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-counter-styles/counter-style-at-rule/pad-syntax.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-counter-styles/counter-style-at-rule/pad-syntax.txt index 6e04b84824c..f3a4c665f64 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-counter-styles/counter-style-at-rule/pad-syntax.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-counter-styles/counter-style-at-rule/pad-syntax.txt @@ -2,13 +2,12 @@ Harness status: OK Found 9 tests -6 Pass -3 Fail +9 Pass Pass @counter-style 'pad: 10' is invalid Pass @counter-style 'pad: "X"' is invalid -Fail @counter-style 'pad: 0 "X"' is valid -Fail @counter-style 'pad: 10 "X"' is valid -Fail @counter-style 'pad: "X" 10' is valid +Pass @counter-style 'pad: 0 "X"' is valid +Pass @counter-style 'pad: 10 "X"' is valid +Pass @counter-style 'pad: "X" 10' is valid Pass @counter-style 'pad: -1 "X"' is invalid Pass @counter-style 'pad: "X" -1' is invalid Pass @counter-style 'pad: 10 "X" "Y"' is invalid diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-counter-styles/idlharness.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-counter-styles/idlharness.txt index 7ee7b822461..f4ceba5692a 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-counter-styles/idlharness.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-counter-styles/idlharness.txt @@ -2,8 +2,8 @@ Harness status: OK Found 37 tests -27 Pass -10 Fail +29 Pass +8 Fail Pass idl_test setup Pass idl_test validation Pass Partial interface CSSRule: original interface defined @@ -22,7 +22,7 @@ Pass CSSCounterStyleRule interface: attribute negative Pass CSSCounterStyleRule interface: attribute prefix Pass CSSCounterStyleRule interface: attribute suffix Pass CSSCounterStyleRule interface: attribute range -Fail CSSCounterStyleRule interface: attribute pad +Pass CSSCounterStyleRule interface: attribute pad Fail CSSCounterStyleRule interface: attribute speakAs Fail CSSCounterStyleRule interface: attribute fallback Pass CSSCounterStyleRule must be primary interface of counter @@ -35,7 +35,7 @@ Pass CSSCounterStyleRule interface: counter must inherit property "negative" wit Pass CSSCounterStyleRule interface: counter must inherit property "prefix" with the proper type Pass CSSCounterStyleRule interface: counter must inherit property "suffix" with the proper type Pass CSSCounterStyleRule interface: counter must inherit property "range" with the proper type -Fail CSSCounterStyleRule interface: counter must inherit property "pad" with the proper type +Pass CSSCounterStyleRule interface: counter must inherit property "pad" with the proper type Fail CSSCounterStyleRule interface: counter must inherit property "speakAs" with the proper type Fail CSSCounterStyleRule interface: counter must inherit property "fallback" with the proper type Pass CSSRule interface: counter must inherit property "COUNTER_STYLE_RULE" with the proper type