@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.
- package/README.md +1 -5
- package/lib/__foo/index.d.ts +1 -1
- package/lib/attr-duplication/index.js +11 -8
- package/lib/attr-equal-space-after/index.d.ts +1 -1
- package/lib/attr-equal-space-after/index.js +2 -2
- package/lib/attr-equal-space-before/index.d.ts +1 -1
- package/lib/attr-equal-space-before/index.js +2 -2
- package/lib/attr-spacing/index.d.ts +3 -3
- package/lib/attr-spacing/index.js +2 -2
- package/lib/attr-value-quotes/index.js +21 -25
- package/lib/case-sensitive-attr-name/index.d.ts +1 -5
- package/lib/case-sensitive-attr-name/index.js +51 -81
- package/lib/case-sensitive-tag-name/index.js +38 -30
- package/lib/character-reference/index.d.ts +2 -1
- package/lib/character-reference/index.js +7 -9
- package/lib/class-naming/index.js +11 -11
- package/lib/deprecated-attr/index.js +17 -18
- package/lib/deprecated-element/index.js +6 -8
- package/lib/disallowed-element/index.js +8 -9
- package/lib/doctype/index.js +7 -7
- package/lib/end-tag/index.js +4 -1
- package/lib/helper/aria/get-aria.d.ts +7 -0
- package/lib/helper/aria/get-aria.js +53 -0
- package/lib/helper/aria/get-computed-role.d.ts +10 -0
- package/lib/helper/aria/get-computed-role.js +24 -0
- package/lib/helper/aria/get-implicit-role.d.ts +7 -0
- package/lib/helper/aria/get-implicit-role.js +12 -0
- package/lib/helper/aria/get-permitted-roles.d.ts +14 -0
- package/lib/helper/aria/get-permitted-roles.js +26 -0
- package/lib/helper/aria/resolve-version.d.ts +2 -0
- package/lib/helper/aria/resolve-version.js +21 -0
- package/lib/helper/spec/aria-spec.d.ts +5 -0
- package/lib/helper/spec/aria-spec.js +12 -0
- package/lib/helper/spec/get-role-spec.d.ts +11 -0
- package/lib/helper/spec/get-role-spec.js +39 -0
- package/lib/helper/spec/html-spec.d.ts +2 -0
- package/lib/helper/spec/html-spec.js +14 -0
- package/lib/helpers.d.ts +10 -28
- package/lib/helpers.js +29 -149
- package/lib/id-duplication/index.js +5 -7
- package/lib/indentation/index.d.ts +3 -3
- package/lib/indentation/index.js +4 -4
- package/lib/index.d.ts +14 -19
- package/lib/index.js +0 -8
- package/lib/ineffective-attr/index.js +19 -27
- package/lib/invalid-attr/index.js +83 -83
- package/lib/landmark-roles/index.d.ts +2 -2
- package/lib/landmark-roles/index.js +10 -10
- package/lib/no-boolean-attr-value/index.js +33 -34
- package/lib/no-default-value/index.js +20 -24
- package/lib/no-hard-code-id/index.js +9 -13
- package/lib/no-refer-to-non-existent-id/index.d.ts +4 -1
- package/lib/no-refer-to-non-existent-id/index.js +77 -83
- package/lib/no-use-event-handler-attr/index.js +20 -22
- package/lib/permitted-contents/index.d.ts +5 -2
- package/lib/permitted-contents/index.js +67 -68
- package/lib/permitted-contents/permitted-content.spec-to-regexp.d.ts +5 -5
- package/lib/permitted-contents/permitted-content.spec-to-regexp.js +19 -14
- package/lib/permitted-contents/unfold-content-models-to-tags.d.ts +2 -2
- package/lib/require-accessible-name/index.d.ts +5 -1
- package/lib/require-accessible-name/index.js +6 -3
- package/lib/required-attr/index.js +16 -25
- package/lib/required-element/index.d.ts +1 -1
- package/lib/required-element/index.js +6 -6
- package/lib/required-h1/index.d.ts +2 -2
- package/lib/required-h1/index.js +4 -4
- package/lib/wai-aria/checkings/abstract-role.d.ts +3 -0
- package/lib/wai-aria/checkings/abstract-role.js +22 -0
- package/lib/wai-aria/checkings/checking-required-owned-elements.d.ts +11 -0
- package/lib/wai-aria/checkings/checking-required-owned-elements.js +63 -0
- package/lib/wai-aria/checkings/default-value.d.ts +6 -0
- package/lib/wai-aria/checkings/default-value.js +17 -0
- package/lib/wai-aria/checkings/deprecated-props.d.ts +7 -0
- package/lib/wai-aria/checkings/deprecated-props.js +18 -0
- package/lib/wai-aria/checkings/disallowed-prop.d.ts +7 -0
- package/lib/wai-aria/checkings/disallowed-prop.js +22 -0
- package/lib/wai-aria/checkings/implicit-props.d.ts +7 -0
- package/lib/wai-aria/checkings/implicit-props.js +50 -0
- package/lib/wai-aria/checkings/implicit-role.d.ts +3 -0
- package/lib/wai-aria/checkings/implicit-role.js +21 -0
- package/lib/wai-aria/checkings/no-global-prop.d.ts +6 -0
- package/lib/wai-aria/checkings/no-global-prop.js +14 -0
- package/lib/wai-aria/checkings/non-existant-role.d.ts +3 -0
- package/lib/wai-aria/checkings/non-existant-role.js +28 -0
- package/lib/wai-aria/checkings/permitted-roles.d.ts +3 -0
- package/lib/wai-aria/checkings/permitted-roles.js +28 -0
- package/lib/wai-aria/checkings/required-prop.d.ts +9 -0
- package/lib/wai-aria/checkings/required-prop.js +27 -0
- package/lib/wai-aria/checkings/value.d.ts +7 -0
- package/lib/wai-aria/checkings/value.js +21 -0
- package/lib/wai-aria/index.d.ts +1 -8
- package/lib/wai-aria/index.js +56 -207
- package/lib/wai-aria/types.d.ts +11 -0
- package/lib/wai-aria/types.js +2 -0
- package/package.json +5 -5
- package/schema.json +0 -12
- 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(
|
|
14
|
-
this
|
|
15
|
-
this
|
|
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 =
|
|
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
|
|
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
|
|
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,
|
|
135
|
-
const counter = this.
|
|
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
|
|
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
|
-
|
|
169
|
-
|
|
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 {
|
|
2
|
-
export default function unfoldContentModelsToTags(contentModel:
|
|
1
|
+
import type { Category } from '@markuplint/ml-spec';
|
|
2
|
+
export default function unfoldContentModelsToTags(contentModel: Category): string[];
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
|
|
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
|
|
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,
|
|
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',
|
|
9
|
-
|
|
10
|
-
if (node.hasSpreadAttr) {
|
|
8
|
+
await document.walkOn('Element', el => {
|
|
9
|
+
if (el.hasSpreadAttr) {
|
|
11
10
|
return;
|
|
12
11
|
}
|
|
13
|
-
const customRequiredAttrs = typeof
|
|
14
|
-
const attrSpec = (0, ml_core_1.getAttrSpecs)(
|
|
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 && !
|
|
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 = !
|
|
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 =>
|
|
51
|
+
invalid = !candidate.some(attrName => el.hasAttribute(attrName));
|
|
53
52
|
}
|
|
54
53
|
else if (spec.required === true) {
|
|
55
|
-
invalid = (0, helpers_1.attrMatches)(
|
|
54
|
+
invalid = (0, helpers_1.attrMatches)(el, spec.condition) && didntHave;
|
|
56
55
|
}
|
|
57
56
|
else if (spec.required) {
|
|
58
|
-
|
|
59
|
-
|
|
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}',
|
|
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:
|
|
63
|
+
scope: el,
|
|
73
64
|
message,
|
|
74
65
|
});
|
|
75
66
|
}
|
|
76
|
-
const value =
|
|
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 =
|
|
83
|
-
const valueToken =
|
|
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:
|
|
78
|
+
rule: el.rule,
|
|
88
79
|
raw: token.raw,
|
|
89
80
|
startCol: token.startCol,
|
|
90
81
|
startLine: token.startLine,
|
|
@@ -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
|
|
10
|
-
const hasMutableContent = document.nodeList.some(n =>
|
|
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
|
|
13
|
-
const exists = document.
|
|
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 ===
|
|
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'
|
|
3
|
-
'in-document-fragment'
|
|
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;
|
package/lib/required-h1/index.js
CHANGED
|
@@ -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,
|
|
9
|
+
async verify({ document, report, t }) {
|
|
10
10
|
const h1Stack = [];
|
|
11
11
|
if (document.nodeList.length === 0) {
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
|
-
if (!
|
|
14
|
+
if (!document.rule.option['in-document-fragment'] && document.isFragment) {
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
-
await document.walkOn('Element',
|
|
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 (
|
|
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,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,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,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,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,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;
|