Переглянути джерело

LibWeb: Support the “image” synonym for the “img” ARIA role

Additionally: For “img” elements with empty “alt” attributes, change the
default role to the newer, preferred “none” synonym for the older
“presentation” role; import https://wpt.fyi/results/html-aam/roles.html
(which provides test/regression coverage for these changes).
sideshowbarker 7 місяців тому
батько
коміт
ccbc436e85

+ 2 - 0
Libraries/LibWeb/ARIA/RoleType.cpp

@@ -210,6 +210,8 @@ ErrorOr<NonnullOwnPtr<RoleType>> RoleType::build_role_object(Role role, bool foc
         return adopt_nonnull_own_or_enomem(new (nothrow) Group(data));
     case Role::heading:
         return adopt_nonnull_own_or_enomem(new (nothrow) Heading(data));
+    case Role::image:
+        return adopt_nonnull_own_or_enomem(new (nothrow) Img(data));
     case Role::img:
         return adopt_nonnull_own_or_enomem(new (nothrow) Img(data));
     case Role::input:

+ 1 - 0
Libraries/LibWeb/ARIA/Roles.h

@@ -43,6 +43,7 @@ namespace Web::ARIA {
     __ENUMERATE_ARIA_ROLE(gridcell)         \
     __ENUMERATE_ARIA_ROLE(group)            \
     __ENUMERATE_ARIA_ROLE(heading)          \
+    __ENUMERATE_ARIA_ROLE(image)            \
     __ENUMERATE_ARIA_ROLE(img)              \
     __ENUMERATE_ARIA_ROLE(input)            \
     __ENUMERATE_ARIA_ROLE(insertion)        \

+ 7 - 2
Libraries/LibWeb/HTML/HTMLImageElement.cpp

@@ -411,10 +411,15 @@ Optional<ARIA::Role> HTMLImageElement::default_role() const
 {
     // https://www.w3.org/TR/html-aria/#el-img
     // https://www.w3.org/TR/html-aria/#el-img-no-alt
+    // https://w3c.github.io/aria/#image
+    // NOTE: The "image" role value is a synonym for the older "img" role value; however, the el-img test in
+    //       https://wpt.fyi/results/html-aam/roles.html expects the value to be "image" (not "img").
     if (!alt().is_empty())
-        return ARIA::Role::img;
+        return ARIA::Role::image;
     // https://www.w3.org/TR/html-aria/#el-img-empty-alt
-    return ARIA::Role::presentation;
+    // NOTE: The "none" role value is a synonym for the older "presentation" role value; however, the el-img-alt-no-value
+    //       test in https://wpt.fyi/results/html-aam/roles.html expects the value to be "none" (not "presentation").
+    return ARIA::Role::none;
 }
 
 // https://html.spec.whatwg.org/multipage/images.html#use-srcset-or-picture

+ 63 - 0
Tests/LibWeb/Text/expected/wpt-import/html-aam/roles.txt

@@ -0,0 +1,63 @@
+Harness status: OK
+
+Found 58 tests
+
+58 Pass
+Pass	el-address
+Pass	el-article
+Pass	el-blockquote
+Pass	el-button
+Pass	el-code
+Pass	el-dd
+Pass	el-del
+Pass	el-details
+Pass	el-dfn
+Pass	el-dt
+Pass	el-em
+Pass	el-fieldset
+Pass	el-figure
+Pass	el-form
+Pass	el-h1
+Pass	el-h2
+Pass	el-h3
+Pass	el-h4
+Pass	el-h5
+Pass	el-h6
+Pass	el-hgroup
+Pass	el-hr
+Pass	el-img
+Pass	el-input-button
+Pass	el-input-checkbox
+Pass	el-input-email
+Pass	el-input-radio
+Pass	el-input-range
+Pass	el-input-reset
+Pass	el-input-search
+Pass	el-input-submit
+Pass	el-input-tel
+Pass	el-input-text
+Pass	el-input-url
+Pass	el-ins
+Pass	el-li-in-ul
+Pass	el-li-in-ol
+Pass	el-main
+Pass	el-mark
+Pass	el-menu
+Pass	el-meter
+Pass	el-nav
+Pass	el-ol
+Pass	el-option
+Pass	el-output
+Pass	el-p
+Pass	el-progress
+Pass	el-s
+Pass	el-search
+Pass	el-select-listbox
+Pass	el-strong
+Pass	el-sub
+Pass	el-sup
+Pass	el-time
+Pass	el-textarea
+Pass	el-ul
+Pass	el-img-alt-no-value
+Pass	el-img-empty-alt

+ 209 - 0
Tests/LibWeb/Text/input/wpt-import/html-aam/roles.html

@@ -0,0 +1,209 @@
+<!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 defined in <a href="https://w3c.github.io/html-aam/">HTML-AAM</a>. Most test names correspond to a unique ID defined in the spec.<p>
+
+<p>These should remain in alphabetical order, and include all HTML tagnames. If a tag is not tested here, include a pointer to the file where it is tested, such as: <code>&lt;!-- caption -&gt; ./table-roles.html --&gt;</code></p>
+
+
+<!-- a (w/ and w/o href) -> ./roles-contextual.html -->
+<!-- todo: abbr -->
+<address data-testname="el-address" data-expectedrole="group" class="ex">x</address>
+<!-- area -> ./fragile/area-role.html -->
+<article data-testname="el-article" data-expectedrole="article" class="ex">x</article>
+<!-- aside -> ./roles-contextual.html -->
+<!-- todo: audio -->
+<!-- todo: autonomous custom element -->
+<!-- b -> ./roles-generic.html -->
+<!-- base (not mapped) -->
+<!-- bdi -> ./roles-generic.html -->
+<!-- bdo -> ./roles-generic.html -->
+<blockquote data-testname="el-blockquote" data-expectedrole="blockquote" class="ex">x</blockquote>
+<!-- todo: body -->
+<!-- br (not mapped) -->
+<button data-testname="el-button" data-expectedrole="button" class="ex">x</button>
+<!-- todo: canvas -->
+<!-- caption -> ./table-roles.html -->
+<!-- todo: cite -->
+<code data-testname="el-code" data-expectedrole="code" class="ex">x</code>
+<!-- todo: col -->
+<!-- todo: colgroup -->
+<!-- data -> ./roles-generic.html -->
+<!-- todo: datalist -->
+
+<!-- el-dd -->
+<dl>
+  <dt>x</dt>
+  <!-- dt/dd pending listitemkey and listitemvalue roles: https://github.com/w3c/aria/issues/1662 -->
+  <dd data-testname="el-dd" data-expectedrole="definition" class="ex">x</dd>
+</dl>
+
+<del data-testname="el-del" data-expectedrole="deletion" class="ex">x</del>
+<details data-testname="el-details" data-expectedrole="group" class="ex"><summary>x</summary>x</details>
+<dfn data-testname="el-dfn" data-expectedrole="term" class="ex">x</dfn>
+<!-- dir -> ./dir-role.tentative.html -->
+<!-- div -> ./roles-generic.html -->
+<!-- todo: dl -->
+
+<!-- el-dt -->
+<dl>
+  <!-- dt/dd pending listitemkey and listitemvalue roles: https://github.com/w3c/aria/issues/1662 -->
+  <dt data-testname="el-dt" data-expectedrole="term" class="ex">x</dt>
+  <dd>x</dd>
+</dl>
+
+<em data-testname="el-em" data-expectedrole="emphasis" class="ex">x</em>
+<!-- todo: embed -->
+<fieldset data-testname="el-fieldset" data-expectedrole="group" class="ex"><legend>x</legend><input></fieldset>
+<!-- todo: figcaption -->
+<figure data-testname="el-figure" data-expectedrole="figure" class="ex"><img alt="x" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="><figcaption>x</figcaption></figure>
+<!-- footer -> ./roles-contextual.html -->
+<form aria-label="form" data-testname="el-form" data-expectedrole="form" class="ex"><input></form>
+<!-- todo: form-associated custom element -->
+
+<!-- el-h1-h6 -->
+<h1 data-testname="el-h1" data-expectedrole="heading" class="ex">x</h1>
+<h2 data-testname="el-h2" data-expectedrole="heading" class="ex">x</h2>
+<h3 data-testname="el-h3" data-expectedrole="heading" class="ex">x</h3>
+<h4 data-testname="el-h4" data-expectedrole="heading" class="ex">x</h4>
+<h5 data-testname="el-h5" data-expectedrole="heading" class="ex">x</h5>
+<h6 data-testname="el-h6" data-expectedrole="heading" class="ex">x</h6>
+
+<!-- head (not mapped) -->
+
+<!-- header -> ./roles-contextual.html -->
+<hgroup data-testname="el-hgroup" data-expectedrole="group" class="ex"><h1>x</h1></hgroup>
+<hr data-testname="el-hr" data-expectedrole="separator" class="ex">
+<!-- todo: html -->
+<!-- i -> ./roles-generic.html -->
+<!-- todo: iframe -->
+<img alt="x" data-testname="el-img" data-expectedrole="image" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
+
+<!-- Implementations might also be valid if ignored rather than returning 'none' for the following images. -->
+<img alt data-testname="el-img-alt-no-value" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
+<img alt="" data-testname="el-img-empty-alt" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
+
+<input type="button" value="x" data-testname="el-input-button" data-expectedrole="button" class="ex">
+<input type="checkbox" data-testname="el-input-checkbox" data-expectedrole="checkbox" class="ex">
+<!-- todo: input type="color" -->
+<!-- todo: input type="date" -->
+<!-- todo: input type="datetime" -->
+<!-- todo: input type="datetime-local" -->
+<input type="email" data-testname="el-input-email" data-expectedrole="textbox" class="ex">
+<!-- todo: input type="file" -->
+<!-- input type="hidden" (not mapped) -->
+<!-- todo: input type="month" -->
+
+<!-- Blocked: HTML-AAM Issue #467 -->
+<!-- <input type="number" data-testname="el-input-number" data-expectedrole="spinbutton" class="ex"> -->
+
+<!-- todo: input type="password" -->
+<input type="radio" data-testname="el-input-radio" data-expectedrole="radio" class="ex">
+<input type="range" data-testname="el-input-range" data-expectedrole="slider" class="ex">
+<input type="reset" value="x" data-testname="el-input-reset" data-expectedrole="button" class="ex">
+<input type="search" data-testname="el-input-search" data-expectedrole="searchbox" class="ex">
+<input type="submit" value="x" data-testname="el-input-submit" data-expectedrole="button" class="ex">
+<input type="tel" data-testname="el-input-tel" data-expectedrole="textbox" class="ex">
+<input type="text" data-testname="el-input-text" data-expectedrole="textbox" class="ex">
+<!-- todo: input (type attribute in the Text, Search, Telephone, URL, or E-mail states with a suggestions source element) -->
+<!-- todo: input type="time" -->
+<input type="url" data-testname="el-input-url" data-expectedrole="textbox" class="ex">
+<!-- todo: input type="week" -->
+<ins data-testname="el-ins" data-expectedrole="insertion" class="ex">x</ins>
+<!-- todo: kbd -->
+<!-- todo: label -->
+<!-- todo: legend -->
+
+<!-- el-li -->
+<!-- li (orphaned) -> ./roles-generic.html -->
+<ul><li data-testname="el-li-in-ul" data-expectedrole="listitem" class="ex">x</li><li>x</li></ul>
+<ol><li data-testname="el-li-in-ol" data-expectedrole="listitem" class="ex">x</li><li>x</li></ol>
+
+<!-- link (not mapped) -->
+<main data-testname="el-main" data-expectedrole="main" class="ex">x</main>
+<!-- map (not mapped) -->
+<mark data-testname="el-mark" data-expectedrole="mark" class="ex">x</mark>
+<!-- todo: math -->
+<menu data-testname="el-menu" data-expectedrole="list" class="ex"><li>x</li></menu>
+<!-- meta (not mapped) -->
+<meter data-testname="el-meter" data-expectedrole="meter" class="ex" min="0" max="100" low="20" high="80" optimum="60" value="50">x</meter>
+<nav data-testname="el-nav" data-expectedrole="navigation" class="ex">x</nav>
+<!-- noscript (not mapped) -->
+<!-- object (not mapped) -->
+<ol data-testname="el-ol" data-expectedrole="list" class="ex"><li>x</li><li>x</li></ol>
+
+<!-- optgroup -> ./fragile/optgroup-role.html -->
+
+<!-- option -->
+<select>
+  <option data-testname="el-option" data-expectedrole="option" class="ex">x</option>
+  <option>x</option>
+</select>
+
+<output data-testname="el-output" data-expectedrole="status" class="ex">x</output>
+<p data-testname="el-p" data-expectedrole="paragraph" class="ex">x</p>
+<!-- param (not mapped) -->
+<!-- todo: picture -->
+<!-- pre -> ./roles-generic.html -->
+<progress data-testname="el-progress" data-expectedrole="progressbar" class="ex">x</progress>
+<!-- q -> ./roles-generic.html -->
+<!-- todo: rp -> /ruby-aam? -->
+<!-- todo: rt -> /ruby-aam? -->
+<!-- todo: ruby -> /ruby-aam? -->
+<s data-testname="el-s" data-expectedrole="deletion" class="ex">x</s>
+<!-- samp -> ./roles-generic.html -->
+<!-- script (not mapped) -->
+<search data-testname="el-search" data-expectedrole="search" class="ex">x</search>
+<!-- section -> ./roles-contextual.html -->
+
+<!-- Blocked: HTML-AAM Issue #467 -->
+<!-- <select data-testname="el-select-combobox" data-expectedrole="combobox" class="ex"><option>a1</option><option>a2</option></select>-->
+
+<select data-testname="el-select-listbox" size="2" data-expectedrole="listbox" class="ex"><option>b1</option><option>b2</option></select>
+
+<!-- slot (not mapped) -->
+<!-- small -> ./roles-generic.html -->
+<!-- source (not mapped) -->
+<!-- span -> ./roles-generic.html -->
+<strong data-testname="el-strong" data-expectedrole="strong" class="ex">x</strong>
+<!-- style (not mapped) -->
+<sub data-testname="el-sub" data-expectedrole="subscript" class="ex">x</sub>
+<!-- todo: summary -->
+<sup data-testname="el-sup" data-expectedrole="superscript" class="ex">x</sup>
+<!-- todo: svg (see /graphics-aam and /svg-aam tests) -->
+<!-- table -> ./table-roles.html -->
+<!-- tbody -> ./table-roles.html -->
+<!-- td -> ./table-roles.html -->
+<!-- template (not mapped) -->
+<!-- tfoot -> ./table-roles.html -->
+<!-- th -> ./table-roles.html -->
+<!-- thead -> ./table-roles.html -->
+<time data-testname="el-time" data-expectedrole="time" class="ex">x</time>
+<!-- title (not mapped) -->
+<!-- tr -> ./table-roles.html -->
+<textarea data-testname="el-textarea" data-expectedrole="textbox" class="ex">x</textarea>
+<!-- track (not mapped) -->
+<!-- u -> ./roles-generic.html -->
+<ul data-testname="el-ul" data-expectedrole="list" class="ex"><li>x</li><li>x</li></ul>
+<!-- var (not mapped) -->
+<!-- todo: video -->
+<!-- wbr (not mapped) -->
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+AriaUtils.verifyGenericRolesBySelector(".ex-generic");
+</script>
+
+</body>
+</html>