mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-24 18:02:20 +00:00
LibWeb/CSS: Implement the empty-cells
property
This property sets whether table borders and backgrounds are painted if a given table cell has no visible content.
This commit is contained in:
parent
a0cef5a7da
commit
e0af205d69
Notes:
github-actions[bot]
2025-06-18 13:56:15 +00:00
Author: https://github.com/tcl3
Commit: e0af205d69
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5133
Reviewed-by: https://github.com/AtkinsSJ ✅
22 changed files with 253 additions and 10 deletions
|
@ -1577,6 +1577,12 @@ BorderCollapse ComputedProperties::border_collapse() const
|
|||
return keyword_to_border_collapse(value.to_keyword()).release_value();
|
||||
}
|
||||
|
||||
EmptyCells ComputedProperties::empty_cells() const
|
||||
{
|
||||
auto const& value = property(PropertyID::EmptyCells);
|
||||
return keyword_to_empty_cells(value.to_keyword()).release_value();
|
||||
}
|
||||
|
||||
Vector<Vector<String>> ComputedProperties::grid_template_areas() const
|
||||
{
|
||||
auto const& value = property(PropertyID::GridTemplateAreas);
|
||||
|
|
|
@ -159,6 +159,7 @@ public:
|
|||
GridTrackPlacement grid_row_end() const;
|
||||
GridTrackPlacement grid_row_start() const;
|
||||
BorderCollapse border_collapse() const;
|
||||
CSS::EmptyCells empty_cells() const;
|
||||
Vector<Vector<String>> grid_template_areas() const;
|
||||
ObjectFit object_fit() const;
|
||||
ObjectPosition object_position() const;
|
||||
|
|
|
@ -182,6 +182,7 @@ public:
|
|||
static CSS::Size column_width() { return CSS::Size::make_auto(); }
|
||||
static Variant<LengthPercentage, NormalGap> row_gap() { return NormalGap {}; }
|
||||
static CSS::BorderCollapse border_collapse() { return CSS::BorderCollapse::Separate; }
|
||||
static CSS::EmptyCells empty_cells() { return CSS::EmptyCells::Show; }
|
||||
static Vector<Vector<String>> grid_template_areas() { return {}; }
|
||||
static CSS::Time transition_delay() { return CSS::Time::make_seconds(0); }
|
||||
static CSS::ObjectFit object_fit() { return CSS::ObjectFit::Fill; }
|
||||
|
@ -490,6 +491,7 @@ public:
|
|||
CSS::Size const& column_width() const { return m_noninherited.column_width; }
|
||||
Variant<LengthPercentage, NormalGap> const& row_gap() const { return m_noninherited.row_gap; }
|
||||
CSS::BorderCollapse border_collapse() const { return m_inherited.border_collapse; }
|
||||
CSS::EmptyCells empty_cells() const { return m_inherited.empty_cells; }
|
||||
Vector<Vector<String>> const& grid_template_areas() const { return m_noninherited.grid_template_areas; }
|
||||
CSS::ObjectFit object_fit() const { return m_noninherited.object_fit; }
|
||||
CSS::ObjectPosition object_position() const { return m_noninherited.object_position; }
|
||||
|
@ -622,6 +624,7 @@ protected:
|
|||
Optional<HashMap<FlyString, NumberOrCalculated>> font_variation_settings;
|
||||
CSSPixels line_height { InitialValues::line_height() };
|
||||
CSS::BorderCollapse border_collapse { InitialValues::border_collapse() };
|
||||
CSS::EmptyCells empty_cells { InitialValues::empty_cells() };
|
||||
CSS::Length border_spacing_horizontal { InitialValues::border_spacing() };
|
||||
CSS::Length border_spacing_vertical { InitialValues::border_spacing() };
|
||||
CSS::CaptionSide caption_side { InitialValues::caption_side() };
|
||||
|
@ -930,6 +933,7 @@ public:
|
|||
void set_column_width(CSS::Size const& column_width) { m_noninherited.column_width = column_width; }
|
||||
void set_row_gap(Variant<LengthPercentage, NormalGap> const& row_gap) { m_noninherited.row_gap = row_gap; }
|
||||
void set_border_collapse(CSS::BorderCollapse const border_collapse) { m_inherited.border_collapse = border_collapse; }
|
||||
void set_empty_cells(CSS::EmptyCells const empty_cells) { m_inherited.empty_cells = empty_cells; }
|
||||
void set_grid_template_areas(Vector<Vector<String>> const& grid_template_areas) { m_noninherited.grid_template_areas = grid_template_areas; }
|
||||
void set_grid_auto_flow(CSS::GridAutoFlow grid_auto_flow) { m_noninherited.grid_auto_flow = grid_auto_flow; }
|
||||
void set_transition_delay(CSS::Time const& transition_delay) { m_noninherited.transition_delay = transition_delay; }
|
||||
|
|
|
@ -224,6 +224,10 @@
|
|||
"inline",
|
||||
"run-in"
|
||||
],
|
||||
"empty-cells": [
|
||||
"show",
|
||||
"hide"
|
||||
],
|
||||
"fill-rule": [
|
||||
"nonzero",
|
||||
"evenodd"
|
||||
|
|
|
@ -224,6 +224,7 @@
|
|||
"groove",
|
||||
"hard-light",
|
||||
"help",
|
||||
"hide",
|
||||
"hidden",
|
||||
"high",
|
||||
"high-quality",
|
||||
|
@ -449,6 +450,7 @@
|
|||
"separate",
|
||||
"serif",
|
||||
"shorter",
|
||||
"show",
|
||||
"sideways-lr",
|
||||
"sideways-rl",
|
||||
"simplified",
|
||||
|
|
|
@ -1265,6 +1265,14 @@
|
|||
"display-legacy"
|
||||
]
|
||||
},
|
||||
"empty-cells": {
|
||||
"animation-type": "discrete",
|
||||
"inherited": true,
|
||||
"initial": "show",
|
||||
"valid-types": [
|
||||
"empty-cells"
|
||||
]
|
||||
},
|
||||
"fill": {
|
||||
"affects-layout": false,
|
||||
"animation-type": "none",
|
||||
|
|
|
@ -924,6 +924,8 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
|
|||
|
||||
computed_values.set_border_collapse(computed_style.border_collapse());
|
||||
|
||||
computed_values.set_empty_cells(computed_style.empty_cells());
|
||||
|
||||
computed_values.set_table_layout(computed_style.table_layout());
|
||||
|
||||
auto const& aspect_ratio = computed_style.property(CSS::PropertyID::AspectRatio);
|
||||
|
|
|
@ -437,7 +437,11 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
|
|||
if (!is_visible())
|
||||
return;
|
||||
|
||||
if (phase == PaintPhase::Background) {
|
||||
auto empty_cells_property_applies = [this]() {
|
||||
return display().is_internal_table() && computed_values().empty_cells() == CSS::EmptyCells::Hide && !has_children();
|
||||
};
|
||||
|
||||
if (phase == PaintPhase::Background && !empty_cells_property_applies()) {
|
||||
paint_backdrop_filter(context);
|
||||
paint_background(context);
|
||||
paint_box_shadow(context);
|
||||
|
|
|
@ -378,6 +378,8 @@ void paint_table_borders(PaintContext& context, PaintableBox const& table_painta
|
|||
auto cell_coordinates_to_device_rect = snap_cells_to_device_coordinates(cell_coordinates_to_box, row_count, column_count, context);
|
||||
for (auto const& cell_box : cell_boxes) {
|
||||
if (table_paintable.computed_values().border_collapse() == CSS::BorderCollapse::Separate) {
|
||||
if (cell_box.computed_values().empty_cells() == CSS::EmptyCells::Hide && !cell_box.has_children())
|
||||
continue;
|
||||
paint_separate_cell_borders(cell_box, cell_coordinates_to_device_rect, context);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>No red visible, blank page, reference</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test passes if there is no red visible on the page.</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Test: Empty-cells and 'display: table-column' elements</title>
|
||||
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/tables.html#propdef-empty-cells" />
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/tables.html#empty-cells" />
|
||||
<link rel="match" href="../../../../../expected/wpt-import/css/CSS2/reference/no-red-on-blank-page-ref.xht" />
|
||||
<meta name="assert" content="Empty-cells does not apply to 'display: table-column' elements." />
|
||||
<style type="text/css">
|
||||
#table
|
||||
{
|
||||
display: table;
|
||||
}
|
||||
.tr
|
||||
{
|
||||
display: table-row;
|
||||
}
|
||||
.td
|
||||
{
|
||||
color: white;
|
||||
display: table-cell;
|
||||
}
|
||||
#test
|
||||
{
|
||||
background: red;
|
||||
border: 5px solid red;
|
||||
display: table-column;
|
||||
empty-cells: hide;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test passes if there is no red visible on the page.</p>
|
||||
<div id="table">
|
||||
<div class="tr">
|
||||
<div id="test"></div>
|
||||
<div class="td">XXXXX</div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td">XXXXX</div>
|
||||
<div class="td">XXXXX</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Test: Empty-cells and 'display: table-column-group' elements</title>
|
||||
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/tables.html#propdef-empty-cells" />
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/tables.html#empty-cells" />
|
||||
<link rel="match" href="../../../../../expected/wpt-import/css/CSS2/reference/no-red-on-blank-page-ref.xht" />
|
||||
<meta name="assert" content="Empty-cells does not apply to 'display: table-column-group' elements." />
|
||||
<style type="text/css">
|
||||
#table
|
||||
{
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
}
|
||||
.tr
|
||||
{
|
||||
display: table-row;
|
||||
}
|
||||
.td
|
||||
{
|
||||
color: white;
|
||||
display: table-cell;
|
||||
}
|
||||
#test
|
||||
{
|
||||
background: red;
|
||||
border: 5px solid red;
|
||||
display: table-column-group;
|
||||
empty-cells: hide;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test passes if there is no red visible on the page.</p>
|
||||
<div id="table">
|
||||
<div class="tr">
|
||||
<div id="test"></div>
|
||||
<div class="td">XXXXX</div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td">XXXXX</div>
|
||||
<div class="td">XXXXX</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Test: Empty-cells and 'display: table-cell' elements</title>
|
||||
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/tables.html#propdef-empty-cells" />
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/tables.html#empty-cells" />
|
||||
<link rel="match" href="../../../../../expected/wpt-import/css/CSS2/reference/no-red-on-blank-page-ref.xht" />
|
||||
<meta name="assert" content="Empty-cells applies to 'display: table-cell' elements." />
|
||||
<style type="text/css">
|
||||
#table
|
||||
{
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
}
|
||||
.tr
|
||||
{
|
||||
display: table-row;
|
||||
}
|
||||
.td
|
||||
{
|
||||
color: white;
|
||||
display: table-cell;
|
||||
}
|
||||
#test
|
||||
{
|
||||
background: red;
|
||||
border: 5px solid red;
|
||||
display: table-cell;
|
||||
empty-cells: hide;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test passes if there is no red visible on the page.</p>
|
||||
<div id="table">
|
||||
<div class="tr">
|
||||
<div id="test"></div>
|
||||
<div class="td">XXXXX</div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td">XXXXX</div>
|
||||
<div class="td">XXXXX</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -11,6 +11,7 @@ All properties associated with getComputedStyle(document.body):
|
|||
"color-scheme",
|
||||
"cursor",
|
||||
"direction",
|
||||
"empty-cells",
|
||||
"fill",
|
||||
"fill-opacity",
|
||||
"fill-rule",
|
||||
|
|
|
@ -327,6 +327,8 @@ All supported properties and their default values exposed from CSSStylePropertie
|
|||
'cy': '0px'
|
||||
'direction': 'ltr'
|
||||
'display': 'block'
|
||||
'emptyCells': 'show'
|
||||
'empty-cells': 'show'
|
||||
'fill': 'rgb(0, 0, 0)'
|
||||
'fillOpacity': '1'
|
||||
'fill-opacity': '1'
|
||||
|
|
|
@ -9,6 +9,7 @@ color: rgb(0, 0, 0)
|
|||
color-scheme: normal
|
||||
cursor: auto
|
||||
direction: ltr
|
||||
empty-cells: show
|
||||
fill: rgb(0, 0, 0)
|
||||
fill-opacity: 1
|
||||
fill-rule: nonzero
|
||||
|
@ -86,7 +87,7 @@ background-position-x: 0%
|
|||
background-position-y: 0%
|
||||
background-repeat: repeat
|
||||
background-size: auto auto
|
||||
block-size: 1320px
|
||||
block-size: 1335px
|
||||
border-block-end-color: rgb(0, 0, 0)
|
||||
border-block-end-style: none
|
||||
border-block-end-width: medium
|
||||
|
@ -151,7 +152,7 @@ grid-row-start: auto
|
|||
grid-template-areas: none
|
||||
grid-template-columns: none
|
||||
grid-template-rows: none
|
||||
height: 2295px
|
||||
height: 2310px
|
||||
inline-size: 784px
|
||||
inset-block-end: auto
|
||||
inset-block-start: auto
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 204 tests
|
||||
Found 205 tests
|
||||
|
||||
200 Pass
|
||||
201 Pass
|
||||
4 Fail
|
||||
Pass accent-color
|
||||
Pass border-collapse
|
||||
|
@ -14,6 +14,7 @@ Pass color
|
|||
Pass color-scheme
|
||||
Pass cursor
|
||||
Pass direction
|
||||
Pass empty-cells
|
||||
Pass fill
|
||||
Pass fill-opacity
|
||||
Pass fill-rule
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 2 tests
|
||||
|
||||
2 Pass
|
||||
Pass e.style['empty-cells'] = "auto" should not set the property value
|
||||
Pass e.style['empty-cells'] = "show hide" should not set the property value
|
|
@ -0,0 +1,7 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 2 tests
|
||||
|
||||
2 Pass
|
||||
Pass e.style['empty-cells'] = "show" should set the property value
|
||||
Pass e.style['empty-cells'] = "hide" should set the property value
|
|
@ -2,8 +2,8 @@ Harness status: OK
|
|||
|
||||
Found 687 tests
|
||||
|
||||
654 Pass
|
||||
33 Fail
|
||||
657 Pass
|
||||
30 Fail
|
||||
Pass background-attachment: scroll
|
||||
Pass background-attachment: fixed
|
||||
Pass background-attachment: inherit
|
||||
|
@ -374,9 +374,9 @@ Pass display: table-cell
|
|||
Pass display: table-caption
|
||||
Pass display: none
|
||||
Pass display: inherit
|
||||
Fail empty-cells: show
|
||||
Fail empty-cells: hide
|
||||
Fail empty-cells: inherit
|
||||
Pass empty-cells: show
|
||||
Pass empty-cells: hide
|
||||
Pass empty-cells: inherit
|
||||
Pass float: left
|
||||
Pass float: right
|
||||
Pass float: none
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Table Module Test: parsing empty-cells with invalid values</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-tables/#propdef-empty-cells">
|
||||
<meta name="assert" content="empty-cells supports only the grammar 'show | hide'.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_invalid_value("empty-cells", "auto");
|
||||
test_invalid_value("empty-cells", "show hide");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Table Module Test: parsing empty-cells with valid values</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-tables/#propdef-empty-cells">
|
||||
<meta name="assert" content="empty-cells supports the full grammar 'show | hide'.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_valid_value("empty-cells", "show");
|
||||
test_valid_value("empty-cells", "hide");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue