mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-04-19 02:10:26 +00:00
:heading() now matches based on a computed heading level, which is based
on the level of the tag (h1, h2, etc) and then modified by these two new
attributes.
I'm caching this heading level on HTMLHeadingElement, based on the dom
tree version. That's more invalidation than is actually needed, but it
saves us calculating it over and over when the document hasn't changed.
The failing test cases are:
- Implicit headingreset for modal dialogs which is apparently unspecced
and controversial.
- Not walking the flat tree properly. A flat tree ancestor of a
slot-assigned element is its slot, which is something we don't do
anywhere that I could find. I've made a note to look into this later.
We also don't implement the `ReflectRange` IDL attribute yet, which
means we're not clamping the read value of `headingOffset`.
Corresponds to:
e774e8e318
69 lines
2.7 KiB
C++
69 lines
2.7 KiB
C++
/*
|
||
* Copyright (c) 2018-2020, Andreas Kling <andreas@ladybird.org>
|
||
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
|
||
*
|
||
* SPDX-License-Identifier: BSD-2-Clause
|
||
*/
|
||
|
||
#include <LibWeb/Bindings/HTMLHeadingElementPrototype.h>
|
||
#include <LibWeb/Bindings/Intrinsics.h>
|
||
#include <LibWeb/CSS/ComputedProperties.h>
|
||
#include <LibWeb/CSS/StyleValues/KeywordStyleValue.h>
|
||
#include <LibWeb/DOM/Document.h>
|
||
#include <LibWeb/HTML/HTMLHeadingElement.h>
|
||
|
||
namespace Web::HTML {
|
||
|
||
GC_DEFINE_ALLOCATOR(HTMLHeadingElement);
|
||
|
||
HTMLHeadingElement::HTMLHeadingElement(DOM::Document& document, DOM::QualifiedName qualified_name)
|
||
: HTMLElement(document, move(qualified_name))
|
||
{
|
||
}
|
||
|
||
HTMLHeadingElement::~HTMLHeadingElement() = default;
|
||
|
||
void HTMLHeadingElement::initialize(JS::Realm& realm)
|
||
{
|
||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLHeadingElement);
|
||
Base::initialize(realm);
|
||
}
|
||
|
||
bool HTMLHeadingElement::is_presentational_hint(FlyString const& name) const
|
||
{
|
||
if (Base::is_presentational_hint(name))
|
||
return true;
|
||
|
||
return name == HTML::AttributeNames::align;
|
||
}
|
||
|
||
// https://html.spec.whatwg.org/multipage/rendering.html#tables-2
|
||
void HTMLHeadingElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||
{
|
||
HTMLElement::apply_presentational_hints(cascaded_properties);
|
||
for_each_attribute([&](auto& name, auto& value) {
|
||
if (name == HTML::AttributeNames::align) {
|
||
if (value == "left"sv)
|
||
cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::TextAlign, CSS::KeywordStyleValue::create(CSS::Keyword::Left));
|
||
else if (value == "right"sv)
|
||
cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::TextAlign, CSS::KeywordStyleValue::create(CSS::Keyword::Right));
|
||
else if (value == "center"sv)
|
||
cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::TextAlign, CSS::KeywordStyleValue::create(CSS::Keyword::Center));
|
||
else if (value == "justify"sv)
|
||
cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::TextAlign, CSS::KeywordStyleValue::create(CSS::Keyword::Justify));
|
||
}
|
||
});
|
||
}
|
||
|
||
// https://html.spec.whatwg.org/multipage/sections.html#heading-level
|
||
WebIDL::UnsignedLong HTMLHeadingElement::heading_level() const
|
||
{
|
||
// h1–h6 elements have a heading level, which is given by getting the element's computed heading level.
|
||
if (m_dom_tree_version_for_cached_heading_level < document().dom_tree_version()) {
|
||
m_dom_tree_version_for_cached_heading_level = document().dom_tree_version();
|
||
m_cached_heading_level = computed_heading_level();
|
||
}
|
||
return m_cached_heading_level;
|
||
}
|
||
|
||
}
|