@surea11y/core 1.0.0 → 1.0.1
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.
- package/CHANGELOG.md +17 -0
- package/README.md +382 -81
- package/docs/ENGINE_OPTIONS.md +66 -1
- package/docs/I18N.md +3 -3
- package/docs/OUTPUT_SCHEMA.md +5 -5
- package/docs/RULE_TAXONOMY.md +9 -8
- package/docs/TROUBLESHOOTING.md +2 -2
- package/docs/WCAG_CONFORMANCE.md +1 -1
- package/package.json +2 -2
- package/src/checks/automatic/aria-allowed-attr.js +47 -24
- package/src/core.js +978 -39
- package/src/i18n/fr.js +314 -1
package/docs/I18N.md
CHANGED
|
@@ -6,10 +6,10 @@ Every rule's title/description, and every occurrence's summary/hint, is localize
|
|
|
6
6
|
|
|
7
7
|
| Locale | File | Keys | Coverage vs. English |
|
|
8
8
|
|---|---|---|---|
|
|
9
|
-
| `en` (English) | `src/i18n/en.js` |
|
|
10
|
-
| `fr` (French) | `src/i18n/fr.js` |
|
|
9
|
+
| `en` (English) | `src/i18n/en.js` | 600 | 100% (the canonical/fallback set) |
|
|
10
|
+
| `fr` (French) | `src/i18n/fr.js` | 600 | 100% |
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Both locales are fully translated as of this writing. That won't stay automatically true — every time a new rule (or a new i18n key) is added to `en.js`, `fr.js` needs the same key added, or it silently falls back to English for that string (see the fallback behavior below). There's no automated check for this yet; diff `Object.keys(require('./src/i18n/en.js'))` against `fr.js` after adding a rule to catch drift before it ships.
|
|
13
13
|
|
|
14
14
|
## Selecting a locale
|
|
15
15
|
|
package/docs/OUTPUT_SCHEMA.md
CHANGED
|
@@ -103,7 +103,7 @@ Notes:
|
|
|
103
103
|
|
|
104
104
|
## An occurrence (`occurrences[i]`)
|
|
105
105
|
|
|
106
|
-
Only present when `outcome` is `fail` or `cantTell` (a `pass`/`notApplicable` result has `occurrences: []` — this engine does not enumerate the elements it passed, only the ones it flagged
|
|
106
|
+
Only present when `outcome` is `fail` or `cantTell` (a `pass`/`notApplicable` result has `occurrences: []` — this engine does not enumerate the elements it passed, only the ones it flagged).
|
|
107
107
|
|
|
108
108
|
```ts
|
|
109
109
|
{
|
|
@@ -114,7 +114,7 @@ Only present when `outcome` is `fail` or `cantTell` (a `pass`/`notApplicable` re
|
|
|
114
114
|
hint: string,
|
|
115
115
|
i18n: { summaryKey: string, hintKey: string, params: object } | null,
|
|
116
116
|
data: {
|
|
117
|
-
visibilityFilter?: { targetSet: string, accEligible: boolean | null, reasons: string[] },
|
|
117
|
+
visibilityFilter?: { eligible: boolean, targetSet: string, accEligible: boolean | null, reasons: string[] },
|
|
118
118
|
details?: object // rule-specific, non-normative — see below
|
|
119
119
|
}
|
|
120
120
|
}
|
|
@@ -128,7 +128,7 @@ Only present when `outcome` is `fail` or `cantTell` (a `pass`/`notApplicable` re
|
|
|
128
128
|
| `summary` | Human-readable, already localized ("This button has no accessible name."). |
|
|
129
129
|
| `hint` | Human-readable remediation guidance, already localized. |
|
|
130
130
|
| `i18n` | The raw translation keys behind `summary`/`hint`, if you want to re-render them in a different locale yourself without re-running the scan. `null` if the occurrence didn't use key-based i18n. |
|
|
131
|
-
| `data.visibilityFilter` | Present on most occurrences: why the engine considered this element eligible
|
|
131
|
+
| `data.visibilityFilter` | Present on most occurrences: why the engine considered this element eligible (or not) under whichever eligibility model the rule used. `eligible` is that result; `targetSet` says which model produced it (`'dom'`: raw DOM/CSS visibility — most rules; `'acc'`: accessibility-tree eligibility). `accEligible` mirrors `eligible` only when `targetSet` is `'acc'`, otherwise `null` — don't read it as a second, independent signal. `reasons` is a list of machine-readable exclusion codes when `eligible: false`. |
|
|
132
132
|
| `data.details` | Rule-specific structured data (e.g. `reasonCode`, computed metrics, resolved references) — **non-normative**: useful for building richer UI or debugging, but never changes what `outcome`/`severity` mean. Shape varies per rule; treat as best-effort extra context, not a stable contract. |
|
|
133
133
|
|
|
134
134
|
## A composite result (`rulesResults[i]`)
|
|
@@ -202,7 +202,7 @@ const result = runDomRulesInPage(
|
|
|
202
202
|
{
|
|
203
203
|
"selector": "html > body > button",
|
|
204
204
|
"html": "<button></button>",
|
|
205
|
-
"structuralPath": [1,
|
|
205
|
+
"structuralPath": [1, 1],
|
|
206
206
|
"summary": "This button has no accessible name.",
|
|
207
207
|
"hint": "Provide visible button text or a programmatic accessible-name mechanism (for example aria-label) so assistive technologies can identify the button.",
|
|
208
208
|
"data": {
|
|
@@ -222,7 +222,7 @@ const result = runDomRulesInPage(
|
|
|
222
222
|
{
|
|
223
223
|
"selector": "html > body > img",
|
|
224
224
|
"html": "<img src=\"logo.png\">",
|
|
225
|
-
"structuralPath": [1,
|
|
225
|
+
"structuralPath": [1, 0],
|
|
226
226
|
"summary": "Missing alt attribute on <img>.",
|
|
227
227
|
"hint": "Add an alt attribute (use alt=\"\" only for decorative images)."
|
|
228
228
|
}
|
package/docs/RULE_TAXONOMY.md
CHANGED
|
@@ -12,7 +12,7 @@ Encoded by: `meta.type`
|
|
|
12
12
|
|
|
13
13
|
- `automatic`
|
|
14
14
|
- Rule makes a **normative decision**
|
|
15
|
-
- Allowed outcomes: `pass`, `fail`, `notApplicable`
|
|
15
|
+
- Allowed outcomes: `pass`, `fail`, `notApplicable`, and `cantTell` as a defensive fallback only (e.g. an internal-failure safety net, or a computability gate a rule can't resolve — see `contrast-minimum.js`/`contrast-enhanced.js`/`contrast-computable.js`/`target-size-minimum.js`), never as its primary intended path
|
|
16
16
|
- `manual`
|
|
17
17
|
- Rule signals **human review required**
|
|
18
18
|
- Allowed outcomes: `cantTell`, `notApplicable`
|
|
@@ -24,7 +24,7 @@ Manual rules MUST NOT make normative failure decisions.
|
|
|
24
24
|
### 1.2 Intent
|
|
25
25
|
Encoded by: **rule id suffix**
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Illustrative intents (from the image-alternatives family used as the running example in §2, not an exhaustive list — the ruleset's 125 rules use dozens of distinct suffixes; `docs/RULE_CATALOG.md` is the generated, always-current list):
|
|
28
28
|
|
|
29
29
|
- `present`
|
|
30
30
|
- Verifies that a required **mechanism exists**
|
|
@@ -43,7 +43,7 @@ Intent determines whether a rule can be automatic.
|
|
|
43
43
|
### 1.3 Target Family
|
|
44
44
|
Encoded by: **rule id prefix**
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
Illustrative families, from the image-alternatives cluster (WCAG 1.1.1) used as the running example in §2 — not an exhaustive list. The ruleset's 125 rules span dozens of families (`aria-*`, `contrast-*`, `dialog-*`, `iframe-*`, `label-*`, `link-*`, `list-*`, `landmark-*`, and more); see `docs/RULE_CATALOG.md` for the generated, always-current list:
|
|
47
47
|
|
|
48
48
|
- `img`
|
|
49
49
|
- `area`
|
|
@@ -67,12 +67,13 @@ Rules MUST NOT mix families.
|
|
|
67
67
|
### 1.4 Target Set (Tree Scope)
|
|
68
68
|
Encoded by: `data.visibilityFilter.targetSet`
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
- `acc` (accessibility tree)
|
|
70
|
+
Values used by this ruleset:
|
|
71
|
+
- `acc` (accessibility tree) — most rules
|
|
72
|
+
- `dom` (raw DOM/CSS visibility, no accessibility-tree computation) — e.g. `label-in-name.js`
|
|
72
73
|
|
|
73
|
-
Rules
|
|
74
|
-
- `helpers.isAccTreeEligible`
|
|
75
|
-
- `helpers.getEligibilityInfo(..., { targetSet: "acc" })`
|
|
74
|
+
Rules log eligibility against whichever tree scope they target using:
|
|
75
|
+
- `helpers.isAccTreeEligible` / `helpers.isDomVisibleEligible`
|
|
76
|
+
- `helpers.getEligibilityInfo(..., { targetSet: "acc" | "dom" })`
|
|
76
77
|
|
|
77
78
|
This is a semantic constraint, not logging noise.
|
|
78
79
|
|
package/docs/TROUBLESHOOTING.md
CHANGED
|
@@ -39,9 +39,9 @@ No — see [`WCAG_CONFORMANCE.md`](./WCAG_CONFORMANCE.md). A `pass` means every
|
|
|
39
39
|
|
|
40
40
|
Treat it as "needs a human to look" — it's neither pass nor fail by design. Most teams log `cantTell` findings without failing CI on them, since failing a build on something the engine explicitly couldn't determine tends to train people to ignore the gate. See [`POLICY.md`](./POLICY.md) if you want to reshape this behavior (e.g. via a custom policy contract), and [`INTEGRATION.md`](./INTEGRATION.md#ci-gating-a-build-on-the-result) for a concrete CI-gating example.
|
|
41
41
|
|
|
42
|
-
## "
|
|
42
|
+
## "What happens if a locale is only partially translated?"
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
Missing keys fall back to English per-string (never a blank or broken result), so a partial locale degrades gracefully rather than failing outright — see [`I18N.md`](./I18N.md) for the mechanism and current coverage. Both shipped locales (`en`, `fr`) are at full parity as of this writing, but that's not guaranteed to stay true automatically: adding a new rule adds a new key to `en.js`, and unless the same key is added to `fr.js` (or any other locale file you maintain), that string falls back to English until it is.
|
|
45
45
|
|
|
46
46
|
## "`runDomRulesInPage` vs `runa11yCoreInPage` — which one do I want?"
|
|
47
47
|
|
package/docs/WCAG_CONFORMANCE.md
CHANGED
|
@@ -4,7 +4,7 @@ How individual rule results relate to a WCAG Success Criterion (SC), and what su
|
|
|
4
4
|
|
|
5
5
|
## The three layers
|
|
6
6
|
|
|
7
|
-
1. **Atomic rules** (`checksResults[]`) — one normative decision each, e.g. "does this `<img>` have an `alt` attribute." See [`RULE_CATALOG.md`](./RULE_CATALOG.md) for all
|
|
7
|
+
1. **Atomic rules** (`checksResults[]`) — one normative decision each, e.g. "does this `<img>` have an `alt` attribute." See [`RULE_CATALOG.md`](./RULE_CATALOG.md) for all 125.
|
|
8
8
|
2. **Facets** — a WCAG SC is usually bigger than any one rule can decide deterministically. Internally, each SC is broken into named "facets" (e.g. 1.1.1 Non-text Content has facets like `img-alt-attr-present`, `text-alternative-quality`, `decorative-null`) tracked in `src/coverage/wcag-facets.js`, each marked `full` (a rule decides it with high confidence), `partial` (a rule decides *part* of it — see each rule's own scope notes), or `manual` (no safe automated heuristic exists at all). Run `npm run coverage` to regenerate `coverage/coverage-report.md`, the per-SC facet breakdown.
|
|
9
9
|
3. **Composite (WCAG-SC rollup) rules** (`rulesResults[]`) — a generated aggregate of every atomic rule mapped to one SC, giving you one pass/fail/cantTell/notApplicable verdict per SC instead of having to roll up dozens of atomic results yourself. See [`RULE_CATALOG.md`](./RULE_CATALOG.md#composite-wcag-sc-rollup-rules-31) for the full list (e.g. `wcag-1.1.1-non-text-content` rolls up 22 atomic rules).
|
|
10
10
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@surea11y/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Lightweight DOM rules accessibility core with modular rules.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"surea11y": "
|
|
7
|
+
"surea11y": "bin/core.js"
|
|
8
8
|
},
|
|
9
9
|
"author": "Jorge Rumoroso",
|
|
10
10
|
"license": "MIT",
|
|
@@ -22,12 +22,7 @@
|
|
|
22
22
|
* - SUPPORTED_ATTRS_BY_ROLE widened 2026-07-21 (7 new roles), cross-checked
|
|
23
23
|
* against a widely-used reference engine's own per-role `allowedAttrs`
|
|
24
24
|
* table AND verified each addition is an unambiguous, well-established ARIA
|
|
25
|
-
* fact rather than a blind import
|
|
26
|
-
* far more than were reconciled here; this pass deliberately took only the
|
|
27
|
-
* additions with clear, specific supported attributes (not just the
|
|
28
|
-
* near-universal, thin `aria-expanded` that engine allows on most roles), and
|
|
29
|
-
* left the rest for a dedicated future full-reconciliation pass rather
|
|
30
|
-
* than rushing all 68 through at lower confidence:
|
|
25
|
+
* fact rather than a blind import:
|
|
31
26
|
* - `searchbox`: identical to the already-covered `textbox` (ARIA
|
|
32
27
|
* explicitly defines searchbox as textbox's subclass, same supported
|
|
33
28
|
* set).
|
|
@@ -47,6 +42,34 @@
|
|
|
47
42
|
* - `menu`/`menubar`/`toolbar`: activedescendant/orientation — standard
|
|
48
43
|
* composite-widget properties, same family as the already-covered
|
|
49
44
|
* `tablist`.
|
|
45
|
+
* - SUPPORTED_ATTRS_BY_ROLE full-reconciliation pass 2026-07-28: the
|
|
46
|
+
* 2026-07-21 pass deliberately deferred ~61 roles where the reference
|
|
47
|
+
* engine (axe-core) allows `aria-expanded`, treating it as too thin/
|
|
48
|
+
* near-universal to import blindly. Checked against `aria-query`
|
|
49
|
+
* (tracks the published WAI-ARIA 1.2 Recommendation, 6 June 2023 — the
|
|
50
|
+
* latest actually-published version, as opposed to the in-progress 1.3
|
|
51
|
+
* Editor's Draft) instead of axe-core directly, because axe-core's own
|
|
52
|
+
* source comments (`// Spec difference: Aria-expanded removed in 1.2`)
|
|
53
|
+
* show that most of its `aria-expanded` allowances are deliberate
|
|
54
|
+
* ARIA-1.1 legacy/AT-compat carryovers axe-core keeps on purpose, not
|
|
55
|
+
* current-spec facts — importing them wholesale would have re-added
|
|
56
|
+
* exactly the kind of unverified allowance the 07-21 pass was avoiding.
|
|
57
|
+
* `aria-query`'s per-role tables (with superclass inheritance resolved,
|
|
58
|
+
* e.g. `aria-activedescendant` via the abstract `composite` role) gave a
|
|
59
|
+
* spec-grounded diff instead. Net changes from that diff:
|
|
60
|
+
* - `aria-expanded` added to: checkbox, columnheader, gridcell, listbox,
|
|
61
|
+
* menuitemcheckbox, menuitemradio, row, rowheader, switch, tab —
|
|
62
|
+
* confirmed present in current spec for these roles specifically
|
|
63
|
+
* (unlike e.g. `listitem`, `dialog`, `alertdialog`, `heading`, which
|
|
64
|
+
* the spec does NOT list it for — those stay excluded).
|
|
65
|
+
* - `aria-activedescendant` added to: combobox, grid, listbox,
|
|
66
|
+
* radiogroup, row, spinbutton, tablist, treegrid (inherited from the
|
|
67
|
+
* abstract `composite` role for any composite/managed-focus widget).
|
|
68
|
+
* - `aria-readonly`/`aria-required` added to: switch, menuitemcheckbox,
|
|
69
|
+
* menuitemradio. `aria-posinset`/`aria-setsize` added to: tab, radio,
|
|
70
|
+
* menuitemcheckbox, menuitemradio. `aria-level` added to: tablist.
|
|
71
|
+
* - `tree`'s `aria-readonly` removed: not in aria-query's resolved
|
|
72
|
+
* props for `tree` (was an unverified carryover, not spec-backed).
|
|
50
73
|
* - Not gated on isAccTreeEligible: this is a static markup property.
|
|
51
74
|
*/
|
|
52
75
|
|
|
@@ -101,39 +124,39 @@ function runInPage(ctx) {
|
|
|
101
124
|
// role/attribute pairings from the WAI-ARIA role definitions are listed.
|
|
102
125
|
const SUPPORTED_ATTRS_BY_ROLE = {
|
|
103
126
|
alertdialog: ['aria-modal'],
|
|
104
|
-
checkbox: ['aria-checked', 'aria-readonly', 'aria-required'],
|
|
105
|
-
columnheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected'],
|
|
106
|
-
combobox: ['aria-expanded', 'aria-autocomplete', 'aria-readonly', 'aria-required'],
|
|
127
|
+
checkbox: ['aria-checked', 'aria-readonly', 'aria-required', 'aria-expanded'],
|
|
128
|
+
columnheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected', 'aria-expanded'],
|
|
129
|
+
combobox: ['aria-expanded', 'aria-autocomplete', 'aria-readonly', 'aria-required', 'aria-activedescendant'],
|
|
107
130
|
dialog: ['aria-modal'],
|
|
108
|
-
grid: ['aria-multiselectable', 'aria-readonly', 'aria-colcount', 'aria-rowcount'],
|
|
109
|
-
gridcell: ['aria-selected', 'aria-readonly', 'aria-required', 'aria-colindex', 'aria-colspan', 'aria-rowindex', 'aria-rowspan'],
|
|
131
|
+
grid: ['aria-multiselectable', 'aria-readonly', 'aria-colcount', 'aria-rowcount', 'aria-activedescendant'],
|
|
132
|
+
gridcell: ['aria-selected', 'aria-readonly', 'aria-required', 'aria-colindex', 'aria-colspan', 'aria-rowindex', 'aria-rowspan', 'aria-expanded'],
|
|
110
133
|
heading: ['aria-level'],
|
|
111
|
-
listbox: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation'],
|
|
134
|
+
listbox: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation', 'aria-expanded', 'aria-activedescendant'],
|
|
112
135
|
listitem: ['aria-level', 'aria-posinset', 'aria-setsize'],
|
|
113
136
|
menu: ['aria-activedescendant', 'aria-orientation'],
|
|
114
137
|
menubar: ['aria-activedescendant', 'aria-orientation'],
|
|
115
|
-
menuitemcheckbox: ['aria-checked'],
|
|
116
|
-
menuitemradio: ['aria-checked'],
|
|
138
|
+
menuitemcheckbox: ['aria-checked', 'aria-expanded', 'aria-readonly', 'aria-required', 'aria-posinset', 'aria-setsize'],
|
|
139
|
+
menuitemradio: ['aria-checked', 'aria-expanded', 'aria-readonly', 'aria-required', 'aria-posinset', 'aria-setsize'],
|
|
117
140
|
meter: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext'],
|
|
118
141
|
option: ['aria-selected', 'aria-checked', 'aria-posinset', 'aria-setsize'],
|
|
119
142
|
progressbar: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext'],
|
|
120
|
-
radio: ['aria-checked'],
|
|
121
|
-
radiogroup: ['aria-readonly', 'aria-required', 'aria-orientation'],
|
|
122
|
-
row: ['aria-selected', 'aria-level', 'aria-posinset', 'aria-setsize', 'aria-colindex', 'aria-rowindex'],
|
|
123
|
-
rowheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected'],
|
|
143
|
+
radio: ['aria-checked', 'aria-posinset', 'aria-setsize'],
|
|
144
|
+
radiogroup: ['aria-readonly', 'aria-required', 'aria-orientation', 'aria-activedescendant'],
|
|
145
|
+
row: ['aria-selected', 'aria-level', 'aria-posinset', 'aria-setsize', 'aria-colindex', 'aria-rowindex', 'aria-expanded', 'aria-activedescendant'],
|
|
146
|
+
rowheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected', 'aria-expanded'],
|
|
124
147
|
scrollbar: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-orientation', 'aria-controls'],
|
|
125
148
|
searchbox: ['aria-activedescendant', 'aria-autocomplete', 'aria-multiline', 'aria-placeholder', 'aria-readonly', 'aria-required'],
|
|
126
149
|
separator: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-orientation'],
|
|
127
150
|
slider: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-orientation', 'aria-readonly'],
|
|
128
|
-
spinbutton: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-readonly', 'aria-required'],
|
|
129
|
-
switch: ['aria-checked'],
|
|
130
|
-
tab: ['aria-selected'],
|
|
151
|
+
spinbutton: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-readonly', 'aria-required', 'aria-activedescendant'],
|
|
152
|
+
switch: ['aria-checked', 'aria-expanded', 'aria-readonly', 'aria-required'],
|
|
153
|
+
tab: ['aria-selected', 'aria-expanded', 'aria-posinset', 'aria-setsize'],
|
|
131
154
|
table: ['aria-colcount', 'aria-rowcount'],
|
|
132
|
-
tablist: ['aria-multiselectable', 'aria-orientation'],
|
|
155
|
+
tablist: ['aria-multiselectable', 'aria-orientation', 'aria-level', 'aria-activedescendant'],
|
|
133
156
|
textbox: ['aria-activedescendant', 'aria-autocomplete', 'aria-multiline', 'aria-placeholder', 'aria-readonly', 'aria-required'],
|
|
134
157
|
toolbar: ['aria-activedescendant', 'aria-orientation'],
|
|
135
|
-
tree: ['aria-multiselectable', 'aria-
|
|
136
|
-
treegrid: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation', 'aria-colcount', 'aria-rowcount'],
|
|
158
|
+
tree: ['aria-multiselectable', 'aria-required', 'aria-orientation', 'aria-activedescendant'],
|
|
159
|
+
treegrid: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation', 'aria-colcount', 'aria-rowcount', 'aria-activedescendant'],
|
|
137
160
|
treeitem: ['aria-checked', 'aria-selected', 'aria-expanded', 'aria-level', 'aria-posinset', 'aria-setsize']
|
|
138
161
|
};
|
|
139
162
|
|