@markuplint/rules 2.4.0 → 3.0.0-alpha.66

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 (97) hide show
  1. package/README.md +1 -5
  2. package/lib/__foo/index.d.ts +1 -1
  3. package/lib/attr-duplication/index.js +11 -8
  4. package/lib/attr-equal-space-after/index.d.ts +1 -1
  5. package/lib/attr-equal-space-after/index.js +2 -2
  6. package/lib/attr-equal-space-before/index.d.ts +1 -1
  7. package/lib/attr-equal-space-before/index.js +2 -2
  8. package/lib/attr-spacing/index.d.ts +3 -3
  9. package/lib/attr-spacing/index.js +2 -2
  10. package/lib/attr-value-quotes/index.js +21 -25
  11. package/lib/case-sensitive-attr-name/index.d.ts +1 -5
  12. package/lib/case-sensitive-attr-name/index.js +51 -81
  13. package/lib/case-sensitive-tag-name/index.js +38 -30
  14. package/lib/character-reference/index.d.ts +2 -1
  15. package/lib/character-reference/index.js +7 -9
  16. package/lib/class-naming/index.js +11 -11
  17. package/lib/deprecated-attr/index.js +17 -18
  18. package/lib/deprecated-element/index.js +6 -8
  19. package/lib/disallowed-element/index.js +8 -9
  20. package/lib/doctype/index.js +7 -7
  21. package/lib/end-tag/index.js +4 -1
  22. package/lib/helper/aria/get-aria.d.ts +7 -0
  23. package/lib/helper/aria/get-aria.js +53 -0
  24. package/lib/helper/aria/get-computed-role.d.ts +10 -0
  25. package/lib/helper/aria/get-computed-role.js +24 -0
  26. package/lib/helper/aria/get-implicit-role.d.ts +7 -0
  27. package/lib/helper/aria/get-implicit-role.js +12 -0
  28. package/lib/helper/aria/get-permitted-roles.d.ts +14 -0
  29. package/lib/helper/aria/get-permitted-roles.js +26 -0
  30. package/lib/helper/aria/resolve-version.d.ts +2 -0
  31. package/lib/helper/aria/resolve-version.js +21 -0
  32. package/lib/helper/spec/aria-spec.d.ts +5 -0
  33. package/lib/helper/spec/aria-spec.js +12 -0
  34. package/lib/helper/spec/get-role-spec.d.ts +11 -0
  35. package/lib/helper/spec/get-role-spec.js +39 -0
  36. package/lib/helper/spec/html-spec.d.ts +2 -0
  37. package/lib/helper/spec/html-spec.js +14 -0
  38. package/lib/helpers.d.ts +10 -28
  39. package/lib/helpers.js +29 -149
  40. package/lib/id-duplication/index.js +5 -7
  41. package/lib/indentation/index.d.ts +3 -3
  42. package/lib/indentation/index.js +4 -4
  43. package/lib/index.d.ts +14 -19
  44. package/lib/index.js +0 -8
  45. package/lib/ineffective-attr/index.js +19 -27
  46. package/lib/invalid-attr/index.js +83 -83
  47. package/lib/landmark-roles/index.d.ts +2 -2
  48. package/lib/landmark-roles/index.js +10 -10
  49. package/lib/no-boolean-attr-value/index.js +33 -34
  50. package/lib/no-default-value/index.js +20 -24
  51. package/lib/no-hard-code-id/index.js +9 -13
  52. package/lib/no-refer-to-non-existent-id/index.d.ts +4 -1
  53. package/lib/no-refer-to-non-existent-id/index.js +77 -83
  54. package/lib/no-use-event-handler-attr/index.js +20 -22
  55. package/lib/permitted-contents/index.d.ts +5 -2
  56. package/lib/permitted-contents/index.js +67 -68
  57. package/lib/permitted-contents/permitted-content.spec-to-regexp.d.ts +5 -5
  58. package/lib/permitted-contents/permitted-content.spec-to-regexp.js +19 -14
  59. package/lib/permitted-contents/unfold-content-models-to-tags.d.ts +2 -2
  60. package/lib/require-accessible-name/index.d.ts +5 -1
  61. package/lib/require-accessible-name/index.js +6 -3
  62. package/lib/required-attr/index.js +16 -25
  63. package/lib/required-element/index.d.ts +1 -1
  64. package/lib/required-element/index.js +6 -6
  65. package/lib/required-h1/index.d.ts +2 -2
  66. package/lib/required-h1/index.js +4 -4
  67. package/lib/wai-aria/checkings/abstract-role.d.ts +3 -0
  68. package/lib/wai-aria/checkings/abstract-role.js +22 -0
  69. package/lib/wai-aria/checkings/checking-required-owned-elements.d.ts +11 -0
  70. package/lib/wai-aria/checkings/checking-required-owned-elements.js +63 -0
  71. package/lib/wai-aria/checkings/default-value.d.ts +6 -0
  72. package/lib/wai-aria/checkings/default-value.js +17 -0
  73. package/lib/wai-aria/checkings/deprecated-props.d.ts +7 -0
  74. package/lib/wai-aria/checkings/deprecated-props.js +18 -0
  75. package/lib/wai-aria/checkings/disallowed-prop.d.ts +7 -0
  76. package/lib/wai-aria/checkings/disallowed-prop.js +22 -0
  77. package/lib/wai-aria/checkings/implicit-props.d.ts +7 -0
  78. package/lib/wai-aria/checkings/implicit-props.js +50 -0
  79. package/lib/wai-aria/checkings/implicit-role.d.ts +3 -0
  80. package/lib/wai-aria/checkings/implicit-role.js +21 -0
  81. package/lib/wai-aria/checkings/no-global-prop.d.ts +6 -0
  82. package/lib/wai-aria/checkings/no-global-prop.js +14 -0
  83. package/lib/wai-aria/checkings/non-existant-role.d.ts +3 -0
  84. package/lib/wai-aria/checkings/non-existant-role.js +28 -0
  85. package/lib/wai-aria/checkings/permitted-roles.d.ts +3 -0
  86. package/lib/wai-aria/checkings/permitted-roles.js +28 -0
  87. package/lib/wai-aria/checkings/required-prop.d.ts +9 -0
  88. package/lib/wai-aria/checkings/required-prop.js +27 -0
  89. package/lib/wai-aria/checkings/value.d.ts +7 -0
  90. package/lib/wai-aria/checkings/value.js +21 -0
  91. package/lib/wai-aria/index.d.ts +1 -8
  92. package/lib/wai-aria/index.js +56 -207
  93. package/lib/wai-aria/types.d.ts +11 -0
  94. package/lib/wai-aria/types.js +2 -0
  95. package/package.json +5 -5
  96. package/schema.json +0 -12
  97. package/tsconfig.tsbuildinfo +1 -1
@@ -1,20 +1,23 @@
1
1
  "use strict";
2
- var _TagList_list;
2
+ var _ExpGenerator_id, _ExpGenerator_specs, _ExpGenerator_idCounter, _TagList_list;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const tslib_1 = require("tslib");
5
+ const ml_spec_1 = require("@markuplint/ml-spec");
5
6
  const helpers_1 = require("../helpers");
6
7
  const array_combination_1 = tslib_1.__importDefault(require("./array.combination"));
7
- const unfold_content_models_to_tags_1 = tslib_1.__importDefault(require("./unfold-content-models-to-tags"));
8
8
  const ALL = '(?:<[^>]+>)?';
9
9
  const ___TRANSPARENT___ = '___TRANSPARENT___';
10
10
  const ___InTRANSPARENT = '___InTRANSPARENT';
11
11
  const CUSTOM_ELEMENT = `(?:<[a-z](?:${helpers_1.rePCENChar})*\\-(?:${helpers_1.rePCENChar})*>)`;
12
12
  class ExpGenerator {
13
- constructor(_id) {
14
- this._id = _id;
15
- this._idCounter = 0;
13
+ constructor(specs, id) {
14
+ _ExpGenerator_id.set(this, void 0);
15
+ _ExpGenerator_specs.set(this, void 0);
16
+ _ExpGenerator_idCounter.set(this, 0);
17
+ tslib_1.__classPrivateFieldSet(this, _ExpGenerator_id, id, "f");
18
+ tslib_1.__classPrivateFieldSet(this, _ExpGenerator_specs, specs, "f");
16
19
  }
17
- specToRegExp(contentRule, parentExp = null, ownNS = null) {
20
+ specToRegExp(contentRule, parentExp = null, ownNS = 'http://www.w3.org/1999/xhtml') {
18
21
  if (contentRule === true) {
19
22
  return new RegExp(`^(?:${ALL})+$`);
20
23
  }
@@ -22,10 +25,11 @@ class ExpGenerator {
22
25
  return new RegExp('^$');
23
26
  }
24
27
  const parentPattern = parentExp ? parentExp.source.replace(/^\^|\$$/g, '') : ALL;
25
- const pattern = this._toPattern(contentRule, null, ownNS, 1, 1).replace(___TRANSPARENT___, () => `(?<TRANSPARENT_${this._id}${this._idCounter++}>${parentPattern})`);
28
+ const pattern = this._toPattern(contentRule, null, ownNS, 1, 1).replace(___TRANSPARENT___, () => { var _a, _b; return `(?<TRANSPARENT_${tslib_1.__classPrivateFieldGet(this, _ExpGenerator_id, "f")}${tslib_1.__classPrivateFieldSet(this, _ExpGenerator_idCounter, (_b = tslib_1.__classPrivateFieldGet(this, _ExpGenerator_idCounter, "f"), _a = _b++, _b), "f"), _a}>${parentPattern})`; });
26
29
  return new RegExp(`^${pattern}$`, 'i');
27
30
  }
28
31
  _toPattern(contentRule, ignore, ownNS, min, max) {
32
+ var _a, _b;
29
33
  if (isTarget(contentRule)) {
30
34
  return this._targetTags(contentRule, ignore, ownNS, min, max);
31
35
  }
@@ -87,7 +91,7 @@ class ExpGenerator {
87
91
  }
88
92
  const range = createRange(min, max);
89
93
  const c = notAllowedDescendantsNamedCapture
90
- ? `?<NAD_${this._id}${this._idCounter++}_${notAllowedDescendantsNamedCapture}>`
94
+ ? `?<NAD_${tslib_1.__classPrivateFieldGet(this, _ExpGenerator_id, "f")}${tslib_1.__classPrivateFieldSet(this, _ExpGenerator_idCounter, (_b = tslib_1.__classPrivateFieldGet(this, _ExpGenerator_idCounter, "f"), _a = _b++, _b), "f"), _a}_${notAllowedDescendantsNamedCapture}>`
91
95
  : '?:';
92
96
  if (1 === exp.length && range === '') {
93
97
  if (notAllowedDescendantsNamedCapture) {
@@ -117,6 +121,7 @@ class ExpGenerator {
117
121
  return join(Array.from(tagList), createRange(min, max));
118
122
  }
119
123
  _resolveTags(target, ownNS) {
124
+ var _a, _b;
120
125
  const list = Array.isArray(target) ? target : [target];
121
126
  const tagList = new TagList();
122
127
  for (const name of list) {
@@ -131,8 +136,8 @@ class ExpGenerator {
131
136
  break;
132
137
  }
133
138
  default: {
134
- const selectors = (0, unfold_content_models_to_tags_1.default)(name);
135
- const counter = this._idCounter++;
139
+ const selectors = (0, ml_spec_1.contentModelCategoryToTagNames)(name, tslib_1.__classPrivateFieldGet(this, _ExpGenerator_specs, "f"));
140
+ const counter = (tslib_1.__classPrivateFieldSet(this, _ExpGenerator_idCounter, (_b = tslib_1.__classPrivateFieldGet(this, _ExpGenerator_idCounter, "f"), _a = _b++, _b), "f"), _a);
136
141
  selectors.forEach(selector => {
137
142
  if (selector === '#custom') {
138
143
  tagList.addPattern(CUSTOM_ELEMENT);
@@ -141,7 +146,7 @@ class ExpGenerator {
141
146
  if (/]$/i.test(selector)) {
142
147
  const [, tagName] = /^([^[\]]+)\[[^\]]+\]$/.exec(selector) || [];
143
148
  // ACM = Attributes by content model
144
- const exp = `(?<ACM_${this._id}${counter}_${name.slice(1)}_${tagName}><${tagName}>)`;
149
+ const exp = `(?<ACM_${tslib_1.__classPrivateFieldGet(this, _ExpGenerator_id, "f")}${counter}_${name.slice(1)}_${tagName}><${tagName}>)`;
145
150
  tagList.addPattern(exp);
146
151
  return;
147
152
  }
@@ -157,6 +162,7 @@ class ExpGenerator {
157
162
  }
158
163
  }
159
164
  exports.default = ExpGenerator;
165
+ _ExpGenerator_id = new WeakMap(), _ExpGenerator_specs = new WeakMap(), _ExpGenerator_idCounter = new WeakMap();
160
166
  class TagList {
161
167
  constructor() {
162
168
  _TagList_list.set(this, new Set());
@@ -165,9 +171,8 @@ class TagList {
165
171
  tslib_1.__classPrivateFieldGet(this, _TagList_list, "f").add(pattern);
166
172
  }
167
173
  addTag(tagNameOrSelector, ownNS) {
168
- if (ownNS) {
169
- tagNameOrSelector = tagNameOrSelector.replace(new RegExp(`^${ownNS}:`, 'i'), '');
170
- }
174
+ tagNameOrSelector = tagNameOrSelector.replace(/\|/g, ':');
175
+ tagNameOrSelector = tagNameOrSelector.replace(/^html:/i, '');
171
176
  tslib_1.__classPrivateFieldGet(this, _TagList_list, "f").add(`<${tagNameOrSelector}>`);
172
177
  }
173
178
  result() {
@@ -1,2 +1,2 @@
1
- import type { ContentModel } from '@markuplint/ml-spec';
2
- export default function unfoldContentModelsToTags(contentModel: ContentModel): string[];
1
+ import type { Category } from '@markuplint/ml-spec';
2
+ export default function unfoldContentModelsToTags(contentModel: Category): string[];
@@ -1,2 +1,6 @@
1
- declare const _default: import("@markuplint/ml-core").RuleSeed<boolean, null>;
1
+ import type { ARIAVersion } from '@markuplint/ml-spec';
2
+ declare type Option = {
3
+ ariaVersion: ARIAVersion;
4
+ };
5
+ declare const _default: import("@markuplint/ml-core").RuleSeed<boolean, Option>;
2
6
  export default _default;
@@ -3,16 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ml_core_1 = require("@markuplint/ml-core");
4
4
  const helpers_1 = require("../helpers");
5
5
  exports.default = (0, ml_core_1.createRule)({
6
+ defaultOptions: {
7
+ ariaVersion: '1.2',
8
+ },
6
9
  async verify({ document, report, t }) {
7
10
  await document.walkOn('Element', el => {
8
11
  if ((0, helpers_1.accnameMayBeMutable)(el, document)) {
9
12
  return;
10
13
  }
11
- const role = (0, helpers_1.getComputedRole)(document.specs, el);
12
- if (!role) {
14
+ const computed = (0, ml_core_1.getComputedRole)(document.specs, el, el.rule.option.ariaVersion);
15
+ if (!computed.role) {
13
16
  return;
14
17
  }
15
- const roleSpec = (0, helpers_1.getRoleSpec)(document.specs, role.name);
18
+ const roleSpec = (0, ml_core_1.getRoleSpec)(document.specs, computed.role.name, el.namespaceURI, el.rule.option.ariaVersion);
16
19
  if (!roleSpec || !roleSpec.accessibleNameRequired) {
17
20
  return;
18
21
  }
@@ -5,15 +5,14 @@ const helpers_1 = require("../helpers");
5
5
  exports.default = (0, ml_core_1.createRule)({
6
6
  defaultValue: [],
7
7
  async verify({ document, report, t }) {
8
- await document.walkOn('Element', async (node) => {
9
- var _a;
10
- if (node.hasSpreadAttr) {
8
+ await document.walkOn('Element', el => {
9
+ if (el.hasSpreadAttr) {
11
10
  return;
12
11
  }
13
- const customRequiredAttrs = typeof node.rule.value === 'string' ? [node.rule.value] : node.rule.value;
14
- const attrSpec = (0, ml_core_1.getAttrSpecs)(node.nameWithNS, document.specs);
12
+ const customRequiredAttrs = typeof el.rule.value === 'string' ? [el.rule.value] : el.rule.value;
13
+ const attrSpec = (0, ml_core_1.getAttrSpecs)(el, document.specs);
15
14
  const attributeSpecs = {};
16
- if (attrSpec && !node.isCustomElement) {
15
+ if (attrSpec && !el.isCustomElement) {
17
16
  for (const spec of attrSpec) {
18
17
  if (spec.required || spec.requiredEither || spec.condition) {
19
18
  attributeSpecs[spec.name] = {
@@ -45,46 +44,38 @@ exports.default = (0, ml_core_1.createRule)({
45
44
  };
46
45
  }
47
46
  for (const spec of Object.values(attributeSpecs)) {
48
- const didntHave = !node.hasAttribute(spec.name);
47
+ const didntHave = !el.hasAttribute(spec.name);
49
48
  let invalid = false;
50
49
  if (spec.requiredEither) {
51
50
  const candidate = [...spec.requiredEither, spec.name];
52
- invalid = !candidate.some(attrName => node.hasAttribute(attrName));
51
+ invalid = !candidate.some(attrName => el.hasAttribute(attrName));
53
52
  }
54
53
  else if (spec.required === true) {
55
- invalid = (0, helpers_1.attrMatches)(node, spec.condition) && didntHave;
54
+ invalid = (0, helpers_1.attrMatches)(el, spec.condition) && didntHave;
56
55
  }
57
56
  else if (spec.required) {
58
- if ('ancestor' in spec.required && spec.required.ancestor) {
59
- const ancestorList = Array.isArray(spec.required.ancestor)
60
- ? spec.required.ancestor
61
- : [spec.required.ancestor];
62
- const ancestors = ancestorList
63
- .join(',')
64
- .split(',')
65
- .map(a => a.trim());
66
- invalid = ancestors.some(a => node.closest(a)) && didntHave;
67
- }
57
+ const selector = Array.isArray(spec.required) ? spec.required.join(',') : spec.required;
58
+ invalid = el.matches(selector) && didntHave;
68
59
  }
69
60
  if (invalid) {
70
- const message = t('{0} expects {1}', t('the "{0*}" {1}', node.nodeName, 'element'), t('the "{0*}" {1}', spec.name, 'attribute'));
61
+ const message = t('{0} expects {1}', t('the "{0*}" {1}', el.localName, 'element'), t('the "{0*}" {1}', spec.name, 'attribute'));
71
62
  report({
72
- scope: node,
63
+ scope: el,
73
64
  message,
74
65
  });
75
66
  }
76
- const value = node.getAttribute(spec.name);
67
+ const value = el.getAttribute(spec.name);
77
68
  if (spec.values.length && value) {
78
69
  const matched = spec.values.some(pattern => (0, helpers_1.match)(value, pattern));
79
70
  if (!matched) {
80
71
  const expects = spec.values.length === 1 ? t(spec.values) : t('either {0}', t(spec.values));
81
72
  const message = t('{0} expects {1}', t('the "{0*}" {1}', spec.name, 'attribute'), expects);
82
- const attrToken = node.getAttributeToken(spec.name);
83
- const valueToken = ((_a = attrToken[0]) === null || _a === void 0 ? void 0 : _a.attrType) === 'html-attr' ? attrToken[0].valueNode : null;
73
+ const attrToken = el.getAttributeToken(spec.name);
74
+ const valueToken = attrToken[0].valueNode;
84
75
  const token = valueToken || attrToken[0];
85
76
  report({
86
77
  scope: {
87
- rule: node.rule,
78
+ rule: el.rule,
88
79
  raw: token.raw,
89
80
  startCol: token.startCol,
90
81
  startLine: token.startLine,
@@ -1,5 +1,5 @@
1
1
  declare type Options = {
2
- ignoreHasMutableContents?: boolean;
2
+ ignoreHasMutableContents: boolean;
3
3
  };
4
4
  declare const _default: import("@markuplint/ml-core").RuleSeed<string[], Options>;
5
5
  export default _default;
@@ -6,11 +6,11 @@ exports.default = (0, ml_core_1.createRule)({
6
6
  defaultOptions: {
7
7
  ignoreHasMutableContents: true,
8
8
  },
9
- async verify({ document, report, t, globalRule }) {
10
- const hasMutableContent = document.nodeList.some(n => (n.type === 'Element' || n.type === 'OmittedElement') && n.hasMutableChildren());
9
+ async verify({ document, report, t }) {
10
+ const hasMutableContent = document.nodeList.some(n => n.is(n.ELEMENT_NODE) && n.hasMutableChildren());
11
11
  if (!hasMutableContent) {
12
- for (const query of globalRule.value) {
13
- const exists = document.matchNodes(query);
12
+ for (const query of document.rule.value) {
13
+ const exists = document.querySelectorAll(query);
14
14
  if (exists.length === 0) {
15
15
  const message = t('Require {0}', t('the "{0*}" {1}', query, 'element'));
16
16
  report({
@@ -23,14 +23,14 @@ exports.default = (0, ml_core_1.createRule)({
23
23
  }
24
24
  }
25
25
  await document.walkOn('Element', el => {
26
- if (el.rule.value === globalRule.value) {
26
+ if (el.rule.value === document.rule.value) {
27
27
  return;
28
28
  }
29
29
  if (el.rule.option.ignoreHasMutableContents && el.hasMutableChildren()) {
30
30
  return;
31
31
  }
32
32
  for (const query of el.rule.value) {
33
- const exists = el.children.find(child => child.matches(query));
33
+ const exists = Array.from(el.children).find(child => child.matches(query));
34
34
  if (!exists) {
35
35
  const message = t('Require {0}', t('the "{0*}" {1}', query, 'element'));
36
36
  report({
@@ -1,6 +1,6 @@
1
1
  export interface Options {
2
- 'expected-once'?: boolean;
3
- 'in-document-fragment'?: boolean;
2
+ 'expected-once': boolean;
3
+ 'in-document-fragment': boolean;
4
4
  }
5
5
  declare const _default: import("@markuplint/ml-core").RuleSeed<boolean, Options>;
6
6
  export default _default;
@@ -6,15 +6,15 @@ exports.default = (0, ml_core_1.createRule)({
6
6
  'expected-once': true,
7
7
  'in-document-fragment': false,
8
8
  },
9
- async verify({ document, report, globalRule, t }) {
9
+ async verify({ document, report, t }) {
10
10
  const h1Stack = [];
11
11
  if (document.nodeList.length === 0) {
12
12
  return;
13
13
  }
14
- if (!globalRule.option['in-document-fragment'] && document.isFragment) {
14
+ if (!document.rule.option['in-document-fragment'] && document.isFragment) {
15
15
  return;
16
16
  }
17
- await document.walkOn('Element', async (node) => {
17
+ await document.walkOn('Element', node => {
18
18
  if (node.nodeName.toLowerCase() === 'h1') {
19
19
  h1Stack.push(node);
20
20
  }
@@ -28,7 +28,7 @@ exports.default = (0, ml_core_1.createRule)({
28
28
  raw: document.nodeList[0].raw.slice(0, 1),
29
29
  });
30
30
  }
31
- else if (globalRule.option['expected-once'] && h1Stack.length > 1) {
31
+ else if (document.rule.option['expected-once'] && h1Stack.length > 1) {
32
32
  const message = t('{0} is {1:c}', t('the "{0*}" {1}', 'h1', 'element'), 'duplicated');
33
33
  report({
34
34
  message,
@@ -0,0 +1,3 @@
1
+ import type { Options } from '../types';
2
+ import type { AttrChecker } from '@markuplint/ml-core';
3
+ export declare const checkingAbstractRole: AttrChecker<boolean, Options>;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkingAbstractRole = void 0;
4
+ const ml_spec_1 = require("@markuplint/ml-spec");
5
+ const checkingAbstractRole = ({ attr }) => t => {
6
+ var _a;
7
+ const { roles } = (0, ml_spec_1.ariaSpecs)(attr.ownerMLDocument.specs, attr.rule.option.version);
8
+ const tokens = (_a = attr.tokenList) === null || _a === void 0 ? void 0 : _a.allTokens();
9
+ if (!tokens) {
10
+ return;
11
+ }
12
+ for (const token of tokens) {
13
+ const role = roles.find(r => r.name === token.raw);
14
+ if (role === null || role === void 0 ? void 0 : role.isAbstract) {
15
+ return {
16
+ scope: token,
17
+ message: t('{0} is {1}', t('the "{0*}" {1}', token.raw, 'role'), 'the abstract role'),
18
+ };
19
+ }
20
+ }
21
+ };
22
+ exports.checkingAbstractRole = checkingAbstractRole;
@@ -0,0 +1,11 @@
1
+ import type { Options } from '../types';
2
+ import type { ElementChecker } from '@markuplint/ml-core';
3
+ import type { ARIARole } from '@markuplint/ml-spec';
4
+ /**
5
+ * Required Owned Elements
6
+ *
7
+ * @see https://w3c.github.io/aria/#mustContain
8
+ */
9
+ export declare const checkingRequiredOwnedElements: ElementChecker<boolean, Options, {
10
+ role?: ARIARole | null;
11
+ }>;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkingRequiredOwnedElements = void 0;
4
+ const ml_spec_1 = require("@markuplint/ml-spec");
5
+ /**
6
+ * Required Owned Elements
7
+ *
8
+ * @see https://w3c.github.io/aria/#mustContain
9
+ */
10
+ const checkingRequiredOwnedElements = ({ el, role }) => t => {
11
+ if (!role) {
12
+ return;
13
+ }
14
+ if (!role.requiredOwnedElements.length) {
15
+ return;
16
+ }
17
+ /**
18
+ * > There may be times that required owned elements are missing,
19
+ * > for example, while editing or while loading a data set.
20
+ * > When a widget is missing required owned elements due to script execution or loading,
21
+ * > authors MUST mark a containing element with aria-busy equal to true.
22
+ * > For example, until a page is fully initialized and complete,
23
+ * > an author could mark the document element as busy.
24
+ *
25
+ * Stop to evaluate when it has `aria-busy=true` for it considers the contents are missing.
26
+ */
27
+ if (el.matches('[aria-busy="true" i]')) {
28
+ return;
29
+ }
30
+ // TODO: Needs to resolve `aria-own`
31
+ if (!el.children.length) {
32
+ return {
33
+ scope: el,
34
+ message: t('{0}. Or, {1}', t('Require {0} to content', t('the {0*} {1}', t(role.requiredOwnedElements), 'role')), t('require {0}', 'aria-busy="true"')),
35
+ };
36
+ }
37
+ const children = Array.from(el.childNodes).map(child => {
38
+ if (child.is(child.ELEMENT_NODE)) {
39
+ const computedChild = (0, ml_spec_1.getComputedRole)(child.ownerMLDocument.specs, child, child.rule.option.version);
40
+ if (role.requiredOwnedElements.some(ownedRole => (0, ml_spec_1.isRequiredOwnedElement)(computedChild, ownedRole, child.ownerMLDocument.specs, child.rule.option.version))) {
41
+ return 'REQUIRED';
42
+ }
43
+ return 'OTHER';
44
+ }
45
+ else if (child.MARKUPLINT_PREPROCESSOR_BLOCK) {
46
+ return 'PB';
47
+ }
48
+ return 'NO_ELEMENT';
49
+ });
50
+ if (children.includes('PB')) {
51
+ return {
52
+ scope: el,
53
+ message: t('{0} expects {1}', t('the "{0*}" {1}', role.name, 'role'), t(role.requiredContextRole.map(ownedRole => t('the "{0*}" {1}', ownedRole, 'role')))),
54
+ };
55
+ }
56
+ if (!children.includes('REQUIRED')) {
57
+ return {
58
+ scope: el,
59
+ message: t('{0} expects {1}', t('the "{0*}" {1}', role.name, 'role'), t('the {0*} {1}', t(role.requiredOwnedElements), 'roles')),
60
+ };
61
+ }
62
+ };
63
+ exports.checkingRequiredOwnedElements = checkingRequiredOwnedElements;
@@ -0,0 +1,6 @@
1
+ import type { Options } from '../types';
2
+ import type { AttrChecker } from '@markuplint/ml-core';
3
+ import type { ARIAProperty } from '@markuplint/ml-spec';
4
+ export declare const checkingDefaultValue: AttrChecker<boolean, Options, {
5
+ propSpecs: ARIAProperty[];
6
+ }>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkingDefaultValue = void 0;
4
+ const checkingDefaultValue = ({ attr, propSpecs }) => t => {
5
+ if (attr.isDynamicValue) {
6
+ return;
7
+ }
8
+ const propSpec = propSpecs.find(p => p.name === attr.name);
9
+ const value = attr.value.trim().toLowerCase();
10
+ if ((propSpec === null || propSpec === void 0 ? void 0 : propSpec.defaultValue) != null && propSpec.defaultValue === value) {
11
+ return {
12
+ scope: attr,
13
+ message: t('It is {0}', 'default value'),
14
+ };
15
+ }
16
+ };
17
+ exports.checkingDefaultValue = checkingDefaultValue;
@@ -0,0 +1,7 @@
1
+ import type { Options } from '../types';
2
+ import type { AttrChecker } from '@markuplint/ml-core';
3
+ import type { ARIAProperty, ARIARole } from '@markuplint/ml-spec';
4
+ export declare const checkingDeprecatedProps: AttrChecker<boolean, Options, {
5
+ role: ARIARole | null;
6
+ propSpecs: ARIAProperty[];
7
+ }>;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkingDeprecatedProps = void 0;
4
+ const checkingDeprecatedProps = ({ attr, role, propSpecs }) => t => {
5
+ var _a;
6
+ if (!role) {
7
+ return;
8
+ }
9
+ const props = role.ownedProperties.find(p => p.name === attr.name);
10
+ if (props === null || props === void 0 ? void 0 : props.deprecated) {
11
+ const propSpec = propSpecs.find(p => p.name === attr.name);
12
+ return {
13
+ scope: attr,
14
+ message: t('{0:c} on {1}', t('{0} is {1:c}', t('the "{0*}" {1}', attr.name, `ARIA ${(_a = propSpec === null || propSpec === void 0 ? void 0 : propSpec.type) !== null && _a !== void 0 ? _a : 'property'}`), 'deprecated'), t('the "{0*}" {1}', role.name, 'role')),
15
+ };
16
+ }
17
+ };
18
+ exports.checkingDeprecatedProps = checkingDeprecatedProps;
@@ -0,0 +1,7 @@
1
+ import type { Options } from '../types';
2
+ import type { AttrChecker } from '@markuplint/ml-core';
3
+ import type { ARIAProperty, ARIARole } from '@markuplint/ml-spec';
4
+ export declare const checkingDisallowedProp: AttrChecker<boolean, Options, {
5
+ role: ARIARole | null;
6
+ propSpecs: ARIAProperty[];
7
+ }>;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkingDisallowedProp = void 0;
4
+ const checkingDisallowedProp = ({ attr, role, propSpecs }) => t => {
5
+ var _a;
6
+ if (!role) {
7
+ return;
8
+ }
9
+ if (!/^aria-/i.test(attr.name)) {
10
+ return;
11
+ }
12
+ const statesAndProp = role.ownedProperties.find(p => p.name === attr.name);
13
+ if (statesAndProp) {
14
+ return;
15
+ }
16
+ const propSpec = propSpecs.find(p => p.name === attr.name);
17
+ return {
18
+ scope: attr,
19
+ message: t('{0:c} on {1}', t('{0} is {1:c}', t('the "{0*}" {1}', attr.name, `ARIA ${(_a = propSpec === null || propSpec === void 0 ? void 0 : propSpec.type) !== null && _a !== void 0 ? _a : 'property'}`), 'disallowed'), t('the "{0*}" {1}', role.name, 'role')),
20
+ };
21
+ };
22
+ exports.checkingDisallowedProp = checkingDisallowedProp;
@@ -0,0 +1,7 @@
1
+ import type { Options } from '../types';
2
+ import type { AttrChecker } from '@markuplint/ml-core';
3
+ import type { ARIAProperty, Attribute } from '@markuplint/ml-spec';
4
+ export declare const checkingImplicitProps: AttrChecker<boolean, Options, {
5
+ propSpecs: ARIAProperty[];
6
+ attrSpecs: Attribute[] | null;
7
+ }>;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkingImplicitProps = void 0;
4
+ const helpers_1 = require("../../helpers");
5
+ const checkingImplicitProps = ({ attr, propSpecs, attrSpecs }) => t => {
6
+ if (!attrSpecs) {
7
+ return;
8
+ }
9
+ if (attr.isDynamicValue) {
10
+ return;
11
+ }
12
+ const propSpec = propSpecs.find(p => p.name === attr.name);
13
+ if (!(propSpec === null || propSpec === void 0 ? void 0 : propSpec.equivalentHtmlAttrs)) {
14
+ return;
15
+ }
16
+ for (const equivalentHtmlAttr of propSpec.equivalentHtmlAttrs) {
17
+ const htmlAttrSpec = attrSpecs.find(a => a.name === equivalentHtmlAttr.htmlAttrName);
18
+ const isValid = (0, helpers_1.isValidAttr)(t, equivalentHtmlAttr.htmlAttrName, equivalentHtmlAttr.value || '', false, attr.ownerElement, attrSpecs);
19
+ if (isValid && isValid.invalidType === 'non-existent') {
20
+ continue;
21
+ }
22
+ const value = attr.value.trim().toLowerCase();
23
+ if (attr.ownerElement.hasAttribute(equivalentHtmlAttr.htmlAttrName)) {
24
+ const targetAttrValue = attr.ownerElement.getAttribute(equivalentHtmlAttr.htmlAttrName);
25
+ if ((equivalentHtmlAttr.value == null && targetAttrValue === value) ||
26
+ equivalentHtmlAttr.value === value) {
27
+ return {
28
+ scope: attr,
29
+ message: t('{0} has {1}', t('the "{0*}" {1}', attr.name, `ARIA ${propSpec.type}`), t('the same {0} as {1}', 'semantics', t('{0} or {1}', t('the current "{0}" {1}', equivalentHtmlAttr.htmlAttrName, 'attribute'), t('the implicit "{0}" {1}', equivalentHtmlAttr.htmlAttrName, 'attribute')))),
30
+ };
31
+ }
32
+ if ((htmlAttrSpec === null || htmlAttrSpec === void 0 ? void 0 : htmlAttrSpec.type) === 'Boolean' && value !== 'false') {
33
+ continue;
34
+ }
35
+ return {
36
+ scope: attr,
37
+ message: t('{0} contradicts {1}', t('the "{0*}" {1}', attr.name, `ARIA ${propSpec.type}`), t('the current "{0}" {1}', equivalentHtmlAttr.htmlAttrName, 'attribute')),
38
+ };
39
+ }
40
+ else if (value === 'true') {
41
+ if (!equivalentHtmlAttr.isNotStrictEquivalent && (htmlAttrSpec === null || htmlAttrSpec === void 0 ? void 0 : htmlAttrSpec.type) === 'Boolean') {
42
+ return {
43
+ scope: attr,
44
+ message: t('{0} contradicts {1}', t('the "{0*}" {1}', attr.name, `ARIA ${propSpec.type}`), t('the implicit "{0}" {1}', equivalentHtmlAttr.htmlAttrName, 'attribute')),
45
+ };
46
+ }
47
+ }
48
+ }
49
+ };
50
+ exports.checkingImplicitProps = checkingImplicitProps;
@@ -0,0 +1,3 @@
1
+ import type { Options } from '../types';
2
+ import type { AttrChecker } from '@markuplint/ml-core';
3
+ export declare const checkingImplicitRole: AttrChecker<boolean, Options>;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkingImplicitRole = void 0;
4
+ const ml_spec_1 = require("@markuplint/ml-spec");
5
+ const checkingImplicitRole = ({ attr }) => t => {
6
+ var _a;
7
+ const implictRole = (0, ml_spec_1.getImplicitRoleName)(attr.ownerElement, attr.rule.option.version, attr.ownerMLDocument.specs);
8
+ const tokens = (_a = attr.tokenList) === null || _a === void 0 ? void 0 : _a.allTokens();
9
+ if (!tokens) {
10
+ return;
11
+ }
12
+ for (const token of tokens) {
13
+ if (implictRole === token.raw) {
14
+ return {
15
+ scope: token,
16
+ message: t('{0} is {1}', t('the "{0*}" {1}', token.raw, 'role'), t('{0} of {1}', 'the implicit role', t('the "{0*}" {1}', attr.ownerElement.localName, 'element'))),
17
+ };
18
+ }
19
+ }
20
+ };
21
+ exports.checkingImplicitRole = checkingImplicitRole;
@@ -0,0 +1,6 @@
1
+ import type { Options } from '../types';
2
+ import type { AttrChecker } from '@markuplint/ml-core';
3
+ import type { ARIAProperty } from '@markuplint/ml-spec';
4
+ export declare const checkingNoGlobalProp: AttrChecker<boolean, Options, {
5
+ propSpecs: ARIAProperty[];
6
+ }>;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkingNoGlobalProp = void 0;
4
+ const checkingNoGlobalProp = ({ attr, propSpecs }) => t => {
5
+ var _a, _b;
6
+ const propSpec = propSpecs.find(prop => prop.name === attr.name);
7
+ if (propSpec && !propSpec.isGlobal) {
8
+ return {
9
+ scope: attr,
10
+ message: t('{0} is not {1}', t('the "{0*}" {1}', attr.name, `ARIA ${(_a = propSpec.type) !== null && _a !== void 0 ? _a : 'property'}`), `global ${(_b = propSpec.type) !== null && _b !== void 0 ? _b : 'property'}`),
11
+ };
12
+ }
13
+ };
14
+ exports.checkingNoGlobalProp = checkingNoGlobalProp;
@@ -0,0 +1,3 @@
1
+ import type { Options } from '../types';
2
+ import type { AttrChecker } from '@markuplint/ml-core';
3
+ export declare const checkingNonExistantRole: AttrChecker<boolean, Options>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkingNonExistantRole = void 0;
4
+ const ml_spec_1 = require("@markuplint/ml-spec");
5
+ const checkingNonExistantRole = ({ attr }) => t => {
6
+ var _a;
7
+ const { roles, graphicsRoles } = (0, ml_spec_1.ariaSpecs)(attr.ownerMLDocument.specs, attr.rule.option.version);
8
+ const tokens = (_a = attr.tokenList) === null || _a === void 0 ? void 0 : _a.allTokens();
9
+ if (!tokens) {
10
+ return;
11
+ }
12
+ for (const token of tokens) {
13
+ let role = roles.find(r => r.name === token.raw);
14
+ if (!role && attr.ownerElement.namespaceURI === 'http://www.w3.org/2000/svg') {
15
+ role = graphicsRoles.find(r => r.name === token.raw);
16
+ }
17
+ if (!role) {
18
+ return {
19
+ scope: token,
20
+ message: t('{0} according to {1}', t('{0} does not exist', t('the "{0*}" {1}', token.raw, 'role')), 'the WAI-ARIA specification') +
21
+ t('.') +
22
+ // TODO: Translate
23
+ ` This "${token.raw}" role does not exist in WAI-ARIA.`,
24
+ };
25
+ }
26
+ }
27
+ };
28
+ exports.checkingNonExistantRole = checkingNonExistantRole;