diff --git a/Userland/Libraries/LibWeb/CSS/Display.h b/Userland/Libraries/LibWeb/CSS/Display.h index 4d922024b2..cc7c7df702 100644 --- a/Userland/Libraries/LibWeb/CSS/Display.h +++ b/Userland/Libraries/LibWeb/CSS/Display.h @@ -100,6 +100,7 @@ public: bool is_flex_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Flex; } bool is_grid_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Grid; } bool is_ruby_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Ruby; } + bool is_math_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Math; } enum class Short { None, @@ -119,6 +120,7 @@ public: Ruby, Table, InlineTable, + Math, }; static Display from_short(Short short_) @@ -158,6 +160,11 @@ public: return Display { DisplayOutside::Block, DisplayInside::Table }; case Short::InlineTable: return Display { DisplayOutside::Inline, DisplayInside::Table }; + case Short::Math: + // NOTE: The spec ( https://w3c.github.io/mathml-core/#new-display-math-value ) does not + // mention what the outside value for `display: math` should be. + // The UA stylesheet does `* { display: block math; }` so let's go with that. + return Display { DisplayOutside::Block, DisplayInside::Math }; } VERIFY_NOT_REACHED(); } diff --git a/Userland/Libraries/LibWeb/CSS/Enums.json b/Userland/Libraries/LibWeb/CSS/Enums.json index 003143999e..3b48c16f05 100644 --- a/Userland/Libraries/LibWeb/CSS/Enums.json +++ b/Userland/Libraries/LibWeb/CSS/Enums.json @@ -143,7 +143,8 @@ "table", "flex", "grid", - "ruby" + "ruby", + "math" ], "display-internal": [ "table-row-group", diff --git a/Userland/Libraries/LibWeb/CSS/Identifiers.json b/Userland/Libraries/LibWeb/CSS/Identifiers.json index 797043150b..7fddd4e6df 100644 --- a/Userland/Libraries/LibWeb/CSS/Identifiers.json +++ b/Userland/Libraries/LibWeb/CSS/Identifiers.json @@ -219,6 +219,7 @@ "listbox", "mark", "marktext", + "math", "max-content", "medium", "menu", diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 1a0bdb3aeb..e408fda748 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -3574,6 +3574,8 @@ RefPtr Parser::parse_display_value(Vector const& com return Display::from_short(Display::Short::Grid); case DisplayInside::Ruby: return Display::from_short(Display::Short::Ruby); + case DisplayInside::Math: + return Display::from_short(Display::Short::Math); } } diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 5e69ff9a1e..66101ead36 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -2243,6 +2244,23 @@ void StyleComputer::transform_box_type_if_needed(StyleProperties& style, DOM::El auto new_display = display; + if (display.is_math_inside()) { + // https://w3c.github.io/mathml-core/#new-display-math-value + // For elements that are not MathML elements, if the specified value of display is inline math or block math + // then the computed value is block flow and inline flow respectively. + if (element.namespace_() != Namespace::MathML) + new_display = CSS::Display { display.outside(), CSS::DisplayInside::Flow }; + // For the mtable element the computed value is block table and inline table respectively. + else if (element.tag_name().equals_ignoring_ascii_case("mtable"sv)) + new_display = CSS::Display { display.outside(), CSS::DisplayInside::Table }; + // For the mtr element, the computed value is table-row. + else if (element.tag_name().equals_ignoring_ascii_case("mtr"sv)) + new_display = CSS::Display { CSS::DisplayInternal::TableRow }; + // For the mtd element, the computed value is table-cell. + else if (element.tag_name().equals_ignoring_ascii_case("mtd"sv)) + new_display = CSS::Display { CSS::DisplayInternal::TableCell }; + } + switch (required_box_type_transformation(style, element, pseudo_element)) { case BoxTypeTransformation::None: break; diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 2ea33c771b..79b1de2931 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -373,6 +373,14 @@ JS::GCPtr Element::create_layout_node_for_display_type(DOM::Docume return document.heap().allocate_without_realm(document, element, move(style)); } + if (display.is_math_inside()) { + // https://w3c.github.io/mathml-core/#new-display-math-value + // MathML elements with a computed display value equal to block math or inline math control box generation + // and layout according to their tag name, as described in the relevant sections. + // FIXME: Figure out what kind of node we should make for them. For now, we'll stick with a generic Box. + return document.heap().allocate_without_realm(document, element, move(style)); + } + if (display.is_inline_outside()) { if (display.is_flow_root_inside()) return document.heap().allocate_without_realm(document, element, move(style));