From f8ce211201bf40ee95e8b171799e576bf79a374a Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Wed, 4 Jan 2023 16:38:42 +0300 Subject: [PATCH] LibWeb: Generate missing parents for table elements Implements 3.1 and 3.2 algorithms from: https://www.w3.org/TR/css-tables-3/#fixup-algorithm --- .../Libraries/LibWeb/Layout/TreeBuilder.cpp | 54 +++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp index 7facd9595b..2baa4e37bb 100644 --- a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -408,28 +408,41 @@ static bool is_table_track_group(CSS::Display display) || display.is_table_column_group(); } +static bool is_proper_table_child(Node const& node) +{ + auto const display = node.display(); + return is_table_track_group(display) || is_table_track(display) || display.is_table_caption(); +} + static bool is_not_proper_table_child(Node const& node) { if (!node.has_style()) return true; - auto const display = node.display(); - return !is_table_track_group(display) && !is_table_track(display) && !display.is_table_caption(); + return !is_proper_table_child(node); +} + +static bool is_table_row(Node const& node) +{ + return node.display().is_table_row(); } static bool is_not_table_row(Node const& node) { if (!node.has_style()) return true; - auto const display = node.display(); - return !display.is_table_row(); + return !is_table_row(node); +} + +static bool is_table_cell(Node const& node) +{ + return node.display().is_table_cell(); } static bool is_not_table_cell(Node const& node) { if (!node.has_style()) return true; - auto const display = node.display(); - return !display.is_table_cell(); + return !is_table_cell(node); } static bool is_ignorable_whitespace(Layout::Node const& node) @@ -467,7 +480,7 @@ static void for_each_sequence_of_consecutive_children_matching(NodeWithStyle& pa }; for (auto child = parent.first_child(); child; child = child->next_sibling()) { - if (matcher(*child)) { + if (matcher(*child) || (!sequence.is_empty() && is_ignorable_whitespace(*child))) { sequence.append(*child); } else { if (!sequence.is_empty()) { @@ -535,9 +548,32 @@ void TreeBuilder::generate_missing_child_wrappers(NodeWithStyle& root) }); } -void TreeBuilder::generate_missing_parents(NodeWithStyle&) +void TreeBuilder::generate_missing_parents(NodeWithStyle& root) { - // FIXME: Implement. + root.for_each_in_inclusive_subtree_of_type([&](auto& parent) { + // An anonymous table-row box must be generated around each sequence of consecutive table-cell boxes whose parent is not a table-row. + if (is_not_table_row(parent)) { + for_each_sequence_of_consecutive_children_matching(parent, is_table_cell, [&](auto& sequence, auto nearest_sibling) { + wrap_in_anonymous(sequence, nearest_sibling); + }); + } + + // A table-row is misparented if its parent is neither a table-row-group nor a table-root box. + if (!parent.display().is_table_inside() && !is_proper_table_child(parent)) { + for_each_sequence_of_consecutive_children_matching(parent, is_table_row, [&](auto& sequence, auto nearest_sibling) { + wrap_in_anonymous(sequence, nearest_sibling); + }); + } + + // A table-row-group, table-column-group, or table-caption box is misparented if its parent is not a table-root box. + if (!parent.display().is_table_inside() && !is_proper_table_child(parent)) { + for_each_sequence_of_consecutive_children_matching(parent, is_proper_table_child, [&](auto& sequence, auto nearest_sibling) { + wrap_in_anonymous(sequence, nearest_sibling); + }); + } + + return IterationDecision::Continue; + }); } }