html-validate 8.10.0 → 8.11.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.
@@ -45,6 +45,7 @@ exports.TextNode = core.TextNode;
45
45
  exports.UserError = core.UserError;
46
46
  exports.Validator = core.Validator;
47
47
  exports.WrappedError = core.WrappedError;
48
+ exports.ariaNaming = core.ariaNaming;
48
49
  exports.classifyNodeText = core.classifyNodeText;
49
50
  exports.configPresets = core.Presets;
50
51
  exports.defineConfig = core.defineConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"browser.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/cjs/core.js CHANGED
@@ -594,8 +594,13 @@ const patternProperties = {
594
594
  implicitRole: {
595
595
  title: "Implicit ARIA role for this element",
596
596
  description: "Some elements have implicit ARIA roles.",
597
+ deprecated: true,
597
598
  "function": true
598
599
  },
600
+ aria: {
601
+ title: "WAI-ARIA properties for this element",
602
+ $ref: "#/definitions/Aria"
603
+ },
599
604
  scriptSupporting: {
600
605
  title: "Mark element as script-supporting",
601
606
  description: "Script-supporting elements are elements which can be inserted where othersise not permitted to assist in templating",
@@ -692,6 +697,39 @@ const patternProperties = {
692
697
  }
693
698
  };
694
699
  const definitions = {
700
+ Aria: {
701
+ type: "object",
702
+ additionalProperties: false,
703
+ properties: {
704
+ implicitRole: {
705
+ title: "Implicit ARIA role for this element",
706
+ description: "Some elements have implicit ARIA roles.",
707
+ anyOf: [
708
+ {
709
+ type: "string"
710
+ },
711
+ {
712
+ "function": true
713
+ }
714
+ ]
715
+ },
716
+ naming: {
717
+ title: "Prohibit or allow this element to be named by aria-label or aria-labelledby",
718
+ anyOf: [
719
+ {
720
+ type: "string",
721
+ "enum": [
722
+ "prohibited",
723
+ "allowed"
724
+ ]
725
+ },
726
+ {
727
+ "function": true
728
+ }
729
+ ]
730
+ }
731
+ }
732
+ },
695
733
  contentCategory: {
696
734
  anyOf: [
697
735
  {
@@ -992,6 +1030,7 @@ const MetaCopyableProperty = [
992
1030
  "formAssociated",
993
1031
  "labelable",
994
1032
  "attributes",
1033
+ "aria",
995
1034
  "permittedContent",
996
1035
  "permittedDescendants",
997
1036
  "permittedOrder",
@@ -1052,7 +1091,27 @@ function migrateAttributes(src) {
1052
1091
  });
1053
1092
  return Object.fromEntries(entries);
1054
1093
  }
1094
+ function normalizeAriaImplicitRole(value) {
1095
+ if (!value) {
1096
+ return () => null;
1097
+ }
1098
+ if (typeof value === "string") {
1099
+ return () => value;
1100
+ }
1101
+ return value;
1102
+ }
1103
+ function normalizeAriaNaming(value) {
1104
+ if (!value) {
1105
+ return () => "allowed";
1106
+ }
1107
+ if (typeof value === "string") {
1108
+ return () => value;
1109
+ }
1110
+ return value;
1111
+ }
1055
1112
  function migrateElement(src) {
1113
+ var _a, _b;
1114
+ const implicitRole = normalizeAriaImplicitRole(src.implicitRole ?? ((_a = src.aria) == null ? void 0 : _a.implicitRole));
1056
1115
  const result = {
1057
1116
  ...src,
1058
1117
  ...{
@@ -1061,7 +1120,11 @@ function migrateElement(src) {
1061
1120
  attributes: migrateAttributes(src),
1062
1121
  textContent: src.textContent,
1063
1122
  focusable: src.focusable ?? false,
1064
- implicitRole: src.implicitRole ?? (() => null)
1123
+ implicitRole,
1124
+ aria: {
1125
+ implicitRole,
1126
+ naming: normalizeAriaNaming((_b = src.aria) == null ? void 0 : _b.naming)
1127
+ }
1065
1128
  };
1066
1129
  delete result.deprecatedAttributes;
1067
1130
  delete result.requiredAttributes;
@@ -1903,8 +1966,30 @@ function factory$1(name, context) {
1903
1966
  function stripslashes(value) {
1904
1967
  return value.replace(/\\(.)/g, "$1");
1905
1968
  }
1969
+ function unescapeCodepoint(value) {
1970
+ const replacement = {
1971
+ "\\9 ": " ",
1972
+ "\\a ": "\n",
1973
+ "\\d ": "\r"
1974
+ };
1975
+ return value.replace(
1976
+ /(\\[\u0039\u0061\u0064] )/g,
1977
+ (_, codepoint) => replacement[codepoint]
1978
+ );
1979
+ }
1906
1980
  function escapeSelectorComponent(text) {
1907
- return text.toString().replace(/([^a-z0-9_-])/gi, "\\$1");
1981
+ const codepoints = {
1982
+ " ": "\\9 ",
1983
+ "\n": "\\a ",
1984
+ "\r": "\\d "
1985
+ };
1986
+ return text.toString().replace(/([\t\n\r]|[^a-z0-9_-])/gi, (_, ch) => {
1987
+ if (codepoints[ch]) {
1988
+ return codepoints[ch];
1989
+ } else {
1990
+ return `\\${ch}`;
1991
+ }
1992
+ });
1908
1993
  }
1909
1994
  function generateIdSelector(id) {
1910
1995
  const escaped = escapeSelectorComponent(id);
@@ -2019,7 +2104,10 @@ class PseudoClassMatcher extends Matcher {
2019
2104
  }
2020
2105
  class Pattern {
2021
2106
  constructor(pattern) {
2022
- const match = pattern.match(/^([~+\->]?)((?:[*]|[^.#[:]+)?)(.*)$/);
2107
+ const match = pattern.match(/^([~+\->]?)((?:[*]|[^.#[:]+)?)([^]*)$/);
2108
+ if (!match) {
2109
+ throw new Error(`Failed to create selector pattern from "${pattern}"`);
2110
+ }
2023
2111
  match.shift();
2024
2112
  this.selector = pattern;
2025
2113
  this.combinator = parseCombinator(match.shift(), pattern);
@@ -2075,10 +2163,10 @@ class Selector {
2075
2163
  static parse(selector) {
2076
2164
  selector = selector.replace(/([+~>]) /g, "$1");
2077
2165
  let begin = 0;
2078
- const delimiter = /((?:[^\\]) +|$)/g;
2166
+ const delimiter = /((?:[^\\\u0039\u0061\u0064]) +|$)/g;
2079
2167
  return Array.from(selector.matchAll(delimiter), (match) => {
2080
2168
  const end = match.index + 1;
2081
- const part = selector.slice(begin, end);
2169
+ const part = unescapeCodepoint(selector.slice(begin, end));
2082
2170
  begin = end + 1;
2083
2171
  return new Pattern(part);
2084
2172
  });
@@ -2411,7 +2499,8 @@ class HtmlElement extends DOMNode {
2411
2499
  return this.cacheSet(ROLE, role.value);
2412
2500
  }
2413
2501
  if (this.metaElement) {
2414
- const implicitRole = this.metaElement.implicitRole(this._adapter);
2502
+ const { aria } = this.metaElement;
2503
+ const implicitRole = aria.implicitRole(this._adapter);
2415
2504
  return this.cacheSet(ROLE, implicitRole);
2416
2505
  }
2417
2506
  return this.cacheSet(ROLE, null);
@@ -3153,6 +3242,48 @@ function interpolate(text, data) {
3153
3242
  });
3154
3243
  }
3155
3244
 
3245
+ const cacheKey = Symbol("aria-naming");
3246
+ const defaultValue = "allowed";
3247
+ const prohibitedRoles = [
3248
+ "caption",
3249
+ "code",
3250
+ "deletion",
3251
+ "emphasis",
3252
+ "generic",
3253
+ "insertion",
3254
+ "paragraph",
3255
+ "presentation",
3256
+ "strong",
3257
+ "subscript",
3258
+ "superscript"
3259
+ ];
3260
+ function byRole(role) {
3261
+ return prohibitedRoles.includes(role) ? "prohibited" : "allowed";
3262
+ }
3263
+ function byMeta(element, meta) {
3264
+ return meta.aria.naming(element._adapter);
3265
+ }
3266
+ function ariaNaming(element) {
3267
+ var _a;
3268
+ const cached = element.cacheGet(cacheKey);
3269
+ if (cached) {
3270
+ return cached;
3271
+ }
3272
+ const role = (_a = element.getAttribute("role")) == null ? void 0 : _a.value;
3273
+ if (role) {
3274
+ if (role instanceof DynamicValue) {
3275
+ return element.cacheSet(cacheKey, defaultValue);
3276
+ } else {
3277
+ return element.cacheSet(cacheKey, byRole(role));
3278
+ }
3279
+ }
3280
+ const meta = element.meta;
3281
+ if (!meta) {
3282
+ return element.cacheSet(cacheKey, defaultValue);
3283
+ }
3284
+ return element.cacheSet(cacheKey, byMeta(element, meta));
3285
+ }
3286
+
3156
3287
  const patternCache = /* @__PURE__ */ new Map();
3157
3288
  function compileStringPattern(pattern) {
3158
3289
  const regexp = pattern.replace(/[*]+/g, ".+");
@@ -3671,7 +3802,7 @@ class Rule {
3671
3802
  }
3672
3803
  }
3673
3804
 
3674
- const defaults$u = {
3805
+ const defaults$v = {
3675
3806
  allowExternal: true,
3676
3807
  allowRelative: true,
3677
3808
  allowAbsolute: true,
@@ -3712,7 +3843,7 @@ function matchList(value, list) {
3712
3843
  }
3713
3844
  class AllowedLinks extends Rule {
3714
3845
  constructor(options) {
3715
- super({ ...defaults$u, ...options });
3846
+ super({ ...defaults$v, ...options });
3716
3847
  this.allowExternal = parseAllow(this.options.allowExternal);
3717
3848
  this.allowRelative = parseAllow(this.options.allowRelative);
3718
3849
  this.allowAbsolute = parseAllow(this.options.allowAbsolute);
@@ -3876,7 +4007,7 @@ class AllowedLinks extends Rule {
3876
4007
  }
3877
4008
  }
3878
4009
 
3879
- const defaults$t = {
4010
+ const defaults$u = {
3880
4011
  accessible: true
3881
4012
  };
3882
4013
  function findByTarget(target, siblings) {
@@ -3906,7 +4037,7 @@ function getDescription$1(context) {
3906
4037
  }
3907
4038
  class AreaAlt extends Rule {
3908
4039
  constructor(options) {
3909
- super({ ...defaults$t, ...options });
4040
+ super({ ...defaults$u, ...options });
3910
4041
  }
3911
4042
  static schema() {
3912
4043
  return {
@@ -3985,6 +4116,9 @@ class AriaHiddenBody extends Rule {
3985
4116
  }
3986
4117
  }
3987
4118
 
4119
+ const defaults$t = {
4120
+ allowAnyNamable: false
4121
+ };
3988
4122
  const whitelisted = [
3989
4123
  "main",
3990
4124
  "nav",
@@ -4023,6 +4157,9 @@ function isValidUsage(target, meta) {
4023
4157
  return false;
4024
4158
  }
4025
4159
  class AriaLabelMisuse extends Rule {
4160
+ constructor(options) {
4161
+ super({ ...defaults$t, ...options });
4162
+ }
4026
4163
  documentation() {
4027
4164
  const valid = [
4028
4165
  "Interactive elements",
@@ -4065,6 +4202,9 @@ ${lines}`,
4065
4202
  if (isValidUsage(target, meta)) {
4066
4203
  return;
4067
4204
  }
4205
+ if (this.options.allowAnyNamable && ariaNaming(target) === "allowed") {
4206
+ return;
4207
+ }
4068
4208
  this.report(target, `"aria-label" cannot be used on this element`, attr.keyLocation);
4069
4209
  }
4070
4210
  }
@@ -7562,7 +7702,7 @@ class NoRedundantRole extends Rule {
7562
7702
  if (!meta) {
7563
7703
  return;
7564
7704
  }
7565
- const implicitRole = meta.implicitRole(target._adapter);
7705
+ const implicitRole = meta.aria.implicitRole(target._adapter);
7566
7706
  if (!implicitRole) {
7567
7707
  return;
7568
7708
  }
@@ -9344,7 +9484,7 @@ const config$4 = {
9344
9484
  rules: {
9345
9485
  "area-alt": ["error", { accessible: true }],
9346
9486
  "aria-hidden-body": "error",
9347
- "aria-label-misuse": "error",
9487
+ "aria-label-misuse": ["error", { allowAnyNamable: false }],
9348
9488
  "deprecated-rule": "warn",
9349
9489
  "empty-heading": "error",
9350
9490
  "empty-title": "error",
@@ -9396,7 +9536,7 @@ const config$1 = {
9396
9536
  rules: {
9397
9537
  "area-alt": ["error", { accessible: true }],
9398
9538
  "aria-hidden-body": "error",
9399
- "aria-label-misuse": "error",
9539
+ "aria-label-misuse": ["error", { allowAnyNamable: false }],
9400
9540
  "attr-case": "error",
9401
9541
  "attr-delimiter": "error",
9402
9542
  "attr-quotes": "error",
@@ -9477,6 +9617,7 @@ var recommended = config$1;
9477
9617
  const config = {
9478
9618
  rules: {
9479
9619
  "area-alt": ["error", { accessible: false }],
9620
+ "aria-label-misuse": ["error", { allowAnyNamable: true }],
9480
9621
  "attr-spacing": "error",
9481
9622
  "attribute-allowed-values": "error",
9482
9623
  "attribute-misuse": "error",
@@ -11729,7 +11870,7 @@ class HtmlValidate {
11729
11870
  }
11730
11871
 
11731
11872
  const name = "html-validate";
11732
- const version = "8.10.0";
11873
+ const version = "8.11.0";
11733
11874
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
11734
11875
 
11735
11876
  function definePlugin(plugin) {
@@ -12636,6 +12777,7 @@ exports.TextNode = TextNode;
12636
12777
  exports.UserError = UserError;
12637
12778
  exports.Validator = Validator;
12638
12779
  exports.WrappedError = WrappedError;
12780
+ exports.ariaNaming = ariaNaming;
12639
12781
  exports.bugs = bugs;
12640
12782
  exports.classifyNodeText = classifyNodeText;
12641
12783
  exports.codeframe = codeframe;