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

Code before:
            // 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>.
            // In that case, the user agent is expected to treat the attribute as a presentational hint setting the element's font-size property to the corresponding value.
            if (auto parsed_value = HTML::parse_dimension_value(value))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::FontSize, parsed_value.release_nonnull());
        } else if (name == "displaystyle") {
            // https://w3c.github.io/mathml-core/#dfn-displaystyle
            // The displaystyle attribute, if present, must have a value that is a boolean. In that case, the user agent is expected to treat the attribute as a presentational hint setting the
            // element's math-style property to the corresponding value.
            if (value.equals_ignoring_ascii_case("true"sv))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::MathStyle, CSS::KeywordStyleValue::create(CSS::Keyword::Normal));
            else if (value.equals_ignoring_ascii_case("false"sv))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::MathStyle, CSS::KeywordStyleValue::create(CSS::Keyword::Compact));
        } else if (name == "scriptlevel") {
            // https://w3c.github.io/mathml-core/#dfn-scriptlevel
            // The scriptlevel attribute, if present, must have value +<U>, -<U> or <U> where <U> is an unsigned-integer.
            // In that case the user agent is expected to treat the scriptlevel attribute as a presentational hint setting the element's math-depth property to the corresponding value.
            // More precisely, +<U>, -<U> and <U> are respectively mapped to add(<U>) add(<-U>) and <U>.
            if (Optional<StringView> parsed_value = HTML::parse_integer_digits(value); parsed_value.has_value()) {
                auto string_value = parsed_value.value();
                if (auto value = parsed_value->to_number<i32>(TrimWhitespace::No); value.has_value()) {
                    auto style_value = string_value[0] == '+' || string_value[0] == '-' ? CSS::MathDepthStyleValue::create_add(CSS::IntegerStyleValue::create(value.release_value()))
                                                                                        : CSS::MathDepthStyleValue::create_integer(CSS::IntegerStyleValue::create(value.release_value()));
                    cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::MathDepth, style_value);
                }
            }
        }
    });
}

}


Review comment (security):
The spec continues:
> More precisely, an [ASCII case-insensitive](https://infra.spec.whatwg.org/#ascii-case-insensitive) match to true is mapped to normal while an [ASCII case-insensitive](https://infra.spec.whatwg.org/#ascii-case-insensitive) match to false is mapped to compact.

I think that'd be useful to include here, to explain why we map these values.

Code after:
    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) {
            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 == AttributeNames::mathsize) {
            // https://w3c.github.io/mathml-core/#dfn-mathsize
            // The mathsize attribute, if present, must have a value that is a valid <length-percentage>.
            // In that case, the user agent is expected to treat the attribute as a presentational hint setting the
            // element's font-size property to the corresponding value.
            if (auto parsed_value = HTML::parse_dimension_value(value))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::FontSize, parsed_value.release_nonnull());
        } else if (name == AttributeNames::displaystyle) {
            // https://w3c.github.io/mathml-core/#dfn-displaystyle
            // The displaystyle attribute, if present, must have a value that is a boolean. In that case, the user agent
            // is expected to treat the attribute as a presentational hint setting the element's math-style property to
            // the corresponding value. More precisely, an ASCII case-insensitive match to true is mapped to normal while
            // an ASCII case-insensitive match to false is mapped to compact.
            if (value.equals_ignoring_ascii_case("true"sv))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::MathStyle, CSS::KeywordStyleValue::create(CSS::Keyword::Normal));
            else if (value.equals_ignoring_ascii_case("false"sv))
                cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::MathStyle, CSS::KeywordStyleValue::create(CSS::Keyword::Compact));
        } else if (name == AttributeNames::scriptlevel) {
            // https://w3c.github.io/mathml-core/#dfn-scriptlevel
            // The scriptlevel attribute, if present, must have value +<U>, -<U> or <U> where <U> is an unsigned-integer.
            // In that case the user agent is expected to treat the scriptlevel attribute as a presentational hint
            // setting the element's math-depth property to the corresponding value. More precisely, +<U>, -<U> and <U>
            // are respectively mapped to add(<U>) add(<-U>) and <U>.
            if (Optional<StringView> parsed_value = HTML::parse_integer_digits(value); parsed_value.has_value()) {
                auto string_value = parsed_value.value();
                if (auto value = parsed_value->to_number<i32>(TrimWhitespace::No); value.has_value()) {
                    auto style_value = string_value[0] == '+' || string_value[0] == '-' ? CSS::MathDepthStyleValue::create_add(CSS::IntegerStyleValue::create(value.release_value()))
                                                                                        : CSS::MathDepthStyleValue::create_integer(CSS::IntegerStyleValue::create(value.release_value()));
                    cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::MathDepth, style_value);
                }