praxis-kit 6.2.3 → 6.5.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.
- package/dist/_shared/diagnostics.d.ts +4 -0
- package/dist/_shared/diagnostics.js +4 -0
- package/dist/{chunk-H3D2JA3J.js → chunk-AM5J6PY3.js} +486 -310
- package/dist/contract/index.d.ts +1 -0
- package/dist/lit/index.d.ts +1 -0
- package/dist/lit/index.js +486 -310
- package/dist/preact/index.d.ts +1 -0
- package/dist/preact/index.js +486 -310
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +1 -1
- package/dist/react/legacy.d.ts +2 -2
- package/dist/react/legacy.js +1 -1
- package/dist/{react-options-DQTX4YS_.d.ts → react-options-DoFNqNdY.d.ts} +1 -0
- package/dist/solid/index.d.ts +1 -0
- package/dist/solid/index.js +486 -310
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +486 -310
- package/dist/vite-plugin/index.d.ts +4 -0
- package/dist/vue/index.d.ts +1 -0
- package/dist/vue/index.js +486 -310
- package/dist/web/index.d.ts +1 -0
- package/dist/web/index.js +486 -310
- package/package.json +5 -5
package/dist/preact/index.js
CHANGED
|
@@ -1005,7 +1005,11 @@ var ATTRIBUTE_IGNORED_CODES = {
|
|
|
1005
1005
|
max: DiagnosticCode3.HtmlInputMaxIgnoredForType,
|
|
1006
1006
|
step: DiagnosticCode3.HtmlInputStepIgnoredForType,
|
|
1007
1007
|
accept: DiagnosticCode3.HtmlInputAcceptIgnoredForType,
|
|
1008
|
-
capture: DiagnosticCode3.HtmlInputCaptureIgnoredForType
|
|
1008
|
+
capture: DiagnosticCode3.HtmlInputCaptureIgnoredForType,
|
|
1009
|
+
size: DiagnosticCode3.HtmlInputSizeIgnoredForType,
|
|
1010
|
+
alt: DiagnosticCode3.HtmlInputAltIgnoredForType,
|
|
1011
|
+
height: DiagnosticCode3.HtmlInputHeightIgnoredForType,
|
|
1012
|
+
width: DiagnosticCode3.HtmlInputWidthIgnoredForType
|
|
1009
1013
|
};
|
|
1010
1014
|
var HtmlDiagnostics = {
|
|
1011
1015
|
emptyRole(tag) {
|
|
@@ -1239,8 +1243,132 @@ var InvariantBase = class {
|
|
|
1239
1243
|
}
|
|
1240
1244
|
};
|
|
1241
1245
|
|
|
1242
|
-
// ../../lib/contract/src/aria/
|
|
1246
|
+
// ../../lib/contract/src/aria/spec/roles/required-properties.ts
|
|
1247
|
+
var REQUIRED_ARIA_PROPERTIES = {
|
|
1248
|
+
combobox: ["aria-expanded"],
|
|
1249
|
+
option: ["aria-selected"],
|
|
1250
|
+
slider: ["aria-valuenow"],
|
|
1251
|
+
scrollbar: ["aria-controls", "aria-valuenow"],
|
|
1252
|
+
spinbutton: ["aria-valuenow"]
|
|
1253
|
+
};
|
|
1254
|
+
|
|
1255
|
+
// ../../lib/contract/src/aria/spec/roles/name-required.ts
|
|
1256
|
+
var NAME_REQUIRED_ROLES = /* @__PURE__ */ new Set(["img"]);
|
|
1257
|
+
|
|
1258
|
+
// ../../lib/contract/src/aria/spec/validators/required-properties-validator.ts
|
|
1243
1259
|
var NO_VIOLATIONS = [{ valid: true }];
|
|
1260
|
+
function requiredAttributeByRole(roles, attribute) {
|
|
1261
|
+
return Object.fromEntries([...roles].map((role) => [role, [attribute]]));
|
|
1262
|
+
}
|
|
1263
|
+
function checkRequiredAttributes(requirement, { props, effectiveRole }) {
|
|
1264
|
+
if (!effectiveRole) return NO_VIOLATIONS;
|
|
1265
|
+
const requiredAttributes = requirement.attributesByRole[effectiveRole];
|
|
1266
|
+
if (!requiredAttributes) return NO_VIOLATIONS;
|
|
1267
|
+
const results = [];
|
|
1268
|
+
for (const attribute of requiredAttributes) {
|
|
1269
|
+
if (attribute in props) continue;
|
|
1270
|
+
results.push({
|
|
1271
|
+
valid: false,
|
|
1272
|
+
fixable: false,
|
|
1273
|
+
severity: "warning",
|
|
1274
|
+
attribute,
|
|
1275
|
+
diagnostic: requirement.diagnosticFor(attribute, effectiveRole)
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
return results;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// ../../lib/contract/src/aria/spec/roles/live-region.ts
|
|
1282
|
+
var LIVE_REGION_ROLES = /* @__PURE__ */ new Map([
|
|
1283
|
+
["alert", "assertive"],
|
|
1284
|
+
["status", "polite"],
|
|
1285
|
+
["log", "polite"],
|
|
1286
|
+
["timer", "off"]
|
|
1287
|
+
]);
|
|
1288
|
+
var ATOMIC_REQUIREMENTS = requiredAttributeByRole(LIVE_REGION_ROLES.keys(), "aria-atomic");
|
|
1289
|
+
|
|
1290
|
+
// ../../lib/contract/src/aria/spec/attributes/aria-value-types.ts
|
|
1291
|
+
var ARIA_VALUE_TYPES = /* @__PURE__ */ new Map([
|
|
1292
|
+
// Boolean (true | false)
|
|
1293
|
+
["aria-atomic", { kind: "boolean" }],
|
|
1294
|
+
["aria-busy", { kind: "boolean" }],
|
|
1295
|
+
["aria-disabled", { kind: "boolean" }],
|
|
1296
|
+
["aria-expanded", { kind: "boolean" }],
|
|
1297
|
+
["aria-hidden", { kind: "boolean" }],
|
|
1298
|
+
["aria-modal", { kind: "boolean" }],
|
|
1299
|
+
["aria-multiline", { kind: "boolean" }],
|
|
1300
|
+
["aria-multiselectable", { kind: "boolean" }],
|
|
1301
|
+
["aria-readonly", { kind: "boolean" }],
|
|
1302
|
+
["aria-required", { kind: "boolean" }],
|
|
1303
|
+
["aria-selected", { kind: "boolean" }],
|
|
1304
|
+
// Tristate (true | false | mixed)
|
|
1305
|
+
["aria-checked", { kind: "tristate" }],
|
|
1306
|
+
["aria-pressed", { kind: "tristate" }],
|
|
1307
|
+
// Numeric (any finite number)
|
|
1308
|
+
["aria-valuenow", { kind: "number" }],
|
|
1309
|
+
["aria-valuemin", { kind: "number" }],
|
|
1310
|
+
["aria-valuemax", { kind: "number" }],
|
|
1311
|
+
// Integer with optional range
|
|
1312
|
+
["aria-level", { kind: "integer", min: 1, max: 6 }],
|
|
1313
|
+
["aria-posinset", { kind: "integer", min: 1 }],
|
|
1314
|
+
["aria-setsize", { kind: "integer", min: -1 }],
|
|
1315
|
+
["aria-rowcount", { kind: "integer", min: -1 }],
|
|
1316
|
+
["aria-colcount", { kind: "integer", min: -1 }],
|
|
1317
|
+
["aria-rowindex", { kind: "integer", min: 1 }],
|
|
1318
|
+
["aria-colindex", { kind: "integer", min: 1 }],
|
|
1319
|
+
["aria-rowspan", { kind: "integer", min: 0 }],
|
|
1320
|
+
["aria-colspan", { kind: "integer", min: 0 }],
|
|
1321
|
+
// Enum (specific allowed tokens)
|
|
1322
|
+
["aria-autocomplete", { kind: "enum", values: /* @__PURE__ */ new Set(["inline", "list", "both", "none"]) }],
|
|
1323
|
+
[
|
|
1324
|
+
"aria-current",
|
|
1325
|
+
{
|
|
1326
|
+
kind: "enum",
|
|
1327
|
+
values: /* @__PURE__ */ new Set(["page", "step", "location", "date", "time", "true", "false"])
|
|
1328
|
+
}
|
|
1329
|
+
],
|
|
1330
|
+
[
|
|
1331
|
+
"aria-haspopup",
|
|
1332
|
+
{
|
|
1333
|
+
kind: "enum",
|
|
1334
|
+
values: /* @__PURE__ */ new Set(["false", "true", "menu", "listbox", "tree", "grid", "dialog"])
|
|
1335
|
+
}
|
|
1336
|
+
],
|
|
1337
|
+
["aria-invalid", { kind: "enum", values: /* @__PURE__ */ new Set(["grammar", "false", "spelling", "true"]) }],
|
|
1338
|
+
["aria-live", { kind: "enum", values: /* @__PURE__ */ new Set(["assertive", "off", "polite"]) }],
|
|
1339
|
+
["aria-orientation", { kind: "enum", values: /* @__PURE__ */ new Set(["horizontal", "vertical", "undefined"]) }],
|
|
1340
|
+
["aria-sort", { kind: "enum", values: /* @__PURE__ */ new Set(["ascending", "descending", "none", "other"]) }]
|
|
1341
|
+
]);
|
|
1342
|
+
|
|
1343
|
+
// ../../lib/contract/src/aria/spec/attributes/aria-relevant-tokens.ts
|
|
1344
|
+
var VALID_RELEVANT_TOKENS = /* @__PURE__ */ new Set([
|
|
1345
|
+
"additions",
|
|
1346
|
+
"removals",
|
|
1347
|
+
"text",
|
|
1348
|
+
"all"
|
|
1349
|
+
]);
|
|
1350
|
+
|
|
1351
|
+
// ../../lib/contract/src/aria/spec/elements/heading-implicit-levels.ts
|
|
1352
|
+
var HEADING_IMPLICIT_LEVELS = /* @__PURE__ */ new Map([
|
|
1353
|
+
["h1", 1],
|
|
1354
|
+
["h2", 2],
|
|
1355
|
+
["h3", 3],
|
|
1356
|
+
["h4", 4],
|
|
1357
|
+
["h5", 5],
|
|
1358
|
+
["h6", 6]
|
|
1359
|
+
]);
|
|
1360
|
+
|
|
1361
|
+
// ../../lib/contract/src/aria/spec/elements/interactive-tags.ts
|
|
1362
|
+
var INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
|
|
1363
|
+
"a",
|
|
1364
|
+
"button",
|
|
1365
|
+
"input",
|
|
1366
|
+
"select",
|
|
1367
|
+
"textarea"
|
|
1368
|
+
]);
|
|
1369
|
+
|
|
1370
|
+
// ../../lib/contract/src/aria/polymorphic-validator.ts
|
|
1371
|
+
var NO_VIOLATIONS2 = [{ valid: true }];
|
|
1244
1372
|
function isIntrinsicTag(tag) {
|
|
1245
1373
|
return isString(tag);
|
|
1246
1374
|
}
|
|
@@ -1302,6 +1430,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1302
1430
|
const violations = [];
|
|
1303
1431
|
const fixes = [];
|
|
1304
1432
|
iterate.forEach(rules, (rule) => {
|
|
1433
|
+
if (isNonNull(rule.tags) && !rule.tags.includes(context.tag)) return;
|
|
1305
1434
|
iterate.forEach(rule(context), (result) => {
|
|
1306
1435
|
if (result.valid) return;
|
|
1307
1436
|
const {
|
|
@@ -1327,7 +1456,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1327
1456
|
return { violations, fixes };
|
|
1328
1457
|
}
|
|
1329
1458
|
static #getRules(context) {
|
|
1330
|
-
if (_AriaPolicyEngine.#hasRole(context.props) || isNonNull(context.effectiveRole) &&
|
|
1459
|
+
if (_AriaPolicyEngine.#hasRole(context.props) || isNonNull(context.effectiveRole) && LIVE_REGION_ROLES.has(context.effectiveRole)) {
|
|
1331
1460
|
return _AriaPolicyEngine.#pipeline;
|
|
1332
1461
|
}
|
|
1333
1462
|
return _AriaPolicyEngine.#implicitOnlyRules;
|
|
@@ -1529,7 +1658,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1529
1658
|
implicitRole
|
|
1530
1659
|
}) {
|
|
1531
1660
|
const role = props.role;
|
|
1532
|
-
if (!implicitRole || !role || role === implicitRole) return
|
|
1661
|
+
if (!implicitRole || !role || role === implicitRole) return NO_VIOLATIONS2;
|
|
1533
1662
|
if (isStrongImplicitRole(tag) && role === "region") {
|
|
1534
1663
|
const diagnostic = HtmlDiagnostics.implicitRoleOverride(tag, implicitRole, role);
|
|
1535
1664
|
return [
|
|
@@ -1542,11 +1671,11 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1542
1671
|
}
|
|
1543
1672
|
];
|
|
1544
1673
|
}
|
|
1545
|
-
return
|
|
1674
|
+
return NO_VIOLATIONS2;
|
|
1546
1675
|
}
|
|
1547
1676
|
static #checkRedundantRole({ tag, props, implicitRole }) {
|
|
1548
1677
|
const role = props.role;
|
|
1549
|
-
if (!implicitRole || !role || role !== implicitRole) return
|
|
1678
|
+
if (!implicitRole || !role || role !== implicitRole) return NO_VIOLATIONS2;
|
|
1550
1679
|
const diagnostic = HtmlDiagnostics.implicitRoleRedundant(tag, implicitRole);
|
|
1551
1680
|
return [
|
|
1552
1681
|
{
|
|
@@ -1560,8 +1689,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1560
1689
|
}
|
|
1561
1690
|
static #checkStandaloneRegion({ tag, props, implicitRole }) {
|
|
1562
1691
|
const role = props.role;
|
|
1563
|
-
if (role !== "region") return
|
|
1564
|
-
if (!isStandaloneTag(tag)) return
|
|
1692
|
+
if (role !== "region") return NO_VIOLATIONS2;
|
|
1693
|
+
if (!isStandaloneTag(tag)) return NO_VIOLATIONS2;
|
|
1565
1694
|
const diagnostic = HtmlDiagnostics.standaloneRegionOverride(tag, implicitRole ?? tag);
|
|
1566
1695
|
return [
|
|
1567
1696
|
{
|
|
@@ -1578,7 +1707,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1578
1707
|
props,
|
|
1579
1708
|
effectiveRole
|
|
1580
1709
|
}) {
|
|
1581
|
-
if (effectiveRole === "none" || effectiveRole === "presentation") return
|
|
1710
|
+
if (effectiveRole === "none" || effectiveRole === "presentation") return NO_VIOLATIONS2;
|
|
1582
1711
|
const results = [];
|
|
1583
1712
|
iterate.forEachEntry(props, (key) => {
|
|
1584
1713
|
if (!key.startsWith("aria-")) return;
|
|
@@ -1596,62 +1725,6 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1596
1725
|
return results;
|
|
1597
1726
|
}
|
|
1598
1727
|
// ─── ARIA attribute value validation ──────────────────────────────────────
|
|
1599
|
-
// Accepted value shapes for typed ARIA attributes.
|
|
1600
|
-
// Attributes not in this map are unconstrained (arbitrary string values permitted).
|
|
1601
|
-
static #ARIA_VALUE_TYPES = /* @__PURE__ */ new Map([
|
|
1602
|
-
// Boolean (true | false)
|
|
1603
|
-
["aria-atomic", { kind: "boolean" }],
|
|
1604
|
-
["aria-busy", { kind: "boolean" }],
|
|
1605
|
-
["aria-disabled", { kind: "boolean" }],
|
|
1606
|
-
["aria-expanded", { kind: "boolean" }],
|
|
1607
|
-
["aria-hidden", { kind: "boolean" }],
|
|
1608
|
-
["aria-modal", { kind: "boolean" }],
|
|
1609
|
-
["aria-multiline", { kind: "boolean" }],
|
|
1610
|
-
["aria-multiselectable", { kind: "boolean" }],
|
|
1611
|
-
["aria-readonly", { kind: "boolean" }],
|
|
1612
|
-
["aria-required", { kind: "boolean" }],
|
|
1613
|
-
["aria-selected", { kind: "boolean" }],
|
|
1614
|
-
// Tristate (true | false | mixed)
|
|
1615
|
-
["aria-checked", { kind: "tristate" }],
|
|
1616
|
-
["aria-pressed", { kind: "tristate" }],
|
|
1617
|
-
// Numeric (any finite number)
|
|
1618
|
-
["aria-valuenow", { kind: "number" }],
|
|
1619
|
-
["aria-valuemin", { kind: "number" }],
|
|
1620
|
-
["aria-valuemax", { kind: "number" }],
|
|
1621
|
-
// Integer with optional range
|
|
1622
|
-
["aria-level", { kind: "integer", min: 1, max: 6 }],
|
|
1623
|
-
["aria-posinset", { kind: "integer", min: 1 }],
|
|
1624
|
-
["aria-setsize", { kind: "integer", min: -1 }],
|
|
1625
|
-
["aria-rowcount", { kind: "integer", min: -1 }],
|
|
1626
|
-
["aria-colcount", { kind: "integer", min: -1 }],
|
|
1627
|
-
["aria-rowindex", { kind: "integer", min: 1 }],
|
|
1628
|
-
["aria-colindex", { kind: "integer", min: 1 }],
|
|
1629
|
-
["aria-rowspan", { kind: "integer", min: 0 }],
|
|
1630
|
-
["aria-colspan", { kind: "integer", min: 0 }],
|
|
1631
|
-
// Enum (specific allowed tokens)
|
|
1632
|
-
["aria-autocomplete", { kind: "enum", values: /* @__PURE__ */ new Set(["inline", "list", "both", "none"]) }],
|
|
1633
|
-
[
|
|
1634
|
-
"aria-current",
|
|
1635
|
-
{
|
|
1636
|
-
kind: "enum",
|
|
1637
|
-
values: /* @__PURE__ */ new Set(["page", "step", "location", "date", "time", "true", "false"])
|
|
1638
|
-
}
|
|
1639
|
-
],
|
|
1640
|
-
[
|
|
1641
|
-
"aria-haspopup",
|
|
1642
|
-
{
|
|
1643
|
-
kind: "enum",
|
|
1644
|
-
values: /* @__PURE__ */ new Set(["false", "true", "menu", "listbox", "tree", "grid", "dialog"])
|
|
1645
|
-
}
|
|
1646
|
-
],
|
|
1647
|
-
["aria-invalid", { kind: "enum", values: /* @__PURE__ */ new Set(["grammar", "false", "spelling", "true"]) }],
|
|
1648
|
-
["aria-live", { kind: "enum", values: /* @__PURE__ */ new Set(["assertive", "off", "polite"]) }],
|
|
1649
|
-
[
|
|
1650
|
-
"aria-orientation",
|
|
1651
|
-
{ kind: "enum", values: /* @__PURE__ */ new Set(["horizontal", "vertical", "undefined"]) }
|
|
1652
|
-
],
|
|
1653
|
-
["aria-sort", { kind: "enum", values: /* @__PURE__ */ new Set(["ascending", "descending", "none", "other"]) }]
|
|
1654
|
-
]);
|
|
1655
1728
|
static #isValidAriaValue(value, type) {
|
|
1656
1729
|
switch (type.kind) {
|
|
1657
1730
|
case "boolean":
|
|
@@ -1696,11 +1769,11 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1696
1769
|
}
|
|
1697
1770
|
}
|
|
1698
1771
|
static #checkAriaAttributeValues({ props, effectiveRole }) {
|
|
1699
|
-
if (effectiveRole === "none" || effectiveRole === "presentation") return
|
|
1772
|
+
if (effectiveRole === "none" || effectiveRole === "presentation") return NO_VIOLATIONS2;
|
|
1700
1773
|
const results = [];
|
|
1701
1774
|
iterate.forEachEntry(props, (key, value) => {
|
|
1702
1775
|
if (!key.startsWith("aria-")) return;
|
|
1703
|
-
const type =
|
|
1776
|
+
const type = ARIA_VALUE_TYPES.get(key);
|
|
1704
1777
|
if (!isNonNull(type)) return;
|
|
1705
1778
|
if (_AriaPolicyEngine.#isValidAriaValue(value, type)) return;
|
|
1706
1779
|
results.push({
|
|
@@ -1719,26 +1792,18 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1719
1792
|
return results;
|
|
1720
1793
|
}
|
|
1721
1794
|
// ─── Heading implicit level ────────────────────────────────────────────────
|
|
1722
|
-
static #HEADING_IMPLICIT_LEVELS = /* @__PURE__ */ new Map([
|
|
1723
|
-
["h1", 1],
|
|
1724
|
-
["h2", 2],
|
|
1725
|
-
["h3", 3],
|
|
1726
|
-
["h4", 4],
|
|
1727
|
-
["h5", 5],
|
|
1728
|
-
["h6", 6]
|
|
1729
|
-
]);
|
|
1730
1795
|
static #checkRedundantAriaLevel({
|
|
1731
1796
|
tag,
|
|
1732
1797
|
props,
|
|
1733
1798
|
effectiveRole
|
|
1734
1799
|
}) {
|
|
1735
|
-
if (effectiveRole === "none" || effectiveRole === "presentation") return
|
|
1736
|
-
const implicitLevel =
|
|
1737
|
-
if (!isNonNull(implicitLevel)) return
|
|
1800
|
+
if (effectiveRole === "none" || effectiveRole === "presentation") return NO_VIOLATIONS2;
|
|
1801
|
+
const implicitLevel = HEADING_IMPLICIT_LEVELS.get(tag);
|
|
1802
|
+
if (!isNonNull(implicitLevel)) return NO_VIOLATIONS2;
|
|
1738
1803
|
const raw = props["aria-level"];
|
|
1739
|
-
if (!isNonNull(raw)) return
|
|
1804
|
+
if (!isNonNull(raw)) return NO_VIOLATIONS2;
|
|
1740
1805
|
const n = typeof raw === "number" ? raw : typeof raw === "string" ? parseInt(raw, 10) : NaN;
|
|
1741
|
-
if (!Number.isFinite(n) || n !== implicitLevel) return
|
|
1806
|
+
if (!Number.isFinite(n) || n !== implicitLevel) return NO_VIOLATIONS2;
|
|
1742
1807
|
return [
|
|
1743
1808
|
{
|
|
1744
1809
|
valid: false,
|
|
@@ -1751,20 +1816,14 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1751
1816
|
];
|
|
1752
1817
|
}
|
|
1753
1818
|
// ─── Name-required roles ───────────────────────────────────────────────────
|
|
1754
|
-
// Roles that always require an accessible name per WAI-ARIA APG.
|
|
1755
|
-
// Dialog and landmark names are enforced via contracts (ariaContract) rather than
|
|
1756
|
-
// the built-in pipeline so consumers can opt in; img is built in because role=img
|
|
1757
|
-
// on any element (including bare <img>) is definitionally useless without a name.
|
|
1758
|
-
static #NAME_REQUIRED_ROLES = /* @__PURE__ */ new Set(["img"]);
|
|
1759
1819
|
static #checkNameRequiredRoles({
|
|
1760
1820
|
tag,
|
|
1761
1821
|
props,
|
|
1762
1822
|
effectiveRole
|
|
1763
1823
|
}) {
|
|
1764
|
-
if (!effectiveRole || !
|
|
1765
|
-
|
|
1766
|
-
if ("
|
|
1767
|
-
if (tag === "img" && typeof props.alt === "string" && props.alt.length > 0) return NO_VIOLATIONS;
|
|
1824
|
+
if (!effectiveRole || !NAME_REQUIRED_ROLES.has(effectiveRole)) return NO_VIOLATIONS2;
|
|
1825
|
+
if ("aria-label" in props || "aria-labelledby" in props) return NO_VIOLATIONS2;
|
|
1826
|
+
if (tag === "img" && typeof props.alt === "string" && props.alt.length > 0) return NO_VIOLATIONS2;
|
|
1768
1827
|
return [
|
|
1769
1828
|
{
|
|
1770
1829
|
valid: false,
|
|
@@ -1774,51 +1833,21 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1774
1833
|
}
|
|
1775
1834
|
];
|
|
1776
1835
|
}
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
["scrollbar", ["aria-controls", "aria-valuenow"]],
|
|
1784
|
-
["spinbutton", ["aria-valuenow"]]
|
|
1785
|
-
]);
|
|
1786
|
-
static #checkRequiredAriaProperties({
|
|
1787
|
-
props,
|
|
1788
|
-
effectiveRole
|
|
1789
|
-
}) {
|
|
1790
|
-
if (!effectiveRole) return NO_VIOLATIONS;
|
|
1791
|
-
const required = _AriaPolicyEngine.#REQUIRED_PROPERTIES.get(effectiveRole);
|
|
1792
|
-
if (!isNonNull(required)) return NO_VIOLATIONS;
|
|
1793
|
-
const results = [];
|
|
1794
|
-
iterate.forEach(required, (attr) => {
|
|
1795
|
-
if (attr in props) return;
|
|
1796
|
-
results.push({
|
|
1797
|
-
valid: false,
|
|
1798
|
-
fixable: false,
|
|
1799
|
-
severity: "warning",
|
|
1800
|
-
attribute: attr,
|
|
1801
|
-
diagnostic: AriaDiagnostics.requiredProperty(attr, effectiveRole)
|
|
1802
|
-
});
|
|
1803
|
-
});
|
|
1804
|
-
return results;
|
|
1836
|
+
static #requiredAriaPropertiesRule = {
|
|
1837
|
+
attributesByRole: REQUIRED_ARIA_PROPERTIES,
|
|
1838
|
+
diagnosticFor: (attribute, role) => AriaDiagnostics.requiredProperty(attribute, role)
|
|
1839
|
+
};
|
|
1840
|
+
static #checkRequiredAriaProperties(context) {
|
|
1841
|
+
return checkRequiredAttributes(_AriaPolicyEngine.#requiredAriaPropertiesRule, context);
|
|
1805
1842
|
}
|
|
1806
|
-
// Natively interactive HTML elements — always keyboard-reachable unless explicitly disabled.
|
|
1807
|
-
static #INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
|
|
1808
|
-
"a",
|
|
1809
|
-
"button",
|
|
1810
|
-
"input",
|
|
1811
|
-
"select",
|
|
1812
|
-
"textarea"
|
|
1813
|
-
]);
|
|
1814
1843
|
// WAI-ARIA 1.2 §6.6: aria-hidden="true" must not be placed on focusable elements.
|
|
1815
1844
|
static #checkAriaHiddenOnFocusable({ tag, props }) {
|
|
1816
|
-
if (props["aria-hidden"] !== "true" && props["aria-hidden"] !== true) return
|
|
1817
|
-
const isInteractive =
|
|
1845
|
+
if (props["aria-hidden"] !== "true" && props["aria-hidden"] !== true) return NO_VIOLATIONS2;
|
|
1846
|
+
const isInteractive = INTERACTIVE_TAGS.has(tag);
|
|
1818
1847
|
if (!isInteractive) {
|
|
1819
1848
|
const tabindex = props.tabindex;
|
|
1820
1849
|
const n = typeof tabindex === "number" ? tabindex : typeof tabindex === "string" ? parseInt(tabindex, 10) : NaN;
|
|
1821
|
-
if (!Number.isFinite(n) || n < 0) return
|
|
1850
|
+
if (!Number.isFinite(n) || n < 0) return NO_VIOLATIONS2;
|
|
1822
1851
|
}
|
|
1823
1852
|
return [
|
|
1824
1853
|
{
|
|
@@ -1837,7 +1866,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1837
1866
|
props,
|
|
1838
1867
|
effectiveRole
|
|
1839
1868
|
}) {
|
|
1840
|
-
if (effectiveRole !== "none" && effectiveRole !== "presentation") return
|
|
1869
|
+
if (effectiveRole !== "none" && effectiveRole !== "presentation") return NO_VIOLATIONS2;
|
|
1841
1870
|
const results = [];
|
|
1842
1871
|
iterate.forEachEntry(props, (key) => {
|
|
1843
1872
|
if (!key.startsWith("aria-")) return;
|
|
@@ -1853,18 +1882,11 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1853
1882
|
});
|
|
1854
1883
|
return results;
|
|
1855
1884
|
}
|
|
1856
|
-
// WAI-ARIA live region roles and their implied aria-live politeness values.
|
|
1857
|
-
static #LIVE_REGION_ROLES = /* @__PURE__ */ new Map([
|
|
1858
|
-
["alert", "assertive"],
|
|
1859
|
-
["status", "polite"],
|
|
1860
|
-
["log", "polite"],
|
|
1861
|
-
["timer", "off"]
|
|
1862
|
-
]);
|
|
1863
1885
|
static #checkMissingLiveRegion({ effectiveRole, props }) {
|
|
1864
|
-
if (!effectiveRole) return
|
|
1865
|
-
const impliedLive =
|
|
1866
|
-
if (!impliedLive) return
|
|
1867
|
-
if ("aria-live" in props) return
|
|
1886
|
+
if (!effectiveRole) return NO_VIOLATIONS2;
|
|
1887
|
+
const impliedLive = LIVE_REGION_ROLES.get(effectiveRole);
|
|
1888
|
+
if (!impliedLive) return NO_VIOLATIONS2;
|
|
1889
|
+
if ("aria-live" in props) return NO_VIOLATIONS2;
|
|
1868
1890
|
const injectLive = {
|
|
1869
1891
|
kind: `injectLive:${effectiveRole}`,
|
|
1870
1892
|
apply: (ctx) => ({
|
|
@@ -1883,20 +1905,13 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1883
1905
|
}
|
|
1884
1906
|
];
|
|
1885
1907
|
}
|
|
1886
|
-
static #
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
valid: false,
|
|
1893
|
-
fixable: false,
|
|
1894
|
-
severity: "warning",
|
|
1895
|
-
diagnostic: AriaDiagnostics.missingAtomic(effectiveRole)
|
|
1896
|
-
}
|
|
1897
|
-
];
|
|
1908
|
+
static #missingAtomicRule = {
|
|
1909
|
+
attributesByRole: ATOMIC_REQUIREMENTS,
|
|
1910
|
+
diagnosticFor: (_attribute, role) => AriaDiagnostics.missingAtomic(role)
|
|
1911
|
+
};
|
|
1912
|
+
static #checkMissingAtomic(context) {
|
|
1913
|
+
return checkRequiredAttributes(_AriaPolicyEngine.#missingAtomicRule, context);
|
|
1898
1914
|
}
|
|
1899
|
-
static #VALID_RELEVANT_TOKENS = /* @__PURE__ */ new Set(["additions", "removals", "text", "all"]);
|
|
1900
1915
|
// Custom fix rules passed via `options.rules` must be pure functions of (tag, props) — the cache
|
|
1901
1916
|
// replays stored fixes against new prop objects, so fixes that close over external state will
|
|
1902
1917
|
// produce inconsistent results on cache hits.
|
|
@@ -1910,10 +1925,10 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1910
1925
|
};
|
|
1911
1926
|
static #checkInvalidAriaRelevant({ props }) {
|
|
1912
1927
|
const relevant = props["aria-relevant"];
|
|
1913
|
-
if (relevant === void 0) return
|
|
1914
|
-
if (typeof relevant !== "string") return
|
|
1928
|
+
if (relevant === void 0) return NO_VIOLATIONS2;
|
|
1929
|
+
if (typeof relevant !== "string") return NO_VIOLATIONS2;
|
|
1915
1930
|
const tokens = relevant.trim().split(/\s+/);
|
|
1916
|
-
const invalid = tokens.filter((t) => !
|
|
1931
|
+
const invalid = tokens.filter((t) => !VALID_RELEVANT_TOKENS.has(t));
|
|
1917
1932
|
if (invalid.length > 0) {
|
|
1918
1933
|
return [
|
|
1919
1934
|
{
|
|
@@ -1938,7 +1953,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1938
1953
|
}
|
|
1939
1954
|
];
|
|
1940
1955
|
}
|
|
1941
|
-
return
|
|
1956
|
+
return NO_VIOLATIONS2;
|
|
1942
1957
|
}
|
|
1943
1958
|
};
|
|
1944
1959
|
|
|
@@ -2258,7 +2273,59 @@ var readonlyProps = ({
|
|
|
2258
2273
|
// ../core/src/html/evaluators.ts
|
|
2259
2274
|
import { warnDiagnostics as warnDiagnostics2 } from "../_shared/diagnostics.js";
|
|
2260
2275
|
|
|
2261
|
-
// ../core/src/html/input
|
|
2276
|
+
// ../core/src/html/spec/vocabulary/input.ts
|
|
2277
|
+
var TEXT_INPUT_TYPES = ["text", "search", "url", "tel", "email", "password"];
|
|
2278
|
+
var NUMERIC_INPUT_TYPES = [
|
|
2279
|
+
"number",
|
|
2280
|
+
"range",
|
|
2281
|
+
"date",
|
|
2282
|
+
"month",
|
|
2283
|
+
"week",
|
|
2284
|
+
"time",
|
|
2285
|
+
"datetime-local"
|
|
2286
|
+
];
|
|
2287
|
+
var HTML_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
2288
|
+
...TEXT_INPUT_TYPES,
|
|
2289
|
+
...NUMERIC_INPUT_TYPES,
|
|
2290
|
+
"checkbox",
|
|
2291
|
+
"radio",
|
|
2292
|
+
"file",
|
|
2293
|
+
"color",
|
|
2294
|
+
"hidden",
|
|
2295
|
+
"button",
|
|
2296
|
+
"submit",
|
|
2297
|
+
"reset",
|
|
2298
|
+
"image"
|
|
2299
|
+
]);
|
|
2300
|
+
|
|
2301
|
+
// ../core/src/html/spec/attributes/input.ts
|
|
2302
|
+
var INPUT_ATTRIBUTE_TYPE_POLICIES = [
|
|
2303
|
+
{ attribute: "checked", allowedTypes: ["checkbox", "radio"] },
|
|
2304
|
+
{ attribute: "multiple", allowedTypes: ["email", "file"] },
|
|
2305
|
+
{ attribute: "maxLength", allowedTypes: TEXT_INPUT_TYPES },
|
|
2306
|
+
{ attribute: "minLength", allowedTypes: TEXT_INPUT_TYPES },
|
|
2307
|
+
{ attribute: "pattern", allowedTypes: TEXT_INPUT_TYPES },
|
|
2308
|
+
{ attribute: "min", allowedTypes: NUMERIC_INPUT_TYPES },
|
|
2309
|
+
{ attribute: "max", allowedTypes: NUMERIC_INPUT_TYPES },
|
|
2310
|
+
{ attribute: "step", allowedTypes: NUMERIC_INPUT_TYPES },
|
|
2311
|
+
{ attribute: "accept", allowedTypes: ["file"] },
|
|
2312
|
+
{ attribute: "capture", allowedTypes: ["file"] },
|
|
2313
|
+
{ attribute: "size", allowedTypes: TEXT_INPUT_TYPES },
|
|
2314
|
+
{ attribute: "alt", allowedTypes: ["image"] },
|
|
2315
|
+
{ attribute: "height", allowedTypes: ["image"] },
|
|
2316
|
+
{ attribute: "width", allowedTypes: ["image"] }
|
|
2317
|
+
];
|
|
2318
|
+
|
|
2319
|
+
// ../core/src/html/spec/constraints/input.ts
|
|
2320
|
+
var REQUIRED_READONLY_CONFLICT = {
|
|
2321
|
+
props: ["required", "readOnly"],
|
|
2322
|
+
diagnostic: () => InputAccessibilityDiagnostics.requiredReadOnlyConflict()
|
|
2323
|
+
};
|
|
2324
|
+
var INPUT_MUTUALLY_EXCLUSIVE_POLICIES = [
|
|
2325
|
+
REQUIRED_READONLY_CONFLICT
|
|
2326
|
+
];
|
|
2327
|
+
|
|
2328
|
+
// ../core/src/html/spec/validators/attribute-type-validator.ts
|
|
2262
2329
|
var DEFAULT_INPUT_TYPE = "text";
|
|
2263
2330
|
function omit(props, key) {
|
|
2264
2331
|
const next = { ...props };
|
|
@@ -2274,7 +2341,10 @@ function removeAttributeFix(attribute) {
|
|
|
2274
2341
|
}
|
|
2275
2342
|
};
|
|
2276
2343
|
}
|
|
2277
|
-
function
|
|
2344
|
+
function createInputAttributeTypeRule({
|
|
2345
|
+
attribute,
|
|
2346
|
+
allowedTypes
|
|
2347
|
+
}) {
|
|
2278
2348
|
const rule = ({ tag, props }) => {
|
|
2279
2349
|
if (tag !== "input" || !(attribute in props)) return [];
|
|
2280
2350
|
const type = typeof props.type === "string" ? props.type : DEFAULT_INPUT_TYPE;
|
|
@@ -2290,31 +2360,30 @@ function inputAttributeRequiresType(attribute, allowedTypes) {
|
|
|
2290
2360
|
}
|
|
2291
2361
|
];
|
|
2292
2362
|
};
|
|
2293
|
-
return Object.assign(rule, { readsProps: ["type", attribute] });
|
|
2363
|
+
return Object.assign(rule, { readsProps: ["type", attribute], tags: ["input"] });
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
// ../core/src/html/spec/validators/mutually-exclusive-validator.ts
|
|
2367
|
+
function createMutuallyExclusiveRule({
|
|
2368
|
+
props: conflictingProps,
|
|
2369
|
+
diagnostic: createDiagnostic
|
|
2370
|
+
}) {
|
|
2371
|
+
const [first, second] = conflictingProps;
|
|
2372
|
+
const rule = ({ tag, props }) => {
|
|
2373
|
+
if (tag !== "input" || !props[first] || !props[second]) return [];
|
|
2374
|
+
const diagnostic = createDiagnostic();
|
|
2375
|
+
return [{ valid: false, fixable: false, severity: diagnostic.severity, diagnostic }];
|
|
2376
|
+
};
|
|
2377
|
+
return Object.assign(rule, { readsProps: conflictingProps, tags: ["input"] });
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
// ../core/src/html/input-rules.ts
|
|
2381
|
+
var policyByAttribute = Object.fromEntries(
|
|
2382
|
+
INPUT_ATTRIBUTE_TYPE_POLICIES.map((policy) => [policy.attribute, policy])
|
|
2383
|
+
);
|
|
2384
|
+
function policyFor(attribute) {
|
|
2385
|
+
return policyByAttribute[attribute];
|
|
2294
2386
|
}
|
|
2295
|
-
var TEXT_INPUT_TYPES = ["text", "search", "url", "tel", "email", "password"];
|
|
2296
|
-
var NUMERIC_INPUT_TYPES = [
|
|
2297
|
-
"number",
|
|
2298
|
-
"range",
|
|
2299
|
-
"date",
|
|
2300
|
-
"month",
|
|
2301
|
-
"week",
|
|
2302
|
-
"time",
|
|
2303
|
-
"datetime-local"
|
|
2304
|
-
];
|
|
2305
|
-
var HTML_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
2306
|
-
...TEXT_INPUT_TYPES,
|
|
2307
|
-
...NUMERIC_INPUT_TYPES,
|
|
2308
|
-
"checkbox",
|
|
2309
|
-
"radio",
|
|
2310
|
-
"file",
|
|
2311
|
-
"color",
|
|
2312
|
-
"hidden",
|
|
2313
|
-
"button",
|
|
2314
|
-
"submit",
|
|
2315
|
-
"reset",
|
|
2316
|
-
"image"
|
|
2317
|
-
]);
|
|
2318
2387
|
var supportedInputTypeRule = Object.assign(
|
|
2319
2388
|
({ tag, props }) => {
|
|
2320
2389
|
if (tag !== "input" || typeof props.type !== "string") return [];
|
|
@@ -2330,30 +2399,22 @@ var supportedInputTypeRule = Object.assign(
|
|
|
2330
2399
|
}
|
|
2331
2400
|
];
|
|
2332
2401
|
},
|
|
2333
|
-
{ readsProps: ["type"] }
|
|
2402
|
+
{ readsProps: ["type"], tags: ["input"] }
|
|
2334
2403
|
);
|
|
2335
|
-
var checkedRequiresCheckableTypeRule =
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
var
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
var
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
);
|
|
2347
|
-
var
|
|
2348
|
-
|
|
2349
|
-
TEXT_INPUT_TYPES
|
|
2350
|
-
);
|
|
2351
|
-
var patternRequiresTextTypeRule = inputAttributeRequiresType("pattern", TEXT_INPUT_TYPES);
|
|
2352
|
-
var minRequiresNumericTypeRule = inputAttributeRequiresType("min", NUMERIC_INPUT_TYPES);
|
|
2353
|
-
var maxRequiresNumericTypeRule = inputAttributeRequiresType("max", NUMERIC_INPUT_TYPES);
|
|
2354
|
-
var stepRequiresNumericTypeRule = inputAttributeRequiresType("step", NUMERIC_INPUT_TYPES);
|
|
2355
|
-
var acceptRequiresFileTypeRule = inputAttributeRequiresType("accept", ["file"]);
|
|
2356
|
-
var captureRequiresFileTypeRule = inputAttributeRequiresType("capture", ["file"]);
|
|
2404
|
+
var checkedRequiresCheckableTypeRule = createInputAttributeTypeRule(policyFor("checked"));
|
|
2405
|
+
var multipleRequiresSupportedTypeRule = createInputAttributeTypeRule(policyFor("multiple"));
|
|
2406
|
+
var maxLengthRequiresTextTypeRule = createInputAttributeTypeRule(policyFor("maxLength"));
|
|
2407
|
+
var minLengthRequiresTextTypeRule = createInputAttributeTypeRule(policyFor("minLength"));
|
|
2408
|
+
var patternRequiresTextTypeRule = createInputAttributeTypeRule(policyFor("pattern"));
|
|
2409
|
+
var minRequiresNumericTypeRule = createInputAttributeTypeRule(policyFor("min"));
|
|
2410
|
+
var maxRequiresNumericTypeRule = createInputAttributeTypeRule(policyFor("max"));
|
|
2411
|
+
var stepRequiresNumericTypeRule = createInputAttributeTypeRule(policyFor("step"));
|
|
2412
|
+
var acceptRequiresFileTypeRule = createInputAttributeTypeRule(policyFor("accept"));
|
|
2413
|
+
var captureRequiresFileTypeRule = createInputAttributeTypeRule(policyFor("capture"));
|
|
2414
|
+
var sizeRequiresTextTypeRule = createInputAttributeTypeRule(policyFor("size"));
|
|
2415
|
+
var altRequiresImageTypeRule = createInputAttributeTypeRule(policyFor("alt"));
|
|
2416
|
+
var heightRequiresImageTypeRule = createInputAttributeTypeRule(policyFor("height"));
|
|
2417
|
+
var widthRequiresImageTypeRule = createInputAttributeTypeRule(policyFor("width"));
|
|
2357
2418
|
var inputAccessibleNameRule = Object.assign(
|
|
2358
2419
|
({ tag, props }) => {
|
|
2359
2420
|
if (tag !== "input" || props.type === "hidden") return [];
|
|
@@ -2362,7 +2423,10 @@ var inputAccessibleNameRule = Object.assign(
|
|
|
2362
2423
|
const diagnostic = hasPlaceholder ? InputAccessibilityDiagnostics.placeholderIsNotLabel() : InputAccessibilityDiagnostics.missingAccessibleName();
|
|
2363
2424
|
return [{ valid: false, fixable: false, severity: diagnostic.severity, diagnostic }];
|
|
2364
2425
|
},
|
|
2365
|
-
{
|
|
2426
|
+
{
|
|
2427
|
+
readsProps: ["type", "aria-label", "aria-labelledby", "placeholder"],
|
|
2428
|
+
tags: ["input"]
|
|
2429
|
+
}
|
|
2366
2430
|
);
|
|
2367
2431
|
var PASSWORD_AUTOCOMPLETE_VALUES = ["current-password", "new-password"];
|
|
2368
2432
|
var passwordAutocompleteRule = Object.assign(
|
|
@@ -2374,16 +2438,9 @@ var passwordAutocompleteRule = Object.assign(
|
|
|
2374
2438
|
const diagnostic = InputAccessibilityDiagnostics.passwordMissingAutocomplete();
|
|
2375
2439
|
return [{ valid: false, fixable: false, severity: diagnostic.severity, diagnostic }];
|
|
2376
2440
|
},
|
|
2377
|
-
{ readsProps: ["type", "autoComplete"] }
|
|
2378
|
-
);
|
|
2379
|
-
var requiredReadOnlyConflictRule = Object.assign(
|
|
2380
|
-
({ tag, props }) => {
|
|
2381
|
-
if (tag !== "input" || !props.required || !props.readOnly) return [];
|
|
2382
|
-
const diagnostic = InputAccessibilityDiagnostics.requiredReadOnlyConflict();
|
|
2383
|
-
return [{ valid: false, fixable: false, severity: diagnostic.severity, diagnostic }];
|
|
2384
|
-
},
|
|
2385
|
-
{ readsProps: ["required", "readOnly"] }
|
|
2441
|
+
{ readsProps: ["type", "autoComplete"], tags: ["input"] }
|
|
2386
2442
|
);
|
|
2443
|
+
var requiredReadOnlyConflictRule = createMutuallyExclusiveRule(REQUIRED_READONLY_CONFLICT);
|
|
2387
2444
|
var INPUT_RULES = [
|
|
2388
2445
|
supportedInputTypeRule,
|
|
2389
2446
|
checkedRequiresCheckableTypeRule,
|
|
@@ -2396,11 +2453,132 @@ var INPUT_RULES = [
|
|
|
2396
2453
|
stepRequiresNumericTypeRule,
|
|
2397
2454
|
acceptRequiresFileTypeRule,
|
|
2398
2455
|
captureRequiresFileTypeRule,
|
|
2456
|
+
sizeRequiresTextTypeRule,
|
|
2457
|
+
altRequiresImageTypeRule,
|
|
2458
|
+
heightRequiresImageTypeRule,
|
|
2459
|
+
widthRequiresImageTypeRule,
|
|
2399
2460
|
inputAccessibleNameRule,
|
|
2400
2461
|
passwordAutocompleteRule,
|
|
2401
2462
|
requiredReadOnlyConflictRule
|
|
2402
2463
|
];
|
|
2403
2464
|
|
|
2465
|
+
// ../core/src/html/spec/types.ts
|
|
2466
|
+
function definePropRolePolicy(prop, map2, fallback) {
|
|
2467
|
+
return { kind: "byProp", prop, map: map2, fallback };
|
|
2468
|
+
}
|
|
2469
|
+
function resolveAllowedRoles(spec, props) {
|
|
2470
|
+
const policy = spec.allowedRoles;
|
|
2471
|
+
if (!policy) return void 0;
|
|
2472
|
+
switch (policy.kind) {
|
|
2473
|
+
case "fixed":
|
|
2474
|
+
return policy.roles;
|
|
2475
|
+
case "byProp": {
|
|
2476
|
+
const value = typeof props[policy.prop] === "string" ? props[policy.prop] : policy.fallback;
|
|
2477
|
+
return policy.map[value];
|
|
2478
|
+
}
|
|
2479
|
+
case "dynamic":
|
|
2480
|
+
return policy.resolve({ props });
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
// ../core/src/html/spec/roles/input.ts
|
|
2485
|
+
var ALLOWED_INPUT_ROLES = {
|
|
2486
|
+
checkbox: ["menuitemcheckbox", "option", "switch", "button"],
|
|
2487
|
+
radio: ["menuitemradio"],
|
|
2488
|
+
range: [],
|
|
2489
|
+
number: [],
|
|
2490
|
+
search: ["combobox"],
|
|
2491
|
+
text: ["combobox", "searchbox", "spinbutton"],
|
|
2492
|
+
email: ["combobox"],
|
|
2493
|
+
tel: ["combobox"],
|
|
2494
|
+
url: ["combobox"],
|
|
2495
|
+
button: [
|
|
2496
|
+
"link",
|
|
2497
|
+
"menuitem",
|
|
2498
|
+
"menuitemcheckbox",
|
|
2499
|
+
"menuitemradio",
|
|
2500
|
+
"option",
|
|
2501
|
+
"radio",
|
|
2502
|
+
"switch",
|
|
2503
|
+
"tab"
|
|
2504
|
+
],
|
|
2505
|
+
submit: [
|
|
2506
|
+
"link",
|
|
2507
|
+
"menuitem",
|
|
2508
|
+
"menuitemcheckbox",
|
|
2509
|
+
"menuitemradio",
|
|
2510
|
+
"option",
|
|
2511
|
+
"radio",
|
|
2512
|
+
"switch",
|
|
2513
|
+
"tab"
|
|
2514
|
+
],
|
|
2515
|
+
reset: [
|
|
2516
|
+
"link",
|
|
2517
|
+
"menuitem",
|
|
2518
|
+
"menuitemcheckbox",
|
|
2519
|
+
"menuitemradio",
|
|
2520
|
+
"option",
|
|
2521
|
+
"radio",
|
|
2522
|
+
"switch",
|
|
2523
|
+
"tab"
|
|
2524
|
+
],
|
|
2525
|
+
image: [
|
|
2526
|
+
"link",
|
|
2527
|
+
"menuitem",
|
|
2528
|
+
"menuitemcheckbox",
|
|
2529
|
+
"menuitemradio",
|
|
2530
|
+
"option",
|
|
2531
|
+
"radio",
|
|
2532
|
+
"switch",
|
|
2533
|
+
"tab"
|
|
2534
|
+
],
|
|
2535
|
+
hidden: []
|
|
2536
|
+
};
|
|
2537
|
+
|
|
2538
|
+
// ../core/src/html/spec/elements/input.ts
|
|
2539
|
+
var inputElementSpec = {
|
|
2540
|
+
tag: "input",
|
|
2541
|
+
allowedRoles: definePropRolePolicy("type", ALLOWED_INPUT_ROLES, "text"),
|
|
2542
|
+
attributes: INPUT_ATTRIBUTE_TYPE_POLICIES,
|
|
2543
|
+
mutuallyExclusive: INPUT_MUTUALLY_EXCLUSIVE_POLICIES
|
|
2544
|
+
};
|
|
2545
|
+
|
|
2546
|
+
// ../core/src/html/spec/roles/img.ts
|
|
2547
|
+
var IMG_NAMED_ROLES = [
|
|
2548
|
+
"button",
|
|
2549
|
+
"checkbox",
|
|
2550
|
+
"link",
|
|
2551
|
+
"menuitem",
|
|
2552
|
+
"menuitemcheckbox",
|
|
2553
|
+
"menuitemradio",
|
|
2554
|
+
"option",
|
|
2555
|
+
"progressbar",
|
|
2556
|
+
"scrollbar",
|
|
2557
|
+
"separator",
|
|
2558
|
+
"slider",
|
|
2559
|
+
"switch",
|
|
2560
|
+
"tab",
|
|
2561
|
+
"treeitem"
|
|
2562
|
+
];
|
|
2563
|
+
|
|
2564
|
+
// ../core/src/html/spec/elements/img.ts
|
|
2565
|
+
var imgElementSpec = {
|
|
2566
|
+
tag: "img",
|
|
2567
|
+
allowedRoles: {
|
|
2568
|
+
kind: "dynamic",
|
|
2569
|
+
resolve: ({ props }) => props.alt === "" ? [] : IMG_NAMED_ROLES
|
|
2570
|
+
}
|
|
2571
|
+
};
|
|
2572
|
+
|
|
2573
|
+
// ../core/src/html/spec/roles/table.ts
|
|
2574
|
+
var ALLOWED_TABLE_ROLES = ["grid", "treegrid"];
|
|
2575
|
+
|
|
2576
|
+
// ../core/src/html/spec/elements/table.ts
|
|
2577
|
+
var tableElementSpec = {
|
|
2578
|
+
tag: "table",
|
|
2579
|
+
allowedRoles: { kind: "fixed", roles: ALLOWED_TABLE_ROLES }
|
|
2580
|
+
};
|
|
2581
|
+
|
|
2404
2582
|
// ../core/src/html/role-restrictions.ts
|
|
2405
2583
|
var ALLOWED_ROLES = {
|
|
2406
2584
|
article: ["application", "document", "feed", "main", "none", "presentation", "region"],
|
|
@@ -2473,86 +2651,17 @@ var ALLOWED_ROLES = {
|
|
|
2473
2651
|
"tab",
|
|
2474
2652
|
"treeitem"
|
|
2475
2653
|
],
|
|
2476
|
-
table: ["grid", "treegrid"],
|
|
2477
2654
|
dialog: ["alertdialog"],
|
|
2478
2655
|
fieldset: ["none", "presentation", "radiogroup"]
|
|
2479
2656
|
};
|
|
2480
|
-
var
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
"menuitem",
|
|
2485
|
-
"menuitemcheckbox",
|
|
2486
|
-
"menuitemradio",
|
|
2487
|
-
"option",
|
|
2488
|
-
"progressbar",
|
|
2489
|
-
"scrollbar",
|
|
2490
|
-
"separator",
|
|
2491
|
-
"slider",
|
|
2492
|
-
"switch",
|
|
2493
|
-
"tab",
|
|
2494
|
-
"treeitem"
|
|
2495
|
-
];
|
|
2496
|
-
var ALLOWED_INPUT_ROLES = {
|
|
2497
|
-
checkbox: ["menuitemcheckbox", "option", "switch", "button"],
|
|
2498
|
-
radio: ["menuitemradio"],
|
|
2499
|
-
range: [],
|
|
2500
|
-
number: [],
|
|
2501
|
-
search: ["combobox"],
|
|
2502
|
-
text: ["combobox", "searchbox", "spinbutton"],
|
|
2503
|
-
email: ["combobox"],
|
|
2504
|
-
tel: ["combobox"],
|
|
2505
|
-
url: ["combobox"],
|
|
2506
|
-
button: [
|
|
2507
|
-
"link",
|
|
2508
|
-
"menuitem",
|
|
2509
|
-
"menuitemcheckbox",
|
|
2510
|
-
"menuitemradio",
|
|
2511
|
-
"option",
|
|
2512
|
-
"radio",
|
|
2513
|
-
"switch",
|
|
2514
|
-
"tab"
|
|
2515
|
-
],
|
|
2516
|
-
submit: [
|
|
2517
|
-
"link",
|
|
2518
|
-
"menuitem",
|
|
2519
|
-
"menuitemcheckbox",
|
|
2520
|
-
"menuitemradio",
|
|
2521
|
-
"option",
|
|
2522
|
-
"radio",
|
|
2523
|
-
"switch",
|
|
2524
|
-
"tab"
|
|
2525
|
-
],
|
|
2526
|
-
reset: [
|
|
2527
|
-
"link",
|
|
2528
|
-
"menuitem",
|
|
2529
|
-
"menuitemcheckbox",
|
|
2530
|
-
"menuitemradio",
|
|
2531
|
-
"option",
|
|
2532
|
-
"radio",
|
|
2533
|
-
"switch",
|
|
2534
|
-
"tab"
|
|
2535
|
-
],
|
|
2536
|
-
image: [
|
|
2537
|
-
"link",
|
|
2538
|
-
"menuitem",
|
|
2539
|
-
"menuitemcheckbox",
|
|
2540
|
-
"menuitemradio",
|
|
2541
|
-
"option",
|
|
2542
|
-
"radio",
|
|
2543
|
-
"switch",
|
|
2544
|
-
"tab"
|
|
2545
|
-
],
|
|
2546
|
-
hidden: []
|
|
2657
|
+
var ELEMENT_SPECS = {
|
|
2658
|
+
input: inputElementSpec,
|
|
2659
|
+
img: imgElementSpec,
|
|
2660
|
+
table: tableElementSpec
|
|
2547
2661
|
};
|
|
2548
2662
|
function getAllowedRoles(tag, props) {
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
return ALLOWED_INPUT_ROLES[type];
|
|
2552
|
-
}
|
|
2553
|
-
if (tag === "img") {
|
|
2554
|
-
return props.alt === "" ? [] : IMG_NAMED_ROLES;
|
|
2555
|
-
}
|
|
2663
|
+
const spec = ELEMENT_SPECS[tag];
|
|
2664
|
+
if (spec) return resolveAllowedRoles(spec, props);
|
|
2556
2665
|
return ALLOWED_ROLES[tag];
|
|
2557
2666
|
}
|
|
2558
2667
|
var removeRoleFix = {
|
|
@@ -2593,21 +2702,24 @@ var removeLandmarkRoleOverride = {
|
|
|
2593
2702
|
return { applied: true, next: rest, previous: props };
|
|
2594
2703
|
}
|
|
2595
2704
|
};
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2705
|
+
var landmarkRoleRule = Object.assign(
|
|
2706
|
+
({ tag, props, implicitRole }) => {
|
|
2707
|
+
if (!LANDMARK_TAG_SET.has(tag) || !implicitRole) return [];
|
|
2708
|
+
const role = props.role;
|
|
2709
|
+
if (!role || role === implicitRole) return [];
|
|
2710
|
+
const diagnostic = HtmlDiagnostics.landmarkRoleOverride(tag, implicitRole, role);
|
|
2711
|
+
return [
|
|
2712
|
+
{
|
|
2713
|
+
valid: false,
|
|
2714
|
+
fixable: true,
|
|
2715
|
+
severity: diagnostic.severity,
|
|
2716
|
+
fix: removeLandmarkRoleOverride,
|
|
2717
|
+
diagnostic
|
|
2718
|
+
}
|
|
2719
|
+
];
|
|
2720
|
+
},
|
|
2721
|
+
{ tags: [...LANDMARK_TAG_SET] }
|
|
2722
|
+
);
|
|
2611
2723
|
function requireAccessibleName({ tag, props }) {
|
|
2612
2724
|
if ("aria-label" in props || "aria-labelledby" in props) return [];
|
|
2613
2725
|
return [
|
|
@@ -2620,10 +2732,13 @@ function requireAccessibleName({ tag, props }) {
|
|
|
2620
2732
|
];
|
|
2621
2733
|
}
|
|
2622
2734
|
var NAMED_LANDMARK_TAGS = /* @__PURE__ */ new Set(["nav", "aside"]);
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2735
|
+
var landmarkNameAdvisory = Object.assign(
|
|
2736
|
+
(ctx) => {
|
|
2737
|
+
if (!ctx.implicitRole || !NAMED_LANDMARK_TAGS.has(ctx.tag)) return [];
|
|
2738
|
+
return requireAccessibleName(ctx);
|
|
2739
|
+
},
|
|
2740
|
+
{ tags: [...NAMED_LANDMARK_TAGS] }
|
|
2741
|
+
);
|
|
2627
2742
|
var HTML_ARIA_RULES = [
|
|
2628
2743
|
landmarkRoleRule,
|
|
2629
2744
|
landmarkNameAdvisory,
|
|
@@ -2724,6 +2839,62 @@ var figureContract = contract([
|
|
|
2724
2839
|
]);
|
|
2725
2840
|
var detailsContract = firstChildContract("summary", "summary");
|
|
2726
2841
|
var fieldsetContract = firstChildContract("legend", "legend");
|
|
2842
|
+
var objectContract = contract([
|
|
2843
|
+
{ name: "param", match: isTag("param") },
|
|
2844
|
+
{ name: "content", match: isOpenContent("param") }
|
|
2845
|
+
]);
|
|
2846
|
+
var INTERACTIVE_CONTENT_TAGS = ["a", "button", "input", "select", "textarea", "label"];
|
|
2847
|
+
var buttonContract = closedContract([
|
|
2848
|
+
{ name: "content", match: isOpenContent(...INTERACTIVE_CONTENT_TAGS) }
|
|
2849
|
+
]);
|
|
2850
|
+
var anchorContract = closedContract([
|
|
2851
|
+
{ name: "content", match: isOpenContent(...INTERACTIVE_CONTENT_TAGS) }
|
|
2852
|
+
]);
|
|
2853
|
+
var LABELABLE_TAGS = [
|
|
2854
|
+
"button",
|
|
2855
|
+
"input",
|
|
2856
|
+
"meter",
|
|
2857
|
+
"output",
|
|
2858
|
+
"progress",
|
|
2859
|
+
"select",
|
|
2860
|
+
"textarea"
|
|
2861
|
+
];
|
|
2862
|
+
var labelContract = contract([
|
|
2863
|
+
{ name: "control", match: isTag(...LABELABLE_TAGS), cardinality: { max: 1 } }
|
|
2864
|
+
]);
|
|
2865
|
+
var P_BLOCKED_TAGS = [
|
|
2866
|
+
"address",
|
|
2867
|
+
"article",
|
|
2868
|
+
"aside",
|
|
2869
|
+
"blockquote",
|
|
2870
|
+
"details",
|
|
2871
|
+
"dialog",
|
|
2872
|
+
"div",
|
|
2873
|
+
"dl",
|
|
2874
|
+
"fieldset",
|
|
2875
|
+
"figure",
|
|
2876
|
+
"footer",
|
|
2877
|
+
"form",
|
|
2878
|
+
"h1",
|
|
2879
|
+
"h2",
|
|
2880
|
+
"h3",
|
|
2881
|
+
"h4",
|
|
2882
|
+
"h5",
|
|
2883
|
+
"h6",
|
|
2884
|
+
"header",
|
|
2885
|
+
"hr",
|
|
2886
|
+
"main",
|
|
2887
|
+
"nav",
|
|
2888
|
+
"ol",
|
|
2889
|
+
"p",
|
|
2890
|
+
"pre",
|
|
2891
|
+
"section",
|
|
2892
|
+
"table",
|
|
2893
|
+
"ul"
|
|
2894
|
+
];
|
|
2895
|
+
var pContract = closedContract([
|
|
2896
|
+
{ name: "content", match: isOpenContent(...P_BLOCKED_TAGS) }
|
|
2897
|
+
]);
|
|
2727
2898
|
var mediaContract = contract([
|
|
2728
2899
|
{ name: "source", match: isTag("source") },
|
|
2729
2900
|
{ name: "track", match: isTag("track") },
|
|
@@ -2778,6 +2949,11 @@ var htmlContracts = {
|
|
|
2778
2949
|
details: detailsContract,
|
|
2779
2950
|
fieldset: fieldsetContract,
|
|
2780
2951
|
dialog: dialogContract,
|
|
2952
|
+
object: objectContract,
|
|
2953
|
+
button: buttonContract,
|
|
2954
|
+
a: anchorContract,
|
|
2955
|
+
label: labelContract,
|
|
2956
|
+
p: pContract,
|
|
2781
2957
|
head: headContract,
|
|
2782
2958
|
html: htmlContract
|
|
2783
2959
|
};
|