pour-engine 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,6 @@
6
6
  export default {
7
7
  engine: {
8
8
  name: 'pour engine',
9
- version: '1.8.0',
9
+ version: '1.9.0',
10
10
  },
11
11
  };
@@ -111,7 +111,7 @@ meaning that only a person can settle, even where a rule decides most real pages
111
111
 
112
112
  | SC | Name | Level | Coverage | Rules |
113
113
  |---|---|---|---|---|
114
- | 4.1.2 | [Name, Role, Value](https://www.w3.org/WAI/WCAG22/Understanding/name-role-value.html) | A | Partially automated | input-image-alt, form-label, link-name, aria-allowed-attr, aria-attr-valid, aria-field-name, aria-hidden-focus, aria-valid-refs, button-name, dialog-name, frame-title, label-for-valid, nested-interactive, role-required-aria, valid-role |
114
+ | 4.1.2 | [Name, Role, Value](https://www.w3.org/WAI/WCAG22/Understanding/name-role-value.html) | A | Partially automated | input-image-alt, form-label, link-name, aria-attr-valid, aria-field-name, aria-hidden-focus, aria-valid-refs, button-name, dialog-name, frame-title, label-for-valid, nested-interactive, role-required-aria, valid-role |
115
115
  | 4.1.3 | [Status Messages](https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html) | AA | Manual review | — |
116
116
 
117
117
  **Totals:** 30 partially automated · 56 manual — with 74 rules.
@@ -1,26 +1,30 @@
1
- // WCAG SC 4.1.2 Name, Role, Value (Level A)
2
- // An ARIA attribute the role does not support is INERT. Measured in Chromium:
3
- // aria-expanded on a button exposes expanded=false, and the same attribute on
4
- // a complementary landmark exposes no state at all. It is dropped, not
5
- // misreported, so the old "announces the wrong state" wording was wrong.
1
+ // ARIA 1.2 §8.6, repeated verbatim in the 1.3 draft: "authors MUST only use
2
+ // non-global states and properties on elements with a role supporting the
3
+ // state or property". An unsupported attribute breaks that MUST, so this is a
4
+ // real, provable authoring error and the rule asserts it.
6
5
  //
7
- // Which is why this REVIEWS rather than fails. ARIA 1.2 §5.2.3 says authors
8
- // MAY provide supported states and user agents MUST map them; "prohibited"
9
- // (§5.2.5) is a separate category this rule does not cover. An unsupported
10
- // attribute is therefore not a spec violation, and name, role and value are
11
- // all still conveyed correctly, so no success criterion provably fails.
6
+ // It is NOT a WCAG failure, which is why it lives here rather than under
7
+ // 4.1.2. An unsupported attribute is INERT, measured in Chromium:
8
+ // aria-expanded on a button exposes expanded=false, while the same attribute
9
+ // on a complementary landmark exposes no state at all. It is dropped, not
10
+ // misreported. So the role is still exposed, the name is still computed, and
11
+ // nothing is announced incorrectly. Name, role and value all survive, which
12
+ // is all 4.1.2 asks for.
12
13
  //
13
- // The 4.1.2 tag stays because there IS a real failure hiding here: if the
14
- // element genuinely has the state the author was reaching for, that state is
15
- // now invisible to assistive technology. Whether it does is exactly what the
16
- // DOM cannot establish, so it is a question for a person. Same reasoning that
17
- // put aria-label-misuse in best-practice.
14
+ // What CAN fail 4.1.2 is the thing underneath: if the element genuinely has
15
+ // the state the author reached for, that state is now invisible. Whether it
16
+ // does is exactly what the DOM cannot establish, so the message asks rather
17
+ // than asserts. Reporting the ARIA error as a WCAG violation would have been
18
+ // asserting a criterion failure off the back of a question.
19
+ //
20
+ // Note "unsupported" is distinct from "prohibited" (§5.2.5), a separate
21
+ // category about naming that this rule does not cover.
18
22
  //
19
23
  // Worth knowing when comparing against other tools: aria-expanded WAS
20
24
  // inherited into complementary, banner, heading, img and list under ARIA 1.1,
21
25
  // and was narrowed in 1.2 (narrowed again in the 1.3 draft). Markup written
22
26
  // against 1.1 is not conforming under 1.2, and a tool on the older baseline
23
- // stays silent on it.
27
+ // stays silent on it. Neither reading is a bug; they are different editions.
24
28
  import { GLOBAL_ARIA, ROLE_ARIA, KNOWN_ARIA, effectiveRole } from '../../lib/roles.js';
25
29
 
26
30
  // aria-label/labelledby misuse on generic elements has its own rule
@@ -30,9 +34,9 @@ const HANDLED_ELSEWHERE = new Set(['label', 'labelledby']);
30
34
  export default {
31
35
  id: 'aria-allowed-attr',
32
36
  impact: 'moderate',
33
- tags: ['wcag2a', 'wcag412'],
34
- help: 'ARIA attributes must be allowed for the element’s role',
35
- helpUrl: 'https://www.w3.org/WAI/WCAG22/Understanding/name-role-value.html',
37
+ tags: ['best-practice'],
38
+ help: 'ARIA attributes must be supported by the element’s role',
39
+ helpUrl: 'https://www.w3.org/TR/wai-aria-1.2/#state_property_processing',
36
40
  selector: '*',
37
41
  visibleOnly: false,
38
42
  evaluate(element) {
@@ -56,9 +60,9 @@ export default {
56
60
  if (!disallowed.length) return { status: 'pass' };
57
61
  const names = disallowed.map((n) => `aria-${n}`);
58
62
  return {
59
- status: 'incomplete',
60
- message: `${names.join(', ')} is not supported on role "${role}", so the browser drops it and assistive technology never sees it. Nothing is announced wrongly, but nothing is announced at all. If this element really does have that state, it is currently invisible: check whether it needs conveying another way.`,
61
- fix: `Move ${names.join('/')} to the element whose role supports it, usually the control that toggles this one, or remove it if the element has no such state.`,
63
+ status: 'fail',
64
+ message: `${names.join(', ')} is not supported on role "${role}", so the browser drops it and assistive technology never sees it. Nothing is announced wrongly, but nothing is announced at all. If this element really does have that state, it is currently invisible to anyone using a screen reader.`,
65
+ fix: `Move ${names.join('/')} to the element whose role supports it, usually the control that toggles this one, or remove it if the element has no such state. Adding a role to this element to make the attribute legal is rarely right: the host language restricts which roles each element may take.`,
62
66
  };
63
67
  },
64
68
  };
@@ -42,7 +42,10 @@ import audioControl from './wcag/1.4.2-audio-control.js';
42
42
  import pauseStopHide from './wcag/2.2.2-pause-stop-hide.js';
43
43
  import mediaCaptions from './wcag/1.2.2-media-captions.js';
44
44
  import ariaAttrValid from './wcag/4.1.2-aria-attr-valid.js';
45
- import ariaAllowedAttr from './wcag/4.1.2-aria-allowed-attr.js';
45
+ // Demoted to best-practice: an unsupported ARIA attribute breaks an ARIA
46
+ // author MUST (1.2 §8.6) but is INERT, so name, role and value all survive
47
+ // and no success criterion fails (see the note in the rule file).
48
+ import ariaAllowedAttr from './best-practice/aria-allowed-attr.js';
46
49
  import ariaFieldName from './wcag/4.1.2-aria-field-name.js';
47
50
  // Demoted to best-practice: prohibited-but-inert ARIA on a generic element
48
51
  // fails no success criterion (see the note in the rule file).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pour-engine",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "Accessibility (WCAG 2.2) audit engine written from the W3C specifications — runs entirely in the browser, no dependencies.",
5
5
  "type": "module",
6
6
  "main": "engine/index.js",