diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 5ab7fddfc9e..540f20dea19 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -84,6 +84,8 @@ set(SOURCES CSS/CSSNamespaceRule.cpp CSS/CSSNestedDeclarations.cpp CSS/CSSNumericType.cpp + CSS/CSSPageRule.cpp + CSS/CSSPageDescriptors.cpp CSS/CSSPropertyRule.cpp CSS/CSSRule.cpp CSS/CSSRuleList.cpp diff --git a/Libraries/LibWeb/CSS/CSSPageDescriptors.cpp b/Libraries/LibWeb/CSS/CSSPageDescriptors.cpp new file mode 100644 index 00000000000..07019d9a0b1 --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSPageDescriptors.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +namespace Web::CSS { + +GC_DEFINE_ALLOCATOR(CSSPageDescriptors); + +GC::Ref CSSPageDescriptors::create(JS::Realm& realm, Vector descriptors) +{ + return realm.create(realm, move(descriptors)); +} + +CSSPageDescriptors::CSSPageDescriptors(JS::Realm& realm, Vector descriptors) + : CSSDescriptors(realm, AtRuleID::Page, move(descriptors)) +{ +} + +CSSPageDescriptors::~CSSPageDescriptors() = default; + +void CSSPageDescriptors::initialize(JS::Realm& realm) +{ + WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSPageDescriptors); + Base::initialize(realm); +} + +WebIDL::ExceptionOr CSSPageDescriptors::set_margin(StringView value) +{ + return set_property("margin"sv, value, ""sv); +} + +String CSSPageDescriptors::margin() const +{ + return get_property_value("margin"sv); +} + +WebIDL::ExceptionOr CSSPageDescriptors::set_margin_top(StringView value) +{ + return set_property("margin-top"sv, value, ""sv); +} + +String CSSPageDescriptors::margin_top() const +{ + return get_property_value("margin-top"sv); +} + +WebIDL::ExceptionOr CSSPageDescriptors::set_margin_right(StringView value) +{ + return set_property("margin-right"sv, value, ""sv); +} + +String CSSPageDescriptors::margin_right() const +{ + return get_property_value("margin-right"sv); +} + +WebIDL::ExceptionOr CSSPageDescriptors::set_margin_bottom(StringView value) +{ + return set_property("margin-bottom"sv, value, ""sv); +} + +String CSSPageDescriptors::margin_bottom() const +{ + return get_property_value("margin-bottom"sv); +} + +WebIDL::ExceptionOr CSSPageDescriptors::set_margin_left(StringView value) +{ + return set_property("margin-left"sv, value, ""sv); +} + +String CSSPageDescriptors::margin_left() const +{ + return get_property_value("margin-left"sv); +} + +WebIDL::ExceptionOr CSSPageDescriptors::set_size(StringView value) +{ + return set_property("size"sv, value, ""sv); +} + +String CSSPageDescriptors::size() const +{ + return get_property_value("size"sv); +} + +WebIDL::ExceptionOr CSSPageDescriptors::set_page_orientation(StringView value) +{ + return set_property("page-orientation"sv, value, ""sv); +} + +String CSSPageDescriptors::page_orientation() const +{ + return get_property_value("page-orientation"sv); +} + +WebIDL::ExceptionOr CSSPageDescriptors::set_marks(StringView value) +{ + return set_property("marks"sv, value, ""sv); +} + +String CSSPageDescriptors::marks() const +{ + return get_property_value("marks"sv); +} + +WebIDL::ExceptionOr CSSPageDescriptors::set_bleed(StringView value) +{ + return set_property("bleed"sv, value, ""sv); +} + +String CSSPageDescriptors::bleed() const +{ + return get_property_value("bleed"sv); +} + +} diff --git a/Libraries/LibWeb/CSS/CSSPageDescriptors.h b/Libraries/LibWeb/CSS/CSSPageDescriptors.h new file mode 100644 index 00000000000..735880abbc5 --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSPageDescriptors.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::CSS { + +// https://drafts.csswg.org/cssom/#csspagedescriptors +class CSSPageDescriptors final : public CSSDescriptors { + WEB_PLATFORM_OBJECT(CSSPageDescriptors, CSSDescriptors); + GC_DECLARE_ALLOCATOR(CSSPageDescriptors); + +public: + [[nodiscard]] static GC::Ref create(JS::Realm&, Vector); + + virtual ~CSSPageDescriptors() override; + + virtual void initialize(JS::Realm&) override; + + WebIDL::ExceptionOr set_margin(StringView value); + String margin() const; + + WebIDL::ExceptionOr set_margin_top(StringView value); + String margin_top() const; + + WebIDL::ExceptionOr set_margin_right(StringView value); + String margin_right() const; + + WebIDL::ExceptionOr set_margin_bottom(StringView value); + String margin_bottom() const; + + WebIDL::ExceptionOr set_margin_left(StringView value); + String margin_left() const; + + WebIDL::ExceptionOr set_size(StringView value); + String size() const; + + WebIDL::ExceptionOr set_page_orientation(StringView value); + String page_orientation() const; + + WebIDL::ExceptionOr set_marks(StringView value); + String marks() const; + + WebIDL::ExceptionOr set_bleed(StringView value); + String bleed() const; + +private: + CSSPageDescriptors(JS::Realm&, Vector); +}; + +} diff --git a/Libraries/LibWeb/CSS/CSSPageDescriptors.idl b/Libraries/LibWeb/CSS/CSSPageDescriptors.idl new file mode 100644 index 00000000000..eaf1026ea64 --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSPageDescriptors.idl @@ -0,0 +1,20 @@ +#import + +// https://drafts.csswg.org/cssom/#csspagedescriptors +[Exposed=Window] +interface CSSPageDescriptors : CSSStyleDeclaration { + [LegacyNullToEmptyString] attribute CSSOMString margin; + [LegacyNullToEmptyString, AttributeCallbackName=margin_top_regular, ImplementedAs=margin_top] attribute CSSOMString marginTop; + [LegacyNullToEmptyString, AttributeCallbackName=margin_right_regular, ImplementedAs=margin_right] attribute CSSOMString marginRight; + [LegacyNullToEmptyString, AttributeCallbackName=margin_bottom_regular, ImplementedAs=margin_bottom] attribute CSSOMString marginBottom; + [LegacyNullToEmptyString, AttributeCallbackName=margin_left_regular, ImplementedAs=margin_left] attribute CSSOMString marginLeft; + [LegacyNullToEmptyString, AttributeCallbackName=margin_top_dashed, ImplementedAs=margin_top] attribute CSSOMString margin-top; + [LegacyNullToEmptyString, AttributeCallbackName=margin_right_dashed, ImplementedAs=margin_right] attribute CSSOMString margin-right; + [LegacyNullToEmptyString, AttributeCallbackName=margin_bottom_dashed, ImplementedAs=margin_bottom] attribute CSSOMString margin-bottom; + [LegacyNullToEmptyString, AttributeCallbackName=margin_left_dashed, ImplementedAs=margin_left] attribute CSSOMString margin-left; + [LegacyNullToEmptyString] attribute CSSOMString size; + [LegacyNullToEmptyString, AttributeCallbackName=page_orientation_regular, ImplementedAs=page_orientation] attribute CSSOMString pageOrientation; + [LegacyNullToEmptyString, AttributeCallbackName=page_orientation_dashed, ImplementedAs=page_orientation] attribute CSSOMString page-orientation; + [LegacyNullToEmptyString] attribute CSSOMString marks; + [LegacyNullToEmptyString] attribute CSSOMString bleed; +}; diff --git a/Libraries/LibWeb/CSS/CSSPageRule.cpp b/Libraries/LibWeb/CSS/CSSPageRule.cpp new file mode 100644 index 00000000000..4acd8b73eea --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSPageRule.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include + +namespace Web::CSS { + +GC_DEFINE_ALLOCATOR(CSSPageRule); + +GC::Ref CSSPageRule::create(JS::Realm& realm, SelectorList&& selectors, GC::Ref style, CSSRuleList& rules) +{ + return realm.create(realm, move(selectors), style, rules); +} + +CSSPageRule::CSSPageRule(JS::Realm& realm, SelectorList&& selectors, GC::Ref style, CSSRuleList& rules) + : CSSGroupingRule(realm, rules, Type::Page) + , m_selectors(move(selectors)) + , m_style(style) +{ + m_style->set_parent_rule(*this); +} + +void CSSPageRule::initialize(JS::Realm& realm) +{ + WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSPageRule); + Base::initialize(realm); +} + +// https://drafts.csswg.org/cssom/#dom-csspagerule-selectortext +String CSSPageRule::selector_text() const +{ + // The selectorText attribute, on getting, must return the result of serializing the associated selector list. + return serialize_a_group_of_selectors(m_selectors); +} + +// https://drafts.csswg.org/cssom/#dom-csspagerule-selectortext +void CSSPageRule::set_selector_text(StringView) +{ + // FIXME: On setting the selectorText attribute these steps must be run: + // 1. Run the parse a list of CSS page selectors algorithm on the given value. + // 2. If the algorithm returns a non-null value replace the associated selector list with the returned value. + // 3. Otherwise, if the algorithm returns a null value, do nothing. +} + +// https://drafts.csswg.org/cssom/#ref-for-csspagerule +String CSSPageRule::serialized() const +{ + auto& descriptors = *m_style; + + StringBuilder builder; + + // AD-HOC: There's no spec for this yet. + builder.append("@page "sv); + if (auto selector = selector_text(); !selector.is_empty()) + builder.appendff("{} ", selector); + builder.append("{ "sv); + if (descriptors.length() > 0) { + builder.append(descriptors.serialized()); + builder.append(' '); + } + builder.append("}"sv); + + return builder.to_string_without_validation(); +} + +void CSSPageRule::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_style); +} + +} diff --git a/Libraries/LibWeb/CSS/CSSPageRule.h b/Libraries/LibWeb/CSS/CSSPageRule.h new file mode 100644 index 00000000000..47cef00860a --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSPageRule.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Web::CSS { + +// https://drafts.csswg.org/css-page-3/#at-ruledef-page +class CSSPageRule final : public CSSGroupingRule { + WEB_PLATFORM_OBJECT(CSSPageRule, CSSGroupingRule); + GC_DECLARE_ALLOCATOR(CSSPageRule); + +public: + [[nodiscard]] static GC::Ref create(JS::Realm&, SelectorList&&, GC::Ref, CSSRuleList&); + + virtual ~CSSPageRule() override = default; + + String selector_text() const; + void set_selector_text(StringView); + + GC::Ref style() { return m_style; } + GC::Ref descriptors() const { return m_style; } + +private: + CSSPageRule(JS::Realm&, SelectorList&&, GC::Ref, CSSRuleList&); + + virtual void initialize(JS::Realm&) override; + virtual String serialized() const override; + virtual void visit_edges(Visitor&) override; + + SelectorList m_selectors; + GC::Ref m_style; +}; + +} diff --git a/Libraries/LibWeb/CSS/CSSPageRule.idl b/Libraries/LibWeb/CSS/CSSPageRule.idl new file mode 100644 index 00000000000..1cf8876544c --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSPageRule.idl @@ -0,0 +1,9 @@ +#import +#import + +// https://drafts.csswg.org/cssom/#csspagerule +[Exposed=Window] +interface CSSPageRule : CSSGroupingRule { + attribute CSSOMString selectorText; + [SameObject, PutForwards=cssText] readonly attribute CSSPageDescriptors style; +}; diff --git a/Libraries/LibWeb/CSS/CSSRule.cpp b/Libraries/LibWeb/CSS/CSSRule.cpp index d2856a95d92..fe7108b6844 100644 --- a/Libraries/LibWeb/CSS/CSSRule.cpp +++ b/Libraries/LibWeb/CSS/CSSRule.cpp @@ -94,6 +94,7 @@ FlyString const& CSSRule::parent_layer_internal_qualified_name_slow_case() const case Type::Supports: case Type::NestedDeclarations: case Type::Property: + case Type::Page: break; } } diff --git a/Libraries/LibWeb/CSS/CSSRule.h b/Libraries/LibWeb/CSS/CSSRule.h index ab0dda8d390..b3ee377024c 100644 --- a/Libraries/LibWeb/CSS/CSSRule.h +++ b/Libraries/LibWeb/CSS/CSSRule.h @@ -28,6 +28,7 @@ public: Import = 3, Media = 4, FontFace = 5, + Page = 6, Keyframes = 7, Keyframe = 8, Namespace = 10, diff --git a/Libraries/LibWeb/CSS/CSSRuleList.cpp b/Libraries/LibWeb/CSS/CSSRuleList.cpp index 4b46b589f19..e2ffcf08956 100644 --- a/Libraries/LibWeb/CSS/CSSRuleList.cpp +++ b/Libraries/LibWeb/CSS/CSSRuleList.cpp @@ -164,6 +164,7 @@ void CSSRuleList::for_each_effective_rule(TraversalOrder order, Function" + ] + }, + "margin-bottom": { + "initial": "0", + "syntax": [ + "<'margin-bottom'>" + ] + }, + "margin-left": { + "initial": "0", + "syntax": [ + "<'margin-left'>" + ] + }, + "margin-right": { + "initial": "0", + "syntax": [ + "<'margin-right'>" + ] + }, + "margin-top": { + "initial": "0", + "syntax": [ + "<'margin-top'>" + ] + } + } + }, "property": { "spec": "https://drafts.css-houdini.org/css-properties-values-api/#at-property-rule", "descriptors": { diff --git a/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Libraries/LibWeb/CSS/Parser/Parser.cpp index 09d7cbb997b..14c11983aa1 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -1375,6 +1375,8 @@ Vector Parser::parse_as_descriptor_declaration_block(AtRuleID at_rul switch (at_rule_id) { case AtRuleID::FontFace: return RuleContext::AtFontFace; + case AtRuleID::Page: + return RuleContext::AtPage; case AtRuleID::Property: return RuleContext::AtProperty; } @@ -1434,8 +1436,9 @@ bool Parser::is_valid_in_the_current_context(Declaration const&) const return m_rule_context.contains_slow(RuleContext::Style); case RuleContext::AtFontFace: + case RuleContext::AtPage: case RuleContext::AtProperty: - // @font-face and @property have descriptor declarations + // @font-face, @page, and @property have descriptor declarations return true; case RuleContext::AtKeyframes: @@ -1482,8 +1485,10 @@ bool Parser::is_valid_in_the_current_context(AtRule const& at_rule) const case RuleContext::AtFontFace: case RuleContext::AtKeyframes: case RuleContext::Keyframe: + case RuleContext::AtPage: case RuleContext::AtProperty: // These can't contain any at-rules + // FIXME: Eventually @page can contain margin-box at-rules: https://drafts.csswg.org/css-page-3/#margin-at-rules return false; } @@ -1522,6 +1527,7 @@ bool Parser::is_valid_in_the_current_context(QualifiedRule const&) const return false; case RuleContext::AtFontFace: + case RuleContext::AtPage: case RuleContext::AtProperty: case RuleContext::Keyframe: // These can't contain qualified rules diff --git a/Libraries/LibWeb/CSS/Parser/Parser.h b/Libraries/LibWeb/CSS/Parser/Parser.h index f65e03574e3..ca2eca83276 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Libraries/LibWeb/CSS/Parser/Parser.h @@ -245,8 +245,9 @@ private: GC::Ptr convert_to_layer_rule(AtRule const&, Nested); GC::Ptr convert_to_media_rule(AtRule const&, Nested); GC::Ptr convert_to_namespace_rule(AtRule const&); - GC::Ptr convert_to_supports_rule(AtRule const&, Nested); + GC::Ptr convert_to_page_rule(AtRule const& rule); GC::Ptr convert_to_property_rule(AtRule const& rule); + GC::Ptr convert_to_supports_rule(AtRule const&, Nested); GC::Ref convert_to_style_declaration(Vector const&); Optional convert_to_style_property(Declaration const&); diff --git a/Libraries/LibWeb/CSS/Parser/RuleContext.cpp b/Libraries/LibWeb/CSS/Parser/RuleContext.cpp index 330bfaada8c..cb12a793c14 100644 --- a/Libraries/LibWeb/CSS/Parser/RuleContext.cpp +++ b/Libraries/LibWeb/CSS/Parser/RuleContext.cpp @@ -27,6 +27,8 @@ RuleContext rule_context_type_for_rule(CSSRule::Type rule_type) return RuleContext::AtLayer; case CSSRule::Type::NestedDeclarations: return RuleContext::Style; + case CSSRule::Type::Page: + return RuleContext::AtPage; case CSSRule::Type::Property: return RuleContext::AtProperty; // Other types shouldn't be trying to create a context. @@ -52,6 +54,8 @@ RuleContext rule_context_type_for_at_rule(FlyString const& name) return RuleContext::AtLayer; if (name == "property") return RuleContext::AtProperty; + if (name == "page") + return RuleContext::AtPage; return RuleContext::Unknown; } diff --git a/Libraries/LibWeb/CSS/Parser/RuleContext.h b/Libraries/LibWeb/CSS/Parser/RuleContext.h index db402b07aed..963a6ef9593 100644 --- a/Libraries/LibWeb/CSS/Parser/RuleContext.h +++ b/Libraries/LibWeb/CSS/Parser/RuleContext.h @@ -22,6 +22,7 @@ enum class RuleContext : u8 { SupportsCondition, AtLayer, AtProperty, + AtPage, }; RuleContext rule_context_type_for_rule(CSSRule::Type); RuleContext rule_context_type_for_at_rule(FlyString const&); diff --git a/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp b/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp index b3e85ae81e2..a49ee5296a2 100644 --- a/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -64,12 +65,15 @@ GC::Ptr Parser::convert_to_rule(Rule const& rule, Nested nested) if (at_rule.name.equals_ignoring_ascii_case("namespace"sv)) return convert_to_namespace_rule(at_rule); - if (at_rule.name.equals_ignoring_ascii_case("supports"sv)) - return convert_to_supports_rule(at_rule, nested); + if (at_rule.name.equals_ignoring_ascii_case("page"sv)) + return convert_to_page_rule(at_rule); if (at_rule.name.equals_ignoring_ascii_case("property"sv)) return convert_to_property_rule(at_rule); + if (at_rule.name.equals_ignoring_ascii_case("supports"sv)) + return convert_to_supports_rule(at_rule, nested); + // FIXME: More at rules! dbgln_if(CSS_PARSER_DEBUG, "Unrecognized CSS at-rule: @{}", at_rule.name); return {}; @@ -596,4 +600,43 @@ GC::Ptr Parser::convert_to_font_face_rule(AtRule const& rule) return CSSFontFaceRule::create(realm(), CSSFontFaceDescriptors::create(realm(), move(descriptors))); } +GC::Ptr Parser::convert_to_page_rule(AtRule const& rule) +{ + // https://drafts.csswg.org/css-page-3/#syntax-page-selector + // @page = @page ? { } + // = # + // = [ ? * ]! + // = : [ left | right | first | blank ] + SelectorList page_selectors; + // FIXME: Parse page selectors + if (rule.prelude.find_first_index_if([](ComponentValue const& it) { return !it.is(Token::Type::Whitespace); }).has_value()) { + dbgln("@page prelude wasn't empty!"); + return nullptr; + } + + GC::RootVector> child_rules { realm().heap() }; + Vector descriptors; + HashTable seen_descriptor_ids; + rule.for_each_as_declaration_rule_list( + [&](auto& at_rule) { + // FIXME: Parse margin rules here. + (void)at_rule; + }, + [&](auto& declaration) { + if (auto descriptor = convert_to_descriptor(AtRuleID::Page, declaration); descriptor.has_value()) { + if (seen_descriptor_ids.contains(descriptor->descriptor_id)) { + descriptors.remove_first_matching([&descriptor](Descriptor const& existing) { + return existing.descriptor_id == descriptor->descriptor_id; + }); + } else { + seen_descriptor_ids.set(descriptor->descriptor_id); + } + descriptors.append(descriptor.release_value()); + } + }); + + auto rule_list = CSSRuleList::create(realm(), child_rules); + return CSSPageRule::create(realm(), move(page_selectors), CSSPageDescriptors::create(realm(), move(descriptors)), rule_list); +} + } diff --git a/Libraries/LibWeb/CSS/StyleComputer.cpp b/Libraries/LibWeb/CSS/StyleComputer.cpp index 938fd3cd1e3..bb8603ba80d 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -3027,8 +3027,9 @@ void StyleComputer::build_qualified_layer_names_cache() case CSSRule::Type::Keyframe: case CSSRule::Type::Namespace: case CSSRule::Type::NestedDeclarations: - case CSSRule::Type::Supports: + case CSSRule::Type::Page: case CSSRule::Type::Property: + case CSSRule::Type::Supports: break; } }); diff --git a/Libraries/LibWeb/Dump.cpp b/Libraries/LibWeb/Dump.cpp index a2792c761d3..5916a3a49b8 100644 --- a/Libraries/LibWeb/Dump.cpp +++ b/Libraries/LibWeb/Dump.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -695,15 +696,18 @@ void dump_rule(StringBuilder& builder, CSS::CSSRule const& rule, int indent_leve case CSS::CSSRule::Type::NestedDeclarations: dump_nested_declarations(builder, as(rule), indent_levels); break; + case CSS::CSSRule::Type::Page: + dump_page_rule(builder, as(rule), indent_levels); + break; + case CSS::CSSRule::Type::Property: + dump_property_rule(builder, as(rule), indent_levels); + break; case CSS::CSSRule::Type::Style: dump_style_rule(builder, as(rule), indent_levels); break; case CSS::CSSRule::Type::Supports: dump_supports_rule(builder, as(rule), indent_levels); break; - case CSS::CSSRule::Type::Property: - dump_property_rule(builder, as(rule), indent_levels); - break; } } @@ -765,6 +769,13 @@ void dump_media_rule(StringBuilder& builder, CSS::CSSMediaRule const& media, int dump_rule(builder, rule, indent_levels + 2); } +void dump_page_rule(StringBuilder& builder, CSS::CSSPageRule const& page, int indent_levels) +{ + indent(builder, indent_levels + 1); + builder.appendff("selector: {}\n", page.selector_text()); + dump_descriptors(builder, page.descriptors(), indent_levels + 1); +} + void dump_supports_rule(StringBuilder& builder, CSS::CSSSupportsRule const& supports, int indent_levels) { indent(builder, indent_levels); diff --git a/Libraries/LibWeb/Dump.h b/Libraries/LibWeb/Dump.h index 586411e5e78..9f29b93d2c8 100644 --- a/Libraries/LibWeb/Dump.h +++ b/Libraries/LibWeb/Dump.h @@ -30,6 +30,7 @@ void dump_import_rule(StringBuilder&, CSS::CSSImportRule const&, int indent_leve void dump_keyframe_rule(StringBuilder&, CSS::CSSKeyframeRule const&, int indent_levels = 0); void dump_keyframes_rule(StringBuilder&, CSS::CSSKeyframesRule const&, int indent_levels = 0); void dump_media_rule(StringBuilder&, CSS::CSSMediaRule const&, int indent_levels = 0); +void dump_page_rule(StringBuilder&, CSS::CSSPageRule const&, int indent_levels = 0); void dump_style_rule(StringBuilder&, CSS::CSSStyleRule const&, int indent_levels = 0); void dump_supports_rule(StringBuilder&, CSS::CSSSupportsRule const&, int indent_levels = 0); void dump_property_rule(StringBuilder&, CSS::CSSPropertyRule const&, int indent_levels = 0); diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index c962ec6a5ca..55daceb4293 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -205,6 +205,8 @@ class CSSNamespaceRule; class CSSNestedDeclarations; class CSSOKLab; class CSSOKLCH; +class CSSPageRule; +class CSSPageDescriptors; class CSSPropertyRule; class CSSRGB; class CSSRule; diff --git a/Libraries/LibWeb/idl_files.cmake b/Libraries/LibWeb/idl_files.cmake index ef222993eb9..58115513529 100644 --- a/Libraries/LibWeb/idl_files.cmake +++ b/Libraries/LibWeb/idl_files.cmake @@ -35,6 +35,8 @@ libweb_js_bindings(CSS/CSSMediaRule) libweb_js_bindings(CSS/CSS NAMESPACE) libweb_js_bindings(CSS/CSSNamespaceRule) libweb_js_bindings(CSS/CSSNestedDeclarations) +libweb_js_bindings(CSS/CSSPageRule) +libweb_js_bindings(CSS/CSSPageDescriptors) libweb_js_bindings(CSS/CSSPropertyRule) libweb_js_bindings(CSS/CSSRule) libweb_js_bindings(CSS/CSSRuleList) diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index 1c18d2b324c..38c35b2375a 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -49,6 +49,8 @@ CSSLayerStatementRule CSSMediaRule CSSNamespaceRule CSSNestedDeclarations +CSSPageDescriptors +CSSPageRule CSSPropertyRule CSSRule CSSRuleList diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-page/cssom/page-001.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-page/cssom/page-001.txt index b0cf4a74add..a318e551a3a 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-page/cssom/page-001.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-page/cssom/page-001.txt @@ -2,8 +2,9 @@ Harness status: OK Found 4 tests -4 Fail +1 Pass +3 Fail Fail There should be 3 @page rules. -Fail Rule #0 +Pass Rule #0 Fail Rule #1 Fail Rule #2 \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-page/cssom/page-002.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-page/cssom/page-002.txt index 6055c864758..4d99763c61f 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-page/cssom/page-002.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-page/cssom/page-002.txt @@ -1,3 +1,7 @@ -Harness status: Error +Harness status: OK -Found 0 tests +Found 2 tests + +2 Fail +Fail Add declarations +Fail Remove declarations \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-page/parsing/page-rules-001.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-page/parsing/page-rules-001.txt index 1dd07162245..9e52bf0463b 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-page/parsing/page-rules-001.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-page/parsing/page-rules-001.txt @@ -2,11 +2,11 @@ Harness status: OK Found 8 tests -4 Pass -4 Fail +5 Pass +3 Fail Pass page-rules-001 Pass @page , { } should be an invalid rule -Fail @page { } should be a valid rule +Pass @page { } should be a valid rule Fail @page a { } should be a valid rule Fail @page page1 { } should be a valid rule Fail @page name1, name2 { } should be a valid rule diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-page/parsing/size-valid.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-page/parsing/size-valid.txt index d1efb025555..cfa10522b33 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-page/parsing/size-valid.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-page/parsing/size-valid.txt @@ -2,8 +2,9 @@ Harness status: OK Found 15 tests -15 Fail -Fail Test setup +1 Pass +14 Fail +Pass Test setup Fail size: 640px 480px Fail size: 8.5in 11in Fail size: 3in 10in diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/cssom/cssimportrule.txt b/Tests/LibWeb/Text/expected/wpt-import/css/cssom/cssimportrule.txt index 7bc6e91ba48..c046b86228f 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/cssom/cssimportrule.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/cssom/cssimportrule.txt @@ -2,8 +2,8 @@ Harness status: OK Found 11 tests -8 Pass -3 Fail +9 Pass +2 Fail Pass CSSRule and CSSImportRule types Pass Type of CSSRule#type and constant values Pass Existence and writability of CSSRule attributes @@ -11,7 +11,7 @@ Pass Values of CSSRule attributes Pass Existence and writability of CSSImportRule attributes Fail Values of CSSImportRule attributes Fail CSSImportRule : MediaList mediaText attribute should be updated due to [PutForwards] -Fail CSSStyleDeclaration cssText attribute should be updated due to [PutForwards] +Pass CSSStyleDeclaration cssText attribute should be updated due to [PutForwards] Pass StyleSheet : MediaList mediaText attribute should be updated due to [PutForwards] Pass Existence and writability of CSSImportRule supportsText attribute Pass Value of CSSImportRule supportsText attribute \ No newline at end of file