mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-22 20:45:14 +00:00
LibWeb: Align default “th” and “td” roles with HTML-AAM spec and tests
This change aligns the default roles for “th” and “td” elements with the requirements in the HTML-AAM spec, and with the corresponding WPT tests at https://wpt.fyi/results/html-aam/table-roles.html, and with the behavior in other engines. Otherwise, without this change, the default role values for “th” and “td” elements in some cases don’t match the behavior in other engines, and don’t match the expected results for the corresponding WPT tests.
This commit is contained in:
parent
2d638485a8
commit
e49fe384d1
Notes:
github-actions[bot]
2024-12-12 00:02:47 +00:00
Author: https://github.com/sideshowbarker Commit: https://github.com/LadybirdBrowser/ladybird/commit/e49fe384d1e Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2822 Reviewed-by: https://github.com/ADKaster ✅
5 changed files with 252 additions and 10 deletions
|
@ -196,16 +196,31 @@ WebIDL::Long HTMLTableCellElement::cell_index() const
|
|||
|
||||
Optional<ARIA::Role> HTMLTableCellElement::default_role() const
|
||||
{
|
||||
// TODO: For td:
|
||||
// role=cell if the ancestor table element is exposed as a role=table
|
||||
// role=gridcell if the ancestor table element is exposed as a role=grid or treegrid
|
||||
// No corresponding role if the ancestor table element is not exposed as a role=table, grid or treegrid
|
||||
// For th:
|
||||
// role=columnheader, rowheader or cell if the ancestor table element is exposed as a role=table
|
||||
// role=columnheader, rowheader or gridcell if the ancestor table element is exposed as a role=grid or treegrid
|
||||
// No corresponding role if the ancestor table element is not exposed as a role=table, grid or treegrid
|
||||
// https://www.w3.org/TR/html-aria/#el-td
|
||||
// https://www.w3.org/TR/html-aria/#el-th
|
||||
if (local_name() == TagNames::th) {
|
||||
for (auto const* ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
|
||||
// AD-HOC: The ancestor checks here aren’t explicitly defined in the spec, but implicitly follow from what
|
||||
// the spec does state, and from the physical placement/layout of elements. Also, the el-th and el-th-in-row
|
||||
// tests at https://wpt.fyi/results/html-aam/table-roles.html require doing these ancestor checks — and
|
||||
// implementing them causes the behavior to match that of other engines.
|
||||
// https://w3c.github.io/html-aam/#el-th-columnheader
|
||||
if (get_attribute(HTML::AttributeNames::scope) == "columnheader" || ancestor->local_name() == TagNames::thead)
|
||||
return ARIA::Role::columnheader;
|
||||
// https://w3c.github.io/html-aam/#el-th-rowheader
|
||||
if (get_attribute(HTML::AttributeNames::scope) == "rowheader" || ancestor->local_name() == TagNames::tbody)
|
||||
return ARIA::Role::rowheader;
|
||||
}
|
||||
}
|
||||
auto const* table_element = first_ancestor_of_type<HTMLTableElement>();
|
||||
// https://w3c.github.io/html-aam/#el-td
|
||||
// https://w3c.github.io/html-aam/#el-th/
|
||||
// (ancestor table element has table role)
|
||||
if (table_element->role_or_default() == ARIA::Role::table)
|
||||
return ARIA::Role::cell;
|
||||
// https://w3c.github.io/html-aam/#el-td-gridcell
|
||||
// https://w3c.github.io/html-aam/#el-th-gridcell
|
||||
// (ancestor table element has grid or treegrid role)
|
||||
if (first_is_one_of(table_element->role_or_default(), ARIA::Role::grid, ARIA::Role::gridcell))
|
||||
return ARIA::Role::gridcell;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 7 tests
|
||||
|
||||
7 Pass
|
||||
Pass el-table
|
||||
Pass el-caption
|
||||
Pass el-tr-thead
|
||||
Pass el-th
|
||||
Pass el-tr-tbody
|
||||
Pass el-th-in-row
|
||||
Pass el-td
|
|
@ -0,0 +1,14 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 9 tests
|
||||
|
||||
9 Pass
|
||||
Pass div role is caption (in div with table role)
|
||||
Pass orphan p role is caption
|
||||
Pass span role is cell (in div with row role, in div with rowgroup role, in div with table role)
|
||||
Pass orphan span role is cell
|
||||
Pass span role is columnheader (in div with row role, in div with rowgroup role, in div with table role)
|
||||
Pass div role is row (in div with rowgroup role, in div with table role)
|
||||
Pass div role is rowgroup (in div with table role)
|
||||
Pass role is rowheader (in div with row role, in div with rowgroup role, in div with table role)
|
||||
Pass div role is table
|
53
Tests/LibWeb/Text/input/wpt-import/html-aam/table-roles.html
Normal file
53
Tests/LibWeb/Text/input/wpt-import/html-aam/table-roles.html
Normal file
|
@ -0,0 +1,53 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML-AAM Role Verification Tests</title>
|
||||
<script src="../resources/testharness.js"></script>
|
||||
<script src="../resources/testharnessreport.js"></script>
|
||||
<script src="../resources/testdriver.js"></script>
|
||||
<script src="../resources/testdriver-vendor.js"></script>
|
||||
<script src="../resources/testdriver-actions.js"></script>
|
||||
<script src="../wai-aria/scripts/aria-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>Tests the computedrole mappings for the table-related roles defined in <a href="https://w3c.github.io/html-aam/">HTML-AAM</a>. Most test names correspond to unique ID defined in the spec.<p>
|
||||
|
||||
<!-- ARIA table roles tested in wpt/wai-aria/role/table-roles.html -->
|
||||
|
||||
<table data-testname="el-table" data-expectedrole="table" class="ex">
|
||||
<caption data-testname="el-caption" data-expectedrole="caption" class="ex">caption</caption>
|
||||
<thead>
|
||||
<tr data-testname="el-tr-thead" data-expectedrole="row" class="ex">
|
||||
<th data-testname="el-th" data-expectedrole="columnheader" class="ex">a</th>
|
||||
<th>b</th>
|
||||
<th>c</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr data-testname="el-tr-tbody" data-expectedrole="row" class="ex">
|
||||
<th data-testname="el-th-in-row" data-expectedrole="rowheader" class="ex">1</th>
|
||||
<td data-testname="el-td" data-expectedrole="cell" class="ex">2</td>
|
||||
<td>3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>4</th>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>x</th>
|
||||
<th>y</th>
|
||||
<th>z</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
AriaUtils.verifyRolesBySelector(".ex");
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,148 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Table Role Verification Tests</title>
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../../resources/testdriver.js"></script>
|
||||
<script src="../../resources/testdriver-vendor.js"></script>
|
||||
<script src="../../resources/testdriver-actions.js"></script>
|
||||
<script src="../../wai-aria/scripts/aria-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<p>Tests <a href="https://w3c.github.io/aria/#table">table</a> and related roles.</p>
|
||||
|
||||
<!-- HTML <table> Elements Testing -->
|
||||
|
||||
<!-- <caption> -> wpt/html-aam/table-roles.html -->
|
||||
|
||||
<!-- <table> -> wpt/html-aam/table-roles.html -->
|
||||
<!-- <tbody> -> wpt/html-aam/table-roles.html -->
|
||||
|
||||
<!-- <td> -> wpt/html-aam/table-roles.html -->
|
||||
|
||||
<!-- <tfoot> -> wpt/html-aam/table-roles.html -->
|
||||
|
||||
<!-- <th> -> wpt/html-aam/table-roles.html -->
|
||||
<!-- <thead> -> wpt/html-aam/table-roles.html -->
|
||||
|
||||
<!-- <tr> -> wpt/html-aam/table-roles.html -->
|
||||
|
||||
|
||||
<!-- ARIA Grid Elements Testing -->
|
||||
|
||||
<!-- Grid roles tested in ./grid-roles.html -->
|
||||
|
||||
|
||||
<!-- ARIA Table Roles Testing -->
|
||||
|
||||
<!-- caption -->
|
||||
<div role="table">
|
||||
<div role="caption" data-testname="div role is caption (in div with table role)" data-expectedrole="caption" class="ex">x</div>
|
||||
</div>
|
||||
|
||||
<p role="caption" data-testname="orphan p role is caption" data-expectedrole="caption" class="ex">x</p>
|
||||
|
||||
<!-- cell -->
|
||||
<div role="table">
|
||||
<div role="rowgroup">
|
||||
<div role="row">
|
||||
<span role="columnheader">x</span>
|
||||
<span role="columnheader">x</span>
|
||||
</div>
|
||||
</div>
|
||||
<div role="rowgroup">
|
||||
<div role="row">
|
||||
<span role="cell" data-testname="span role is cell (in div with row role, in div with rowgroup role, in div with table role)" data-expectedrole="cell" class="ex">x</span>
|
||||
<span role="cell">x</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span role="cell" data-testname="orphan span role is cell" data-expectedrole="cell" class="ex">x</span>
|
||||
|
||||
<!-- columnheader -->
|
||||
<div role="table">
|
||||
<div role="rowgroup">
|
||||
<div role="row">
|
||||
<span role="columnheader" data-testname="span role is columnheader (in div with row role, in div with rowgroup role, in div with table role)" data-expectedrole="columnheader" class="ex">x</span>
|
||||
<span role="columnheader">x</span>
|
||||
<span role="columnheader">x</span>
|
||||
</div>
|
||||
</div>
|
||||
<div role="rowgroup">
|
||||
<div role="row">
|
||||
<span role="rowheader">x</span>
|
||||
<span role="cell">x</span>
|
||||
<span role="cell">x</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- row -->
|
||||
<div role="table">
|
||||
<div role="rowgroup">
|
||||
<div role="row" data-testname="div role is row (in div with rowgroup role, in div with table role)" data-expectedrole="row" class="ex">
|
||||
<span role="columnheader">x</span>
|
||||
</div>
|
||||
</div>
|
||||
<div role="rowgroup">
|
||||
<div role="row">
|
||||
<span role="cell">x</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- rowgroup -->
|
||||
<div role="table">
|
||||
<div role="rowgroup" data-testname="div role is rowgroup (in div with table role)" data-expectedrole="rowgroup" class="ex">
|
||||
<div role="row">
|
||||
<span role="columnheader">x</span>
|
||||
<span role="columnheader">x</span>
|
||||
</div>
|
||||
</div>
|
||||
<div role="rowgroup">
|
||||
<div role="row">
|
||||
<span role="cell">x</span>
|
||||
<span role="cell">x</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- rowheader -->
|
||||
<div role="table">
|
||||
<div role="rowgroup">
|
||||
<div role="row">
|
||||
<span role="columnheader">x</span>
|
||||
<span role="columnheader">x</span>
|
||||
<span role="columnheader">x</span>
|
||||
</div>
|
||||
</div>
|
||||
<div role="rowgroup">
|
||||
<div role="row">
|
||||
<span role="rowheader" data-testname="role is rowheader (in div with row role, in div with rowgroup role, in div with table role)" data-expectedrole="rowheader" class="ex">x</span>
|
||||
<span role="cell">x</span>
|
||||
<span role="cell">x</span>
|
||||
<span role="cell">x</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- table -->
|
||||
<div role="table" data-testname="div role is table" data-expectedrole="table" class="ex">
|
||||
<div role="row">
|
||||
<span role="columnheader">x</span>
|
||||
<span role="columnheader">x</span>
|
||||
</div>
|
||||
<div role="row">
|
||||
<span role="cell">x</span>
|
||||
<span role="cell">x</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
AriaUtils.verifyRolesBySelector(".ex");
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Reference in a new issue