@markuplint/rules 2.4.3 → 3.0.0-alpha.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.
Files changed (118) hide show
  1. package/README.md +2 -6
  2. package/lib/attr-check.js +1 -1
  3. package/lib/attr-duplication/index.js +10 -7
  4. package/lib/attr-value-quotes/index.js +22 -26
  5. package/lib/case-sensitive-attr-name/index.d.ts +1 -5
  6. package/lib/case-sensitive-attr-name/index.js +52 -82
  7. package/lib/case-sensitive-tag-name/index.js +39 -31
  8. package/lib/character-reference/index.d.ts +2 -1
  9. package/lib/character-reference/index.js +6 -8
  10. package/lib/class-naming/index.js +12 -12
  11. package/lib/create-message.d.ts +1 -1
  12. package/lib/create-message.js +5 -5
  13. package/lib/deprecated-attr/index.js +17 -18
  14. package/lib/deprecated-element/index.js +5 -7
  15. package/lib/disallowed-element/index.js +8 -9
  16. package/lib/doctype/index.d.ts +1 -1
  17. package/lib/doctype/index.js +8 -8
  18. package/lib/end-tag/index.js +5 -2
  19. package/lib/helpers.d.ts +15 -28
  20. package/lib/helpers.js +42 -156
  21. package/lib/id-duplication/index.js +4 -6
  22. package/lib/index.d.ts +12 -21
  23. package/lib/index.js +0 -8
  24. package/lib/ineffective-attr/index.js +20 -28
  25. package/lib/invalid-attr/index.js +83 -83
  26. package/lib/landmark-roles/index.d.ts +2 -2
  27. package/lib/landmark-roles/index.js +10 -10
  28. package/lib/no-boolean-attr-value/index.js +34 -35
  29. package/lib/no-default-value/index.js +21 -25
  30. package/lib/no-hard-code-id/index.js +10 -14
  31. package/lib/no-refer-to-non-existent-id/index.d.ts +4 -1
  32. package/lib/no-refer-to-non-existent-id/index.js +77 -83
  33. package/lib/no-use-event-handler-attr/index.js +21 -23
  34. package/lib/permitted-contents/choice.d.ts +3 -0
  35. package/lib/permitted-contents/choice.js +37 -0
  36. package/lib/permitted-contents/complex-branch.d.ts +13 -0
  37. package/lib/permitted-contents/complex-branch.js +27 -0
  38. package/lib/permitted-contents/content-model.d.ts +2 -0
  39. package/lib/permitted-contents/content-model.js +49 -0
  40. package/lib/permitted-contents/count-pattern.d.ts +13 -0
  41. package/lib/permitted-contents/count-pattern.js +155 -0
  42. package/lib/permitted-contents/debug.d.ts +2 -0
  43. package/lib/permitted-contents/debug.js +5 -0
  44. package/lib/permitted-contents/index.d.ts +2 -5
  45. package/lib/permitted-contents/index.js +78 -249
  46. package/lib/permitted-contents/matches-selector.d.ts +3 -0
  47. package/lib/permitted-contents/matches-selector.js +185 -0
  48. package/lib/permitted-contents/order.d.ts +13 -0
  49. package/lib/permitted-contents/order.js +89 -0
  50. package/lib/permitted-contents/recursive-branch.d.ts +4 -0
  51. package/lib/permitted-contents/recursive-branch.js +43 -0
  52. package/lib/permitted-contents/represent-transparent-nodes.d.ts +6 -0
  53. package/lib/permitted-contents/represent-transparent-nodes.js +79 -0
  54. package/lib/permitted-contents/start.d.ts +12 -0
  55. package/lib/permitted-contents/start.js +71 -0
  56. package/lib/permitted-contents/transparent.d.ts +2 -0
  57. package/lib/permitted-contents/transparent.js +34 -0
  58. package/lib/permitted-contents/types.d.ts +45 -0
  59. package/lib/permitted-contents/types.js +2 -0
  60. package/lib/permitted-contents/utils.d.ts +32 -0
  61. package/lib/permitted-contents/utils.js +184 -0
  62. package/lib/require-accessible-name/index.d.ts +5 -1
  63. package/lib/require-accessible-name/index.js +11 -4
  64. package/lib/required-attr/index.js +16 -25
  65. package/lib/required-element/index.d.ts +1 -1
  66. package/lib/required-element/index.js +6 -6
  67. package/lib/required-h1/index.d.ts +2 -2
  68. package/lib/required-h1/index.js +3 -3
  69. package/lib/use-list/index.js +2 -2
  70. package/lib/wai-aria/checkings/abstract-role.d.ts +3 -0
  71. package/lib/wai-aria/checkings/abstract-role.js +22 -0
  72. package/lib/wai-aria/checkings/default-value.d.ts +6 -0
  73. package/lib/wai-aria/checkings/default-value.js +17 -0
  74. package/lib/wai-aria/checkings/deprecated-props.d.ts +7 -0
  75. package/lib/wai-aria/checkings/deprecated-props.js +18 -0
  76. package/lib/wai-aria/checkings/disallowed-prop.d.ts +7 -0
  77. package/lib/wai-aria/checkings/disallowed-prop.js +22 -0
  78. package/lib/wai-aria/checkings/implicit-props.d.ts +7 -0
  79. package/lib/wai-aria/checkings/implicit-props.js +50 -0
  80. package/lib/wai-aria/checkings/implicit-role.d.ts +3 -0
  81. package/lib/wai-aria/checkings/implicit-role.js +21 -0
  82. package/lib/wai-aria/checkings/interaction-in-hidden.d.ts +11 -0
  83. package/lib/wai-aria/checkings/interaction-in-hidden.js +47 -0
  84. package/lib/wai-aria/checkings/no-global-prop.d.ts +6 -0
  85. package/lib/wai-aria/checkings/no-global-prop.js +14 -0
  86. package/lib/wai-aria/checkings/non-existant-role.d.ts +3 -0
  87. package/lib/wai-aria/checkings/non-existant-role.js +28 -0
  88. package/lib/wai-aria/checkings/permitted-roles.d.ts +3 -0
  89. package/lib/wai-aria/checkings/permitted-roles.js +28 -0
  90. package/lib/wai-aria/checkings/presentational-children.d.ts +29 -0
  91. package/lib/wai-aria/checkings/presentational-children.js +60 -0
  92. package/lib/wai-aria/checkings/required-owned-elements.d.ts +11 -0
  93. package/lib/wai-aria/checkings/required-owned-elements.js +63 -0
  94. package/lib/wai-aria/checkings/required-prop.d.ts +9 -0
  95. package/lib/wai-aria/checkings/required-prop.js +27 -0
  96. package/lib/wai-aria/checkings/value.d.ts +7 -0
  97. package/lib/wai-aria/checkings/value.js +21 -0
  98. package/lib/wai-aria/index.d.ts +1 -8
  99. package/lib/wai-aria/index.js +66 -207
  100. package/lib/wai-aria/types.d.ts +13 -0
  101. package/lib/wai-aria/types.js +2 -0
  102. package/package.json +8 -7
  103. package/schema.json +0 -12
  104. package/tsconfig.tsbuildinfo +1 -1
  105. package/lib/attr-equal-space-after/index.d.ts +0 -3
  106. package/lib/attr-equal-space-after/index.js +0 -90
  107. package/lib/attr-equal-space-before/index.d.ts +0 -3
  108. package/lib/attr-equal-space-before/index.js +0 -90
  109. package/lib/attr-spacing/index.d.ts +0 -6
  110. package/lib/attr-spacing/index.js +0 -100
  111. package/lib/indentation/index.d.ts +0 -7
  112. package/lib/indentation/index.js +0 -208
  113. package/lib/permitted-contents/array.combination.d.ts +0 -1
  114. package/lib/permitted-contents/array.combination.js +0 -33
  115. package/lib/permitted-contents/permitted-content.spec-to-regexp.d.ts +0 -11
  116. package/lib/permitted-contents/permitted-content.spec-to-regexp.js +0 -225
  117. package/lib/permitted-contents/unfold-content-models-to-tags.d.ts +0 -2
  118. package/lib/permitted-contents/unfold-content-models-to-tags.js +0 -8
@@ -4,16 +4,16 @@ const ml_core_1 = require("@markuplint/ml-core");
4
4
  exports.default = (0, ml_core_1.createRule)({
5
5
  defaultValue: 'always',
6
6
  defaultOptions: {
7
- denyObsolateType: true,
7
+ denyObsoleteType: true,
8
8
  },
9
- verify(context) {
10
- if (context.document.isFragment) {
9
+ verify({ document, report, t }) {
10
+ if (document.isFragment) {
11
11
  return;
12
12
  }
13
- const doctype = context.document.doctype;
13
+ const doctype = document.doctype;
14
14
  if (!doctype) {
15
- context.report({
16
- message: context.translate('Require {0}', 'doctype'),
15
+ report({
16
+ message: t('Require {0}', 'doctype'),
17
17
  line: 1,
18
18
  col: 1,
19
19
  raw: '',
@@ -21,9 +21,9 @@ exports.default = (0, ml_core_1.createRule)({
21
21
  return;
22
22
  }
23
23
  if ((doctype.name.toLowerCase() === 'html' && doctype.publicId) || doctype.systemId) {
24
- context.report({
24
+ report({
25
25
  scope: doctype,
26
- message: context.translate('Never {0} {1}', 'declarate', 'obsolete doctype'),
26
+ message: t('Never {0} {1}', 'declarate', 'obsolete doctype'),
27
27
  });
28
28
  }
29
29
  },
@@ -18,14 +18,17 @@ const voidElements = [
18
18
  'wbr',
19
19
  ];
20
20
  exports.default = (0, ml_core_1.createRule)({
21
- defaultServerity: 'warning',
21
+ defaultSeverity: 'warning',
22
22
  async verify({ document, report, t }) {
23
23
  if (document.endTag === 'never') {
24
24
  return;
25
25
  }
26
26
  await document.walkOn('Element', el => {
27
27
  var _a;
28
- if (voidElements.some(vE => vE === el.nodeName.toLowerCase())) {
28
+ if (el.isOmitted) {
29
+ return;
30
+ }
31
+ if (voidElements.some(vE => vE === el.localName)) {
29
32
  return;
30
33
  }
31
34
  if (el.closeTag != null) {
package/lib/helpers.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { Log } from './debug';
2
2
  import type { Translator } from '@markuplint/i18n';
3
3
  import type { Element, RuleConfigValue, Document } from '@markuplint/ml-core';
4
- import type { ARIRRoleAttribute, Attribute, MLMLSpec, PermittedRoles } from '@markuplint/ml-spec';
4
+ import type { ARIAVersion, Attribute, MLMLSpec } from '@markuplint/ml-spec';
5
5
  export declare function attrMatches<T extends RuleConfigValue, R>(node: Element<T, R>, condition: Attribute['condition']): boolean;
6
6
  export declare function match(needle: string, pattern: string): boolean;
7
7
  /**
@@ -20,7 +20,6 @@ export declare function match(needle: string, pattern: string): boolean;
20
20
  * Originally, it is not possible to define a name including ASCII upper alphas in the custom element, but it is not treated as illegal by the HTML parser.
21
21
  */
22
22
  export declare const rePCENChar: string;
23
- export declare function htmlSpec(specs: Readonly<MLMLSpec>, nameWithNS: string): import("@markuplint/ml-spec").ElementSpec | null;
24
23
  export declare function isValidAttr(t: Translator, name: string, value: string, isDynamicValue: boolean, node: Element<any, any>, attrSpecs: Attribute[], log?: Log): false | {
25
24
  invalidType: "non-existent" | "invalid-value";
26
25
  message: string;
@@ -31,30 +30,6 @@ export declare function isValidAttr(t: Translator, name: string, value: string,
31
30
  } | undefined;
32
31
  };
33
32
  export declare function toNormalizedValue(value: string, spec: Attribute): string;
34
- export declare function ariaSpec(specs: Readonly<MLMLSpec>): {
35
- roles: ARIRRoleAttribute[];
36
- ariaAttrs: import("@markuplint/ml-spec").ARIAAttribute[];
37
- };
38
- export declare function getRoleSpec(specs: Readonly<MLMLSpec>, roleName: string): {
39
- name: string;
40
- isAbstract: boolean;
41
- accessibleNameRequired: boolean;
42
- statesAndProps: import("@markuplint/ml-spec").ARIARoleOwnedPropOrState[];
43
- superClassRoles: ARIRRoleAttribute[];
44
- } | null;
45
- /**
46
- * Getting permitted ARIA roles.
47
- *
48
- * - If an array, it is role list.
49
- * - If `true`, this mean is "Any".
50
- * - If `false`, this mean is "No".
51
- */
52
- export declare function getPermittedRoles(specs: Readonly<MLMLSpec>, el: Element<any, any>): PermittedRoles;
53
- export declare function getImplicitRole(specs: Readonly<MLMLSpec>, el: Element<any, any>): string | false;
54
- export declare function getComputedRole(specs: Readonly<MLMLSpec>, el: Element<any, any>): {
55
- name: string;
56
- isImplicit: boolean;
57
- } | null;
58
33
  /**
59
34
  *
60
35
  * @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
@@ -64,7 +39,7 @@ export declare function getComputedRole(specs: Readonly<MLMLSpec>, el: Element<a
64
39
  * @param tokenEnum
65
40
  */
66
41
  export declare function checkAriaValue(type: string, value: string, tokenEnum: string[]): boolean;
67
- export declare function checkAria(specs: Readonly<MLMLSpec>, attrName: string, currentValue: string, role?: string): {
42
+ export declare function checkAria(specs: Readonly<MLMLSpec>, attrName: string, currentValue: string, version: ARIAVersion, role?: string): {
68
43
  currentValue: string;
69
44
  isValid: boolean;
70
45
  } | {
@@ -85,5 +60,17 @@ export declare function checkAria(specs: Readonly<MLMLSpec>, attrName: string, c
85
60
  valueDescriptions?: Record<string, string> | undefined;
86
61
  };
87
62
  export declare function accnameMayBeMutable(el: Element<any, any>, document: Document<any, any>): boolean;
88
- export declare function getOwnedLabel<V extends RuleConfigValue, O>(el: Element<V, O>, docuemnt: Document<V, O>): import("packages/@markuplint/ml-core/lib/ml-dom/tokens/abstract-element").default<V, O, import("packages/@markuplint/ml-ast/src").MLASTElement | import("packages/@markuplint/ml-ast/src").MLASTOmittedElement> | null;
63
+ export declare function getOwnedLabel<V extends RuleConfigValue, O>(el: Element<V, O>, document: Document<V, O>): Element<V, O> | null;
89
64
  export declare function decodeCharRef(characterReference: string): string;
65
+ export declare class Collection<T> {
66
+ #private;
67
+ constructor(...items: (T | null | undefined)[]);
68
+ [Symbol.iterator](): Iterator<T>;
69
+ add(...items: (T | null | undefined)[]): void;
70
+ toArray(): readonly T[];
71
+ }
72
+ declare type Writeable<T> = {
73
+ -readonly [P in keyof T]: T[P];
74
+ };
75
+ export declare function deepCopy<T>(value: T): Writeable<T>;
76
+ export {};
package/lib/helpers.js CHANGED
@@ -1,33 +1,19 @@
1
1
  "use strict";
2
+ var _Collection_items;
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.decodeCharRef = exports.getOwnedLabel = exports.accnameMayBeMutable = exports.checkAria = exports.checkAriaValue = exports.getComputedRole = exports.getImplicitRole = exports.getPermittedRoles = exports.getRoleSpec = exports.ariaSpec = exports.toNormalizedValue = exports.isValidAttr = exports.htmlSpec = exports.rePCENChar = exports.match = exports.attrMatches = void 0;
4
+ exports.deepCopy = exports.Collection = exports.decodeCharRef = exports.getOwnedLabel = exports.accnameMayBeMutable = exports.checkAria = exports.checkAriaValue = exports.toNormalizedValue = exports.isValidAttr = exports.rePCENChar = exports.match = exports.attrMatches = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const ml_core_1 = require("@markuplint/ml-core");
7
+ // @ts-ignore
8
+ const structured_clone_1 = tslib_1.__importDefault(require("@ungap/structured-clone"));
4
9
  const html_entities_1 = require("html-entities");
5
10
  const attr_check_1 = require("./attr-check");
6
11
  function attrMatches(node, condition) {
7
12
  if (!condition) {
8
13
  return true;
9
14
  }
10
- let matched = false;
11
- if ('self' in condition && condition.self) {
12
- const condSelector = Array.isArray(condition.self) ? condition.self.join(',') : condition.self;
13
- matched = node.matches(condSelector);
14
- }
15
- if ('ancestor' in condition && condition.ancestor) {
16
- let _node = node.parentNode;
17
- while (_node) {
18
- if (_node.type === 'Element') {
19
- const condSelector = Array.isArray(condition.ancestor)
20
- ? condition.ancestor.join(',')
21
- : condition.ancestor;
22
- if (_node.matches(condSelector)) {
23
- matched = true;
24
- break;
25
- }
26
- }
27
- _node = _node.parentNode;
28
- }
29
- }
30
- return matched;
15
+ const condSelector = Array.isArray(condition) ? condition.join(',') : condition;
16
+ return node.matches(condSelector);
31
17
  }
32
18
  exports.attrMatches = attrMatches;
33
19
  function match(needle, pattern) {
@@ -75,11 +61,6 @@ exports.rePCENChar = [
75
61
  '[\uFDF0-\uFFFD]',
76
62
  '[\uD800-\uDBFF][\uDC00-\uDFFF]',
77
63
  ].join('|');
78
- function htmlSpec(specs, nameWithNS) {
79
- const spec = specs.specs.find(spec => spec.name === nameWithNS);
80
- return spec || null;
81
- }
82
- exports.htmlSpec = htmlSpec;
83
64
  function isValidAttr(t, name, value, isDynamicValue, node, attrSpecs, log) {
84
65
  let invalid = false;
85
66
  const spec = attrSpecs.find(s => s.name.toLowerCase() === name.toLowerCase());
@@ -126,126 +107,6 @@ function toNormalizedValue(value, spec) {
126
107
  return normalized;
127
108
  }
128
109
  exports.toNormalizedValue = toNormalizedValue;
129
- function ariaSpec(specs) {
130
- const roles = specs.def['#roles'];
131
- const ariaAttrs = specs.def['#ariaAttrs'];
132
- return {
133
- roles,
134
- ariaAttrs,
135
- };
136
- }
137
- exports.ariaSpec = ariaSpec;
138
- function getRoleSpec(specs, roleName) {
139
- const role = getRoleByName(specs, roleName);
140
- if (!role) {
141
- return null;
142
- }
143
- const superClassRoles = recursiveTraverseSuperClassRoles(specs, roleName);
144
- return {
145
- name: role.name,
146
- isAbstract: !!role.isAbstract,
147
- accessibleNameRequired: role.accessibleNameRequired,
148
- statesAndProps: role.ownedAttribute,
149
- superClassRoles,
150
- };
151
- }
152
- exports.getRoleSpec = getRoleSpec;
153
- function getRoleByName(specs, roleName) {
154
- const roles = specs.def['#roles'];
155
- const role = roles.find(r => r.name === roleName);
156
- return role;
157
- }
158
- function getSuperClassRoles(specs, roleName) {
159
- const role = getRoleByName(specs, roleName);
160
- return ((role === null || role === void 0 ? void 0 : role.generalization.map(roleName => getRoleByName(specs, roleName)).filter((role) => !!role)) || null);
161
- }
162
- function recursiveTraverseSuperClassRoles(specs, roleName) {
163
- const roles = [];
164
- const superClassRoles = getSuperClassRoles(specs, roleName);
165
- if (superClassRoles) {
166
- roles.push(...superClassRoles);
167
- for (const superClassRole of superClassRoles) {
168
- const ancestorRoles = recursiveTraverseSuperClassRoles(specs, superClassRole.name);
169
- roles.push(...ancestorRoles);
170
- }
171
- }
172
- return roles;
173
- }
174
- /**
175
- * Getting permitted ARIA roles.
176
- *
177
- * - If an array, it is role list.
178
- * - If `true`, this mean is "Any".
179
- * - If `false`, this mean is "No".
180
- */
181
- function getPermittedRoles(specs, el) {
182
- var _a;
183
- const implicitRole = getImplicitRole(specs, el);
184
- const spec = (_a = htmlSpec(specs, el.nodeName)) === null || _a === void 0 ? void 0 : _a.permittedRoles;
185
- if (!spec) {
186
- return true;
187
- }
188
- if (spec.conditions) {
189
- for (const { condition, roles } of spec.conditions) {
190
- if (el.matches(condition)) {
191
- return mergeRoleList(implicitRole, roles);
192
- }
193
- }
194
- }
195
- if (implicitRole && Array.isArray(spec.roles)) {
196
- return [implicitRole, ...spec.roles];
197
- }
198
- if (implicitRole && spec.roles === false) {
199
- return [implicitRole];
200
- }
201
- return mergeRoleList(implicitRole, spec.roles);
202
- }
203
- exports.getPermittedRoles = getPermittedRoles;
204
- function mergeRoleList(implicitRole, permittedRoles) {
205
- if (implicitRole && Array.isArray(permittedRoles)) {
206
- return [implicitRole, ...permittedRoles];
207
- }
208
- if (implicitRole && permittedRoles === false) {
209
- return [implicitRole];
210
- }
211
- return permittedRoles;
212
- }
213
- function getImplicitRole(specs, el) {
214
- var _a;
215
- const implicitRole = (_a = htmlSpec(specs, el.nodeName)) === null || _a === void 0 ? void 0 : _a.implicitRole;
216
- if (!implicitRole) {
217
- return false;
218
- }
219
- if (implicitRole.conditions) {
220
- for (const { condition, role } of implicitRole.conditions) {
221
- if (el.matches(condition)) {
222
- return role;
223
- }
224
- }
225
- }
226
- return implicitRole.role;
227
- }
228
- exports.getImplicitRole = getImplicitRole;
229
- function getComputedRole(specs, el) {
230
- const roleAttrTokens = el.getAttributeToken('role');
231
- const roleAttr = roleAttrTokens[0];
232
- if (roleAttr) {
233
- const roleName = roleAttr.getValue().potential.trim().toLowerCase();
234
- return {
235
- name: roleName,
236
- isImplicit: false,
237
- };
238
- }
239
- const implicitRole = getImplicitRole(specs, el);
240
- if (implicitRole) {
241
- return {
242
- name: implicitRole,
243
- isImplicit: true,
244
- };
245
- }
246
- return null;
247
- }
248
- exports.getComputedRole = getComputedRole;
249
110
  /**
250
111
  *
251
112
  * @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
@@ -288,8 +149,8 @@ function checkAriaValue(type, value, tokenEnum) {
288
149
  return true;
289
150
  }
290
151
  exports.checkAriaValue = checkAriaValue;
291
- function checkAria(specs, attrName, currentValue, role) {
292
- const ariaAttrs = specs.def['#ariaAttrs'];
152
+ function checkAria(specs, attrName, currentValue, version, role) {
153
+ const ariaAttrs = (0, ml_core_1.ariaSpecs)(specs, version).props;
293
154
  const aria = ariaAttrs.find(a => a.name === attrName);
294
155
  if (!aria) {
295
156
  return {
@@ -319,29 +180,54 @@ function accnameMayBeMutable(el, document) {
319
180
  if (el.hasMutableAttributes() || el.hasMutableChildren(true)) {
320
181
  return true;
321
182
  }
322
- const ownedLable = getOwnedLabel(el, document);
323
- if (ownedLable && (ownedLable.hasMutableAttributes() || ownedLable.hasMutableChildren(true))) {
183
+ const ownedLabel = getOwnedLabel(el, document);
184
+ if (ownedLabel && (ownedLabel.hasMutableAttributes() || ownedLabel.hasMutableChildren(true))) {
324
185
  return true;
325
186
  }
326
187
  return false;
327
188
  }
328
189
  exports.accnameMayBeMutable = accnameMayBeMutable;
329
190
  const labelable = ['button', 'input:not([type=hidden])', 'meter', 'output', 'progress', 'select', 'textarea'];
330
- function getOwnedLabel(el, docuemnt) {
191
+ function getOwnedLabel(el, document) {
331
192
  if (!labelable.some(cond => el.matches(cond))) {
332
193
  return null;
333
194
  }
334
- let ownedLable = el.closest('label');
335
- if (!ownedLable) {
195
+ let ownedLabel = el.closest('label');
196
+ if (!ownedLabel) {
336
197
  const id = el.getAttribute('id');
337
198
  if (id) {
338
- ownedLable = docuemnt.querySelector(`label[for="${id}"]`);
199
+ ownedLabel = document.querySelector(`label[for="${id}"]`);
339
200
  }
340
201
  }
341
- return ownedLable;
202
+ return ownedLabel;
342
203
  }
343
204
  exports.getOwnedLabel = getOwnedLabel;
344
205
  function decodeCharRef(characterReference) {
345
206
  return (0, html_entities_1.decode)(characterReference);
346
207
  }
347
208
  exports.decodeCharRef = decodeCharRef;
209
+ class Collection {
210
+ constructor(...items) {
211
+ _Collection_items.set(this, new Set());
212
+ this.add(...items);
213
+ }
214
+ [(_Collection_items = new WeakMap(), Symbol.iterator)]() {
215
+ return tslib_1.__classPrivateFieldGet(this, _Collection_items, "f").values();
216
+ }
217
+ add(...items) {
218
+ for (const item of items) {
219
+ if (item == null) {
220
+ continue;
221
+ }
222
+ tslib_1.__classPrivateFieldGet(this, _Collection_items, "f").add(item);
223
+ }
224
+ }
225
+ toArray() {
226
+ return Object.freeze(Array.from(tslib_1.__classPrivateFieldGet(this, _Collection_items, "f")));
227
+ }
228
+ }
229
+ exports.Collection = Collection;
230
+ function deepCopy(value) {
231
+ return (0, structured_clone_1.default)(value);
232
+ }
233
+ exports.deepCopy = deepCopy;
@@ -8,13 +8,11 @@ exports.default = (0, ml_core_1.createRule)({
8
8
  await document.walkOn('Element', node => {
9
9
  const idAttrs = node.getAttributeToken('id');
10
10
  for (const idAttr of idAttrs) {
11
- if (idAttr.attrType === 'ps-attr' ||
12
- (idAttr.attrType === 'html-attr' && idAttr.isDynamicValue) ||
13
- (idAttr.attrType === 'html-attr' && idAttr.isDirective)) {
11
+ if (idAttr.isDynamicValue || idAttr.isDirective) {
14
12
  continue;
15
13
  }
16
- const id = idAttr.getValue();
17
- if (idStack.includes(id.raw)) {
14
+ const id = idAttr.value;
15
+ if (idStack.includes(id)) {
18
16
  report({
19
17
  scope: node,
20
18
  message,
@@ -23,7 +21,7 @@ exports.default = (0, ml_core_1.createRule)({
23
21
  raw: idAttr.raw,
24
22
  });
25
23
  }
26
- idStack.push(id.raw);
24
+ idStack.push(id);
27
25
  }
28
26
  });
29
27
  },
package/lib/index.d.ts CHANGED
@@ -1,10 +1,7 @@
1
1
  declare const _default: {
2
2
  'attr-duplication': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
3
- 'attr-equal-space-after': import("packages/@markuplint/ml-core/lib").RuleSeed<"always" | "never" | "always-single-line" | "never-single-line", null>;
4
- 'attr-equal-space-before': import("packages/@markuplint/ml-core/lib").RuleSeed<"always" | "never" | "always-single-line" | "never-single-line", null>;
5
- 'attr-spacing': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, import("./attr-spacing").AttrSpasingOptions>;
6
3
  'attr-value-quotes': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./attr-value-quotes").Type, null>;
7
- 'case-sensitive-attr-name': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./case-sensitive-attr-name").Value | import("./case-sensitive-attr-name").Value_v1, null>;
4
+ 'case-sensitive-attr-name': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./case-sensitive-attr-name").Value, null>;
8
5
  'case-sensitive-tag-name': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./case-sensitive-tag-name").Value, null>;
9
6
  'character-reference': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
10
7
  'class-naming': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./class-naming").Value, null>;
@@ -12,11 +9,10 @@ declare const _default: {
12
9
  'deprecated-element': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
13
10
  'disallowed-element': import("packages/@markuplint/ml-core/lib").RuleSeed<string[], null>;
14
11
  doctype: import("packages/@markuplint/ml-core/lib").RuleSeed<"always", {
15
- denyObsolateType: boolean;
12
+ denyObsoleteType: boolean;
16
13
  }>;
17
14
  'end-tag': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, null>;
18
15
  'id-duplication': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
19
- indentation: import("packages/@markuplint/ml-core/lib").RuleSeed<import("./indentation").Value, import("./indentation").IndentationOptions>;
20
16
  'ineffective-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
21
17
  'invalid-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
22
18
  attrs?: Record<string, {
@@ -31,38 +27,33 @@ declare const _default: {
31
27
  ignoreAttrNamePrefix?: string | string[] | undefined;
32
28
  }>;
33
29
  'landmark-roles': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
34
- ignoreRoles?: (("banner" | "main" | "complementary" | "contentinfo") | "form" | "navigation" | "region")[] | undefined;
35
- labelEachArea?: boolean | undefined;
30
+ ignoreRoles: (("banner" | "main" | "complementary" | "contentinfo") | "form" | "navigation" | "region")[];
31
+ labelEachArea: boolean;
36
32
  }>;
37
33
  'no-boolean-attr-value': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
38
34
  'no-default-value': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
39
35
  'no-hard-code-id': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
40
- 'no-refer-to-non-existent-id': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
36
+ 'no-refer-to-non-existent-id': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, {
37
+ ariaVersion: import("packages/@markuplint/ml-spec/lib").ARIAVersion;
38
+ }>;
41
39
  'no-use-event-handler-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
42
40
  ignore?: string | string[] | undefined;
43
41
  }>;
44
- 'permitted-contents': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-spec/lib").PermittedStructuresSchema[], {
45
- ignoreHasMutableChildren: boolean;
42
+ 'permitted-contents': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./permitted-contents/types").TagRule[], import("./permitted-contents/types").Options>;
43
+ 'require-accessible-name': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
44
+ ariaVersion: import("packages/@markuplint/ml-spec/lib").ARIAVersion;
46
45
  }>;
47
- 'require-accessible-name': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, null>;
48
46
  'required-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<string | (string | {
49
47
  name: string;
50
48
  value: string | string[];
51
49
  })[], null>;
52
50
  'required-element': import("packages/@markuplint/ml-core/lib").RuleSeed<string[], {
53
- ignoreHasMutableContents?: boolean | undefined;
51
+ ignoreHasMutableContents: boolean;
54
52
  }>;
55
53
  'required-h1': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, import("./required-h1").Options>;
56
54
  'use-list': import("packages/@markuplint/ml-core/lib").RuleSeed<string[], {
57
55
  spaceNeededBullets?: string[] | undefined;
58
56
  }>;
59
- 'wai-aria': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
60
- checkingValue?: boolean | undefined;
61
- checkingDeprecatedProps?: boolean | undefined;
62
- permittedAriaRoles?: boolean | undefined;
63
- disallowSetImplicitRole?: boolean | undefined;
64
- disallowSetImplicitProps?: boolean | undefined;
65
- disallowDefaultValue?: boolean | undefined;
66
- }>;
57
+ 'wai-aria': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, import("./wai-aria/types").Options>;
67
58
  };
68
59
  export default _default;
package/lib/index.js CHANGED
@@ -2,9 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const attr_duplication_1 = tslib_1.__importDefault(require("./attr-duplication"));
5
- const attr_equal_space_after_1 = tslib_1.__importDefault(require("./attr-equal-space-after"));
6
- const attr_equal_space_before_1 = tslib_1.__importDefault(require("./attr-equal-space-before"));
7
- const attr_spacing_1 = tslib_1.__importDefault(require("./attr-spacing"));
8
5
  const attr_value_quotes_1 = tslib_1.__importDefault(require("./attr-value-quotes"));
9
6
  const case_sensitive_attr_name_1 = tslib_1.__importDefault(require("./case-sensitive-attr-name"));
10
7
  const case_sensitive_tag_name_1 = tslib_1.__importDefault(require("./case-sensitive-tag-name"));
@@ -16,7 +13,6 @@ const disallowed_element_1 = tslib_1.__importDefault(require("./disallowed-eleme
16
13
  const doctype_1 = tslib_1.__importDefault(require("./doctype"));
17
14
  const end_tag_1 = tslib_1.__importDefault(require("./end-tag"));
18
15
  const id_duplication_1 = tslib_1.__importDefault(require("./id-duplication"));
19
- const indentation_1 = tslib_1.__importDefault(require("./indentation"));
20
16
  const ineffective_attr_1 = tslib_1.__importDefault(require("./ineffective-attr"));
21
17
  const invalid_attr_1 = tslib_1.__importDefault(require("./invalid-attr"));
22
18
  const landmark_roles_1 = tslib_1.__importDefault(require("./landmark-roles"));
@@ -34,9 +30,6 @@ const use_list_1 = tslib_1.__importDefault(require("./use-list"));
34
30
  const wai_aria_1 = tslib_1.__importDefault(require("./wai-aria"));
35
31
  exports.default = {
36
32
  'attr-duplication': attr_duplication_1.default,
37
- 'attr-equal-space-after': attr_equal_space_after_1.default,
38
- 'attr-equal-space-before': attr_equal_space_before_1.default,
39
- 'attr-spacing': attr_spacing_1.default,
40
33
  'attr-value-quotes': attr_value_quotes_1.default,
41
34
  'case-sensitive-attr-name': case_sensitive_attr_name_1.default,
42
35
  'case-sensitive-tag-name': case_sensitive_tag_name_1.default,
@@ -48,7 +41,6 @@ exports.default = {
48
41
  doctype: doctype_1.default,
49
42
  'end-tag': end_tag_1.default,
50
43
  'id-duplication': id_duplication_1.default,
51
- indentation: indentation_1.default,
52
44
  'ineffective-attr': ineffective_attr_1.default,
53
45
  'invalid-attr': invalid_attr_1.default,
54
46
  'landmark-roles': landmark_roles_1.default,
@@ -2,38 +2,30 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ml_core_1 = require("@markuplint/ml-core");
4
4
  exports.default = (0, ml_core_1.createRule)({
5
- defaultServerity: 'warning',
5
+ defaultSeverity: 'warning',
6
6
  async verify({ document, report, t }) {
7
- await document.walkOn('Element', el => {
8
- const attrSpec = (0, ml_core_1.getAttrSpecs)(el.nameWithNS, document.specs);
7
+ await document.walkOn('Attr', attr => {
8
+ const attrSpec = (0, ml_core_1.getAttrSpecs)(attr.ownerElement, document.specs);
9
9
  if (!attrSpec) {
10
10
  return;
11
11
  }
12
- for (const attr of el.attributes) {
13
- if (attr.attrType === 'ps-attr') {
14
- continue;
15
- }
16
- const name = attr.getName().potential;
17
- const spec = attrSpec.find(s => s.name === name);
18
- if (!spec) {
19
- continue;
20
- }
21
- const ineffectiveConditions = spec.ineffective
22
- ? Array.isArray(spec.ineffective)
23
- ? spec.ineffective
24
- : [spec.ineffective]
25
- : [];
26
- if (ineffectiveConditions.some(selector => el.matches(selector))) {
27
- report({
28
- scope: el,
29
- raw: attr.raw,
30
- line: attr.startLine,
31
- col: attr.startCol,
32
- message: t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'ineffective') +
33
- t('. ') +
34
- t("It doesn't need {0}", t('the {0}', 'attribute')),
35
- });
36
- }
12
+ const name = attr.name;
13
+ const spec = attrSpec.find(s => s.name === name);
14
+ if (!spec) {
15
+ return;
16
+ }
17
+ const ineffectiveConditions = spec.ineffective
18
+ ? Array.isArray(spec.ineffective)
19
+ ? spec.ineffective
20
+ : [spec.ineffective]
21
+ : [];
22
+ if (ineffectiveConditions.some(selector => attr.ownerElement.matches(selector))) {
23
+ report({
24
+ scope: attr,
25
+ message: t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'ineffective') +
26
+ t('. ') +
27
+ t("It doesn't need {0}", t('the {0}', 'attribute')),
28
+ });
37
29
  }
38
30
  });
39
31
  },