Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/MathML/MathMLElement.cpp (C++)

Code before:
    HTMLOrSVGElement::inserted();
}

void MathMLElement::initialize(JS::Realm& realm)
{
    WEB_SET_PROTOTYPE_FOR_INTERFACE(MathMLElement);
    Base::initialize(realm);
}

Optional<ARIA::Role> MathMLElement::default_role() const
{
    // https://www.w3.org/TR/html-aria/#el-math
    if (local_name() == TagNames::math)
        return ARIA::Role::math;
    return {};
}

void MathMLElement::visit_edges(JS::Cell::Visitor& visitor)
{
    Base::visit_edges(visitor);
    HTMLOrSVGElement::visit_edges(visitor);
}

bool MathMLElement::is_presentational_hint(FlyString const& name) const
{
    return first_is_one_of(name, "dir", "mathcolor", "mathbackground", "mathsize", "displaystyle", "scriptlevel");
}

void MathMLElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
{
    for_each_attribute([&](auto& name, auto& value) {
        if (name == "dir") {
            // https://w3c.github.io/mathml-core/#attributes-common-to-html-and-mathml-elements
            // The dir attribute, if present, must be an ASCII case-insensitive match to ltr or rtl. In that case, the user agent is expected to treat the attribute as a presentational hint setting the
            // element's direction property to the corresponding value. More precisely, an ASCII case-insensitive match to rtl is mapped to rtl while an ASCII case-insensitive match to ltr is mapped to ltr.
            if (value.equals_ignoring_ascii_case("ltr"sv))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::Direction, CSS::KeywordStyleValue::create(CSS::Keyword::Ltr));
            else if (value.equals_ignoring_ascii_case("rtl"sv))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::Direction, CSS::KeywordStyleValue::create(CSS::Keyword::Rtl));
        } else if (name == "mathcolor") {
            // https://w3c.github.io/mathml-core/#legacy-mathml-style-attributes
            // The mathcolor and mathbackground attributes, if present, must have a value that is a <color>. In that case, the user agent is expected to treat these attributes as a presentational hint
            // setting the element's color and background-color properties to the corresponding values.
            if (auto parsed_value = parse_css_value(CSS::Parser::ParsingParams { document() }, value, CSS::PropertyID::Color))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::Color, parsed_value.release_nonnull());
        } else if (name == "mathbackground") {
            if (auto parsed_value = parse_css_value(CSS::Parser::ParsingParams { document() }, value, CSS::PropertyID::BackgroundColor))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::BackgroundColor, parsed_value.release_nonnull());
        } else if (name == "mathsize") {
            // https://w3c.github.io/mathml-core/#dfn-mathsize
            // The mathsize attribute, if present, must have a value that is a valid <length-percentage>.

Review comment (suggestion):
Regarding `MathML::AtributeNames`, the benefit is that those would be `FlyString`s, meaning that comparing them is much faster.

Code after:
    Base::inserted();
    HTMLOrSVGElement::inserted();
}

void MathMLElement::initialize(JS::Realm& realm)
{
    WEB_SET_PROTOTYPE_FOR_INTERFACE(MathMLElement);
    Base::initialize(realm);
}

Optional<ARIA::Role> MathMLElement::default_role() const
{
    // https://www.w3.org/TR/html-aria/#el-math
    if (local_name() == TagNames::math)
        return ARIA::Role::math;
    return {};
}

void MathMLElement::visit_edges(JS::Cell::Visitor& visitor)
{
    Base::visit_edges(visitor);
    HTMLOrSVGElement::visit_edges(visitor);
}

bool MathMLElement::is_presentational_hint(FlyString const& name) const
{
    return first_is_one_of(name, AttributeNames::dir, AttributeNames::mathcolor, AttributeNames::mathbackground,
        AttributeNames::mathsize, AttributeNames::displaystyle, AttributeNames::scriptlevel);
}

void MathMLElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
{
    for_each_attribute([&](auto& name, auto& value) {
        if (name == AttributeNames::dir) {
            // https://w3c.github.io/mathml-core/#attributes-common-to-html-and-mathml-elements
            // The dir attribute, if present, must be an ASCII case-insensitive match to ltr or rtl. In that case, the
            // user agent is expected to treat the attribute as a presentational hint setting the element's direction
            // property to the corresponding value. More precisely, an ASCII case-insensitive match to rtl is mapped to
            // rtl while an ASCII case-insensitive match to ltr is mapped to ltr.
            if (value.equals_ignoring_ascii_case("ltr"sv))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::Direction, CSS::KeywordStyleValue::create(CSS::Keyword::Ltr));
            else if (value.equals_ignoring_ascii_case("rtl"sv))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::Direction, CSS::KeywordStyleValue::create(CSS::Keyword::Rtl));
        } else if (name == AttributeNames::mathcolor) {
            // https://w3c.github.io/mathml-core/#legacy-mathml-style-attributes
            // The mathcolor and mathbackground attributes, if present, must have a value that is a <color>. In that case,
            // the user agent is expected to treat these attributes as a presentational hint setting the element's color
            // and background-color properties to the corresponding values.
            if (auto parsed_value = parse_css_value(CSS::Parser::ParsingParams { document() }, value, CSS::PropertyID::Color))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::Color, parsed_value.release_nonnull());
        } else if (name == AttributeNames::mathbackground) {