diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 233dd960a76..37984d52c55 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -1471,6 +1471,53 @@ void Document::obtain_supported_color_schemes() // 3. Return null. } +// https://html.spec.whatwg.org/multipage/semantics.html#meta-theme-color +void Document::obtain_theme_color() +{ + Color theme_color = Color::Transparent; + + // 1. Let candidate elements be the list of all meta elements that meet the following criteria, in tree order: + for_each_in_subtree_of_type([&](HTML::HTMLMetaElement& element) { + // * the element is in a document tree; + // * the element has a name attribute, whose value is an ASCII case-insensitive match for theme-color; and + // * the element has a content attribute. + + // 2. For each element in candidate elements: + auto content = element.attribute(HTML::AttributeNames::content); + if (element.name().has_value() && element.name()->equals_ignoring_ascii_case("theme-color"sv) && content.has_value()) { + // 1. If element has a media attribute and the value of element's media attribute does not match the environment, then continue. + auto context = CSS::Parser::ParsingContext { document() }; + auto media = element.attribute(HTML::AttributeNames::media); + if (media.has_value()) { + auto query = parse_media_query(context, media.value()); + if (window() && !query->evaluate(*window())) + return TraversalDecision::Continue; + } + + // 2. Let value be the result of stripping leading and trailing ASCII whitespace from the value of element's content attribute. + auto value = content->bytes_as_string_view().trim(Infra::ASCII_WHITESPACE); + + // 3. Let color be the result of parsing value. + auto css_value = parse_css_value(context, value, CSS::PropertyID::Color); + + // 4. If color is not failure, then return color. + if (!css_value.is_null() && css_value->is_color()) { + Optional root_node; + if (html_element()) + root_node = *html_element()->layout_node(); + + theme_color = css_value->to_color(root_node); + return TraversalDecision::Break; + } + } + + return TraversalDecision::Continue; + }); + + // 3. Return nothing(the page has no theme color). + document().page().client().page_did_change_theme_color(theme_color); +} + Layout::Viewport const* Document::layout_node() const { return static_cast(Node::layout_node()); diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index 22fbec3fc26..10c14e4cac4 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -245,6 +245,8 @@ public: Optional const&> supported_color_schemes() const; void obtain_supported_color_schemes(); + void obtain_theme_color(); + void update_style(); void update_layout(); void update_paint_and_hit_testing_properties_if_needed(); diff --git a/Libraries/LibWeb/HTML/HTMLMetaElement.cpp b/Libraries/LibWeb/HTML/HTMLMetaElement.cpp index e68d4c2ecb6..f7079ec41a5 100644 --- a/Libraries/LibWeb/HTML/HTMLMetaElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLMetaElement.cpp @@ -51,14 +51,18 @@ Optional HTMLMetaElement::http_equiv_s void HTMLMetaElement::update_metadata(Optional const& old_name) { if (name().has_value()) { - if (name()->equals_ignoring_ascii_case("color-scheme"sv)) { + if (name()->equals_ignoring_ascii_case("theme-color"sv)) { + document().obtain_theme_color(); + } else if (name()->equals_ignoring_ascii_case("color-scheme"sv)) { document().obtain_supported_color_schemes(); return; } } if (old_name.has_value()) { - if (old_name->equals_ignoring_ascii_case("color-scheme"sv)) { + if (old_name->equals_ignoring_ascii_case("theme-color"sv)) { + document().obtain_theme_color(); + } else if (old_name->equals_ignoring_ascii_case("color-scheme"sv)) { document().obtain_supported_color_schemes(); return; } @@ -69,39 +73,6 @@ void HTMLMetaElement::inserted() { Base::inserted(); - // https://html.spec.whatwg.org/multipage/semantics.html#meta-theme-color - // 1. To obtain a page's theme color, user agents must run the following steps: - // * The element is in a document tree - // * The element has a name attribute, whose value is an ASCII case-insensitive match for theme-color - // * The element has a content attribute - auto content = attribute(AttributeNames::content); - if (name().has_value() && name()->equals_ignoring_ascii_case("theme-color"sv) && content.has_value()) { - auto context = CSS::Parser::ParsingContext { document() }; - - // 2. For each element in candidate elements: - - // 1. If element has a media attribute and the value of element's media attribute does not match the environment, then continue. - auto media = attribute(AttributeNames::media); - if (media.has_value()) { - auto query = parse_media_query(context, media.value()); - if (document().window() && !query->evaluate(*document().window())) - return; - } - - // 2. Let value be the result of stripping leading and trailing ASCII whitespace from the value of element's content attribute. - auto value = content->bytes_as_string_view().trim(Infra::ASCII_WHITESPACE); - - // 3. Let color be the result of parsing value. - auto css_value = parse_css_value(context, value, CSS::PropertyID::Color); - if (css_value.is_null() || !css_value->is_color()) - return; - auto color = css_value->to_color({}); // TODO: Pass a layout node? - - // 4. If color is not failure, then return color. - document().page().client().page_did_change_theme_color(color); - return; - } - update_metadata(); // https://html.spec.whatwg.org/multipage/semantics.html#pragma-directives