@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
@@ -8,100 +8,100 @@ const log = debug_1.log.extend('invalid-attr');
8
8
  exports.default = (0, ml_core_1.createRule)({
9
9
  defaultOptions: {},
10
10
  async verify({ document, report, t }) {
11
- await document.walkOn('Element', node => {
12
- var _a, _b, _c, _d, _e, _f, _g, _h;
13
- const attrSpecs = (0, ml_core_1.getAttrSpecs)(node.nameWithNS, document.specs);
14
- for (const attr of node.attributes) {
15
- if (attr.attrType === 'html-attr' && attr.isDirective) {
16
- continue;
11
+ await document.walkOn('Attr', attr => {
12
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
13
+ if (attr.isDirective) {
14
+ return;
15
+ }
16
+ const attrSpecs = (0, ml_core_1.getAttrSpecs)(attr.ownerElement, document.specs);
17
+ const attrName = attr.nameNode;
18
+ const name = attr.name;
19
+ if (attr.ownerElement.elementType === 'html' && attr.candidate) {
20
+ const message = t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'disallowed') +
21
+ t('. ') +
22
+ t('Did you mean "{0}"?', attr.candidate);
23
+ report({
24
+ scope: attr,
25
+ line: attrName === null || attrName === void 0 ? void 0 : attrName.startLine,
26
+ col: attrName === null || attrName === void 0 ? void 0 : attrName.startCol,
27
+ raw: attrName === null || attrName === void 0 ? void 0 : attrName.raw,
28
+ message: message,
29
+ });
30
+ return;
31
+ }
32
+ const valueNode = attr.valueNode;
33
+ const value = attr.value;
34
+ if (attr.rule.option.ignoreAttrNamePrefix) {
35
+ const ignoreAttrNamePrefixes = Array.isArray(attr.rule.option.ignoreAttrNamePrefix)
36
+ ? attr.rule.option.ignoreAttrNamePrefix
37
+ : [attr.rule.option.ignoreAttrNamePrefix];
38
+ if (ignoreAttrNamePrefixes.some(prefix => name.indexOf(prefix) === 0)) {
39
+ return;
17
40
  }
18
- const attrName = attr.getName();
19
- const name = attrName.potential;
20
- if (!node.isCustomElement && attr.attrType === 'html-attr' && attr.candidate) {
21
- const message = t('{0} is {1:c}', t('the "{0*}" {1}', attrName.raw, 'attribute'), 'disallowed') +
22
- t('. ') +
23
- t('Did you mean "{0}"?', attr.candidate);
24
- report({
25
- scope: node,
26
- message: message,
27
- line: attrName.line,
28
- col: attrName.col,
29
- raw: attrName.raw,
41
+ }
42
+ let invalid = false;
43
+ const customRule = attr.rule.option.attrs ? attr.rule.option.attrs[name] : null;
44
+ if (customRule) {
45
+ if ('enum' in customRule) {
46
+ invalid = (0, attr_check_1.attrCheck)(t, name.toLowerCase(), value, true, {
47
+ name,
48
+ type: {
49
+ enum: customRule.enum,
50
+ },
51
+ description: '',
30
52
  });
31
- continue;
32
- }
33
- const attrValue = attr.getValue();
34
- const value = attrValue.potential;
35
- if (node.rule.option.ignoreAttrNamePrefix) {
36
- const ignoreAttrNamePrefixes = Array.isArray(node.rule.option.ignoreAttrNamePrefix)
37
- ? node.rule.option.ignoreAttrNamePrefix
38
- : [node.rule.option.ignoreAttrNamePrefix];
39
- if (ignoreAttrNamePrefixes.some(prefix => name.indexOf(prefix) === 0)) {
40
- continue;
41
- }
42
53
  }
43
- let invalid = false;
44
- const customRule = node.rule.option.attrs ? node.rule.option.attrs[name] : null;
45
- if (customRule) {
46
- if (attr.attrType === 'html-attr' && attr.isDynamicValue) {
47
- continue;
48
- }
49
- if ('enum' in customRule) {
50
- invalid = (0, attr_check_1.attrCheck)(t, name.toLowerCase(), value, true, {
51
- name,
52
- type: {
53
- enum: customRule.enum,
54
- },
55
- description: '',
56
- });
57
- }
58
- else if ('pattern' in customRule) {
59
- if (!(0, helpers_1.match)(value, customRule.pattern)) {
60
- invalid = {
61
- invalidType: 'invalid-value',
62
- message: t('{0} is unmatched with the below patterns: {1}', t('the "{0*}" {1}', name, 'attribute'), customRule.pattern),
63
- };
64
- }
65
- }
66
- else if ('type' in customRule) {
67
- invalid = (0, attr_check_1.attrCheck)(t, name, value, true, { name, type: customRule.type, description: '' });
68
- }
69
- else if ('disallowed' in customRule && customRule.disallowed) {
54
+ else if ('pattern' in customRule) {
55
+ if (!(0, helpers_1.match)(value, customRule.pattern)) {
70
56
  invalid = {
71
- invalidType: 'non-existent',
72
- message: t('{0} is disallowed', t('the "{0*}" {1}', name, 'attribute')),
57
+ invalidType: 'invalid-value',
58
+ message: t('{0} is unmatched with the below patterns: {1}', t('the "{0*}" {1}', name, 'attribute'), customRule.pattern),
73
59
  };
74
60
  }
75
61
  }
76
- else if (!node.isCustomElement && attrSpecs) {
77
- log('Checking %s[%s="%s"]', node.nodeName, name, value);
78
- invalid = (0, helpers_1.isValidAttr)(t, name, value, (attr.attrType === 'html-attr' && attr.isDynamicValue) || false, node, attrSpecs, log);
62
+ else if ('type' in customRule) {
63
+ invalid = (0, attr_check_1.attrCheck)(t, name, value, true, { name, type: customRule.type, description: '' });
79
64
  }
80
- if (invalid) {
81
- switch (invalid.invalidType) {
82
- case 'invalid-value': {
83
- report({
84
- scope: node,
85
- message: invalid.message,
86
- line: attrValue.line + ((_b = (_a = invalid.loc) === null || _a === void 0 ? void 0 : _a.line) !== null && _b !== void 0 ? _b : 0),
87
- col: ((_c = invalid.loc) === null || _c === void 0 ? void 0 : _c.line) ? ((_d = invalid.loc) === null || _d === void 0 ? void 0 : _d.col) + 1 : attrValue.col + ((_f = (_e = invalid.loc) === null || _e === void 0 ? void 0 : _e.col) !== null && _f !== void 0 ? _f : 0),
88
- raw: (_h = (_g = invalid.loc) === null || _g === void 0 ? void 0 : _g.raw) !== null && _h !== void 0 ? _h : value,
89
- });
65
+ else if ('disallowed' in customRule && customRule.disallowed) {
66
+ invalid = {
67
+ invalidType: 'non-existent',
68
+ message: t('{0} is disallowed', t('the "{0*}" {1}', name, 'attribute')),
69
+ };
70
+ }
71
+ }
72
+ else if (attr.ownerElement.elementType === 'html' && attrSpecs) {
73
+ log('Checking %s[%s="%s"]', attr.nodeName, name, value);
74
+ invalid = (0, helpers_1.isValidAttr)(t, name, value, attr.isDynamicValue || false, attr.ownerElement, attrSpecs, log);
75
+ }
76
+ if (invalid) {
77
+ switch (invalid.invalidType) {
78
+ case 'invalid-value': {
79
+ if (attr.isDynamicValue) {
90
80
  break;
91
81
  }
92
- case 'non-existent': {
93
- const spec = (0, helpers_1.htmlSpec)(document.specs, node.nameWithNS);
94
- if (spec === null || spec === void 0 ? void 0 : spec.possibleToAddProperties) {
95
- continue;
96
- }
97
- report({
98
- scope: node,
99
- message: invalid.message,
100
- line: attrName.line,
101
- col: attrName.col,
102
- raw: attrName.raw,
103
- });
82
+ report({
83
+ scope: attr,
84
+ message: invalid.message,
85
+ line: ((_a = valueNode === null || valueNode === void 0 ? void 0 : valueNode.startLine) !== null && _a !== void 0 ? _a : 0) + ((_c = (_b = invalid.loc) === null || _b === void 0 ? void 0 : _b.line) !== null && _c !== void 0 ? _c : 0),
86
+ col: ((_d = invalid.loc) === null || _d === void 0 ? void 0 : _d.line)
87
+ ? ((_e = invalid.loc) === null || _e === void 0 ? void 0 : _e.col) + 1
88
+ : ((_f = valueNode === null || valueNode === void 0 ? void 0 : valueNode.startCol) !== null && _f !== void 0 ? _f : 0) + ((_h = (_g = invalid.loc) === null || _g === void 0 ? void 0 : _g.col) !== null && _h !== void 0 ? _h : 0),
89
+ raw: (_k = (_j = invalid.loc) === null || _j === void 0 ? void 0 : _j.raw) !== null && _k !== void 0 ? _k : value,
90
+ });
91
+ break;
92
+ }
93
+ case 'non-existent': {
94
+ const spec = (0, ml_core_1.getSpec)(attr.ownerElement, document.specs.specs);
95
+ if (spec === null || spec === void 0 ? void 0 : spec.possibleToAddProperties) {
96
+ return;
104
97
  }
98
+ report({
99
+ scope: attr,
100
+ message: invalid.message,
101
+ line: attrName === null || attrName === void 0 ? void 0 : attrName.startLine,
102
+ col: attrName === null || attrName === void 0 ? void 0 : attrName.startCol,
103
+ raw: attrName === null || attrName === void 0 ? void 0 : attrName.raw,
104
+ });
105
105
  }
106
106
  }
107
107
  }
@@ -1,6 +1,6 @@
1
1
  declare type Options = {
2
- ignoreRoles?: Roles[];
3
- labelEachArea?: boolean;
2
+ ignoreRoles: Roles[];
3
+ labelEachArea: boolean;
4
4
  };
5
5
  declare type TopLevelRoles = 'banner' | 'main' | 'complementary' | 'contentinfo';
6
6
  declare type Roles = TopLevelRoles | 'form' | 'navigation' | 'region';
@@ -12,7 +12,7 @@ const selectors = {
12
12
  };
13
13
  const topLevelRoles = ['banner', 'main', 'complementary', 'contentinfo'];
14
14
  exports.default = (0, ml_core_1.createRule)({
15
- defaultServerity: 'warning',
15
+ defaultSeverity: 'warning',
16
16
  defaultOptions: {
17
17
  ignoreRoles: [],
18
18
  labelEachArea: true,
@@ -23,13 +23,13 @@ exports.default = (0, ml_core_1.createRule)({
23
23
  return;
24
24
  }
25
25
  const roles = {
26
- complementary: document.matchNodes(selectors.complementary.join(',')),
27
- contentinfo: document.matchNodes(selectors.contentinfo.join(',')),
28
- form: document.matchNodes(selectors.form.join(',')),
29
- banner: document.matchNodes(selectors.banner.join(',')),
30
- main: document.matchNodes(selectors.main.join(',')),
31
- navigation: document.matchNodes(selectors.navigation.join(',')),
32
- region: document.matchNodes(selectors.region.join(',')),
26
+ complementary: Array.from(document.querySelectorAll(selectors.complementary.join(','))),
27
+ contentinfo: Array.from(document.querySelectorAll(selectors.contentinfo.join(','))),
28
+ form: Array.from(document.querySelectorAll(selectors.form.join(','))),
29
+ banner: Array.from(document.querySelectorAll(selectors.banner.join(','))),
30
+ main: Array.from(document.querySelectorAll(selectors.main.join(','))),
31
+ navigation: Array.from(document.querySelectorAll(selectors.navigation.join(','))),
32
+ region: Array.from(document.querySelectorAll(selectors.region.join(','))),
33
33
  };
34
34
  /**
35
35
  * `<header>`
@@ -43,7 +43,7 @@ exports.default = (0, ml_core_1.createRule)({
43
43
  * > - nav
44
44
  * > - section
45
45
  */
46
- const headers = document.matchNodes('header').filter(header => {
46
+ const headers = Array.from(document.querySelectorAll('header')).filter(header => {
47
47
  return !header.closest('article, aside, main, nav, section');
48
48
  });
49
49
  roles.banner.push(...headers);
@@ -59,7 +59,7 @@ exports.default = (0, ml_core_1.createRule)({
59
59
  * > - nav
60
60
  * > - section
61
61
  */
62
- const footers = document.matchNodes('footer').filter(footer => {
62
+ const footers = Array.from(document.querySelectorAll('footer')).filter(footer => {
63
63
  return !footer.closest('article, aside, main, nav, section');
64
64
  });
65
65
  roles.contentinfo.push(...footers);
@@ -2,45 +2,44 @@
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
+ var _a, _b;
9
+ const attrSpec = (0, ml_core_1.getAttrSpecs)(attr.ownerElement, document.specs);
9
10
  if (!attrSpec) {
10
11
  return;
11
12
  }
12
- for (const attr of el.attributes) {
13
- if (attr.attrType === 'ps-attr' || attr.isDynamicValue) {
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
- if (spec.type !== 'Boolean') {
22
- continue;
23
- }
24
- const extraTokens = [
25
- attr.spacesBeforeEqual,
26
- attr.equal,
27
- attr.spacesAfterEqual,
28
- attr.startQuote,
29
- attr.valueNode,
30
- attr.endQuote,
31
- ];
32
- const extraRaw = extraTokens.reduce((raw, t) => raw + t.raw, '');
33
- if (extraRaw) {
34
- report({
35
- scope: el,
36
- raw: extraRaw,
37
- line: attr.spacesBeforeEqual.startLine,
38
- col: attr.spacesBeforeEqual.startCol,
39
- message: t('{0} is {1}', t('the "{0*}" {1}', name, 'attribute'), t('a {0}', 'boolean attribute')) +
40
- t('. ') +
41
- t("It doesn't need {0}", t('the {0}', 'value')),
42
- });
43
- }
13
+ if (attr.isDynamicValue) {
14
+ return;
15
+ }
16
+ const name = attr.name;
17
+ const spec = attrSpec.find(s => s.name === name);
18
+ if (!spec) {
19
+ return;
20
+ }
21
+ if (spec.type !== 'Boolean') {
22
+ return;
23
+ }
24
+ const extraTokens = [
25
+ attr.spacesBeforeEqual,
26
+ attr.equal,
27
+ attr.spacesAfterEqual,
28
+ attr.startQuote,
29
+ attr.valueNode,
30
+ attr.endQuote,
31
+ ];
32
+ const extraRaw = extraTokens.reduce((raw, t) => { var _a; return raw + ((_a = t === null || t === void 0 ? void 0 : t.raw) !== null && _a !== void 0 ? _a : ''); }, '');
33
+ if (extraRaw) {
34
+ report({
35
+ scope: attr,
36
+ line: (_a = attr.spacesBeforeEqual) === null || _a === void 0 ? void 0 : _a.startLine,
37
+ col: (_b = attr.spacesBeforeEqual) === null || _b === void 0 ? void 0 : _b.startCol,
38
+ raw: extraRaw,
39
+ message: t('{0} is {1}', t('the "{0*}" {1}', name, 'attribute'), t('a {0}', 'boolean attribute')) +
40
+ t('. ') +
41
+ t("It doesn't need {0}", t('the {0}', 'value')),
42
+ });
44
43
  }
45
44
  });
46
45
  },
@@ -3,35 +3,31 @@ 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
- defaultServerity: 'warning',
6
+ defaultSeverity: 'warning',
7
7
  async verify({ document, report, t }) {
8
- await document.walkOn('Element', el => {
9
- const attrSpec = (0, ml_core_1.getAttrSpecs)(el.nameWithNS, document.specs);
8
+ await document.walkOn('Attr', attr => {
9
+ var _a, _b, _c;
10
+ const attrSpec = (0, ml_core_1.getAttrSpecs)(attr.ownerElement, document.specs);
10
11
  if (!attrSpec) {
11
12
  return;
12
13
  }
13
- for (const attr of el.attributes) {
14
- if (attr.attrType !== 'html-attr') {
15
- continue;
16
- }
17
- const spec = attrSpec.find(s => s.name === attr.getName().potential);
18
- if (!spec) {
19
- continue;
20
- }
21
- if (!spec.defaultValue) {
22
- continue;
23
- }
24
- const normalizedValue = (0, helpers_1.toNormalizedValue)(attr.getValue().potential, spec);
25
- const defaultValue = (0, helpers_1.toNormalizedValue)(spec.defaultValue, spec);
26
- if (defaultValue === normalizedValue) {
27
- report({
28
- scope: el,
29
- line: attr.valueNode.startLine,
30
- col: attr.valueNode.startCol,
31
- raw: attr.valueNode.raw,
32
- message: t('It is {0}', t('the {0}', 'default value')),
33
- });
34
- }
14
+ const spec = attrSpec.find(s => s.name === attr.name);
15
+ if (!spec) {
16
+ return;
17
+ }
18
+ if (!spec.defaultValue) {
19
+ return;
20
+ }
21
+ const normalizedValue = (0, helpers_1.toNormalizedValue)(attr.value, spec);
22
+ const defaultValue = (0, helpers_1.toNormalizedValue)(spec.defaultValue, spec);
23
+ if (defaultValue === normalizedValue) {
24
+ report({
25
+ scope: attr,
26
+ line: (_a = attr.valueNode) === null || _a === void 0 ? void 0 : _a.startLine,
27
+ col: (_b = attr.valueNode) === null || _b === void 0 ? void 0 : _b.startCol,
28
+ raw: (_c = attr.valueNode) === null || _c === void 0 ? void 0 : _c.raw,
29
+ message: t('It is {0}', t('the {0}', 'default value')),
30
+ });
35
31
  }
36
32
  });
37
33
  },
@@ -2,24 +2,20 @@
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
7
  if (!document.isFragment) {
8
8
  return;
9
9
  }
10
- await document.walkOn('Element', el => {
11
- for (const attr of el.attributes) {
12
- if (attr.potentialName.toLowerCase() === 'id' &&
13
- ((attr.attrType === 'html-attr' && !attr.isDynamicValue) ||
14
- (attr.attrType === 'ps-attr' && attr.valueType !== 'code'))) {
15
- report({
16
- scope: el,
17
- line: attr.startLine,
18
- col: attr.startCol,
19
- raw: attr.raw,
20
- message: t('It is {0:c}', 'hard-coded'),
21
- });
22
- }
10
+ await document.walkOn('Attr', attr => {
11
+ if (attr.name.toLowerCase() === 'id' && !attr.isDynamicValue && attr.valueType !== 'code') {
12
+ report({
13
+ scope: attr,
14
+ line: attr.startLine,
15
+ col: attr.startCol,
16
+ raw: attr.raw,
17
+ message: t('It is {0:c}', 'hard-coded'),
18
+ });
23
19
  }
24
20
  });
25
21
  },
@@ -1,2 +1,5 @@
1
- declare const _default: import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, null>;
1
+ import type { ARIAVersion } from '@markuplint/ml-spec';
2
+ declare const _default: import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, {
3
+ ariaVersion: ARIAVersion;
4
+ }>;
2
5
  export default _default;
@@ -1,106 +1,100 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ml_core_1 = require("@markuplint/ml-core");
4
- const helpers_1 = require("../helpers");
5
4
  exports.default = (0, ml_core_1.createRule)({
5
+ defaultOptions: {
6
+ ariaVersion: '1.2',
7
+ },
6
8
  async verify({ document, report, t }) {
7
- const { ariaAttrs } = (0, helpers_1.ariaSpec)(document.specs);
8
9
  const idList = new Set();
9
10
  let hasDynamicId = false;
10
- await document.walkOn('Element', el => {
11
- for (const attr of el.attributes) {
12
- if (attr.getName().potential.toLowerCase() !== 'id') {
13
- continue;
14
- }
15
- if (attr.attrType === 'html-attr') {
16
- if (attr.isDynamicValue) {
17
- hasDynamicId = true;
18
- }
19
- idList.add(attr.getValue().potential);
20
- }
21
- else {
22
- if (attr.valueType !== 'code') {
23
- idList.add(attr.getValue().potential);
24
- }
25
- }
11
+ await document.walkOn('Attr', attr => {
12
+ if (attr.name.toLowerCase() !== 'id') {
13
+ return;
14
+ }
15
+ if (attr.isDynamicValue) {
16
+ hasDynamicId = true;
17
+ }
18
+ if (attr.valueType !== 'code') {
19
+ idList.add(attr.value);
26
20
  }
27
21
  });
28
22
  if (hasDynamicId) {
29
23
  return;
30
24
  }
31
- document.walkOn('Element', el => {
32
- const attrSpec = (0, ml_core_1.getAttrSpecs)(el.nameWithNS, document.specs);
25
+ await document.walkOn('Attr', attr => {
26
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
27
+ const attrSpec = (0, ml_core_1.getAttrSpecs)(attr.ownerElement, document.specs);
33
28
  if (!attrSpec) {
34
29
  return;
35
30
  }
36
- for (const attr of el.attributes) {
37
- if (attr.attrType !== 'html-attr' || attr.isDynamicValue) {
38
- continue;
31
+ if (attr.isDynamicValue) {
32
+ return;
33
+ }
34
+ const name = attr.name;
35
+ if (name.toLowerCase() === 'id') {
36
+ return;
37
+ }
38
+ const value = attr.value;
39
+ const spec = attrSpec.find(s => s.name === name);
40
+ if (spec) {
41
+ // DOMID and DOMID List do not become in the array type.
42
+ if (Array.isArray(spec.type)) {
43
+ return;
39
44
  }
40
- const name = attr.getName().potential;
41
- if (name.toLowerCase() === 'id') {
42
- continue;
45
+ if (spec.type === 'DOMID' && !idList.has(value)) {
46
+ report({
47
+ scope: attr,
48
+ line: (_a = attr.valueNode) === null || _a === void 0 ? void 0 : _a.startLine,
49
+ col: (_b = attr.valueNode) === null || _b === void 0 ? void 0 : _b.startCol,
50
+ raw: (_c = attr.valueNode) === null || _c === void 0 ? void 0 : _c.raw,
51
+ message: t('Missing {0}', t('"{0*}" ID', value)),
52
+ });
43
53
  }
44
- const value = attr.getValue().potential;
45
- const spec = attrSpec.find(s => s.name === name);
46
- if (spec) {
47
- // DOMID and DOMID List do not become in the array type.
48
- if (Array.isArray(spec.type)) {
49
- continue;
50
- }
51
- if (spec.type === 'DOMID' && !idList.has(value)) {
52
- report({
53
- scope: el,
54
- line: attr.valueNode.startLine,
55
- col: attr.valueNode.startCol,
56
- raw: attr.valueNode.raw,
57
- message: t('Missing {0}', t('"{0*}" ID', value)),
58
- });
59
- }
60
- if (typeof spec.type !== 'string' && 'token' in spec.type && spec.type.token === 'DOMID') {
61
- const refs = value
62
- .split(spec.type.separator === 'space' ? /\s/ : ',')
63
- .map(id => id.trim())
64
- .filter(_ => _);
65
- for (const ref of refs) {
66
- if (!idList.has(ref)) {
67
- report({
68
- scope: el,
69
- line: attr.valueNode.startLine,
70
- col: attr.valueNode.startCol,
71
- raw: attr.valueNode.raw,
72
- message: t('Missing {0}', t('"{0*}" ID', ref)),
73
- });
74
- }
54
+ if (typeof spec.type !== 'string' && 'token' in spec.type && spec.type.token === 'DOMID') {
55
+ const refs = value
56
+ .split(spec.type.separator === 'space' ? /\s/ : ',')
57
+ .map(id => id.trim())
58
+ .filter(_ => _);
59
+ for (const ref of refs) {
60
+ if (!idList.has(ref)) {
61
+ report({
62
+ scope: attr,
63
+ line: (_d = attr.valueNode) === null || _d === void 0 ? void 0 : _d.startLine,
64
+ col: (_e = attr.valueNode) === null || _e === void 0 ? void 0 : _e.startCol,
65
+ raw: (_f = attr.valueNode) === null || _f === void 0 ? void 0 : _f.raw,
66
+ message: t('Missing {0}', t('"{0*}" ID', ref)),
67
+ });
75
68
  }
76
69
  }
77
70
  }
78
- const aria = ariaAttrs.find(aria => aria.name === name);
79
- if (aria) {
80
- if (aria.value === 'ID reference' && !idList.has(value)) {
81
- report({
82
- scope: el,
83
- line: attr.valueNode.startLine,
84
- col: attr.valueNode.startCol,
85
- raw: attr.valueNode.raw,
86
- message: t('Missing {0}', t('"{0*}" ID', value)),
87
- });
88
- }
89
- else if (aria.value === 'ID reference list') {
90
- const refs = value
91
- .split(/\s/)
92
- .map(id => id.trim())
93
- .filter(_ => _);
94
- for (const ref of refs) {
95
- if (!idList.has(ref)) {
96
- report({
97
- scope: el,
98
- line: attr.valueNode.startLine,
99
- col: attr.valueNode.startCol,
100
- raw: attr.valueNode.raw,
101
- message: t('Missing {0}', t('"{0*}" ID', ref)),
102
- });
103
- }
71
+ }
72
+ const { props } = (0, ml_core_1.ariaSpecs)(document.specs, attr.rule.option.ariaVersion);
73
+ const aria = props.find(prop => prop.name === name);
74
+ if (aria) {
75
+ if (aria.value === 'ID reference' && !idList.has(value)) {
76
+ report({
77
+ scope: attr,
78
+ line: (_g = attr.valueNode) === null || _g === void 0 ? void 0 : _g.startLine,
79
+ col: (_h = attr.valueNode) === null || _h === void 0 ? void 0 : _h.startCol,
80
+ raw: (_j = attr.valueNode) === null || _j === void 0 ? void 0 : _j.raw,
81
+ message: t('Missing {0}', t('"{0*}" ID', value)),
82
+ });
83
+ }
84
+ else if (aria.value === 'ID reference list') {
85
+ const refs = value
86
+ .split(/\s/)
87
+ .map(id => id.trim())
88
+ .filter(_ => _);
89
+ for (const ref of refs) {
90
+ if (!idList.has(ref)) {
91
+ report({
92
+ scope: attr,
93
+ line: (_k = attr.valueNode) === null || _k === void 0 ? void 0 : _k.startLine,
94
+ col: (_l = attr.valueNode) === null || _l === void 0 ? void 0 : _l.startCol,
95
+ raw: (_m = attr.valueNode) === null || _m === void 0 ? void 0 : _m.raw,
96
+ message: t('Missing {0}', t('"{0*}" ID', ref)),
97
+ });
104
98
  }
105
99
  }
106
100
  }