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