@markuplint/rules 3.0.0-alpha.2 → 3.0.0-alpha.27
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 +10 -44
- package/lib/attr-check.d.ts +2 -2
- package/lib/attr-value-quotes/index.d.ts +3 -3
- package/lib/case-sensitive-attr-name/index.d.ts +1 -1
- package/lib/case-sensitive-tag-name/index.d.ts +1 -1
- package/lib/class-naming/index.d.ts +1 -1
- package/lib/class-naming/index.js +1 -1
- package/lib/debug.d.ts +1 -1
- package/lib/doctype/index.d.ts +1 -1
- package/lib/doctype/index.js +1 -1
- package/lib/end-tag/index.js +2 -17
- package/lib/helpers.d.ts +2 -31
- package/lib/helpers.js +1 -71
- package/lib/index.d.ts +2 -58
- package/lib/index.js +4 -0
- package/lib/invalid-attr/index.d.ts +3 -2
- package/lib/invalid-attr/index.js +16 -11
- package/lib/label-has-control/index.d.ts +2 -0
- package/lib/label-has-control/index.js +28 -0
- package/lib/landmark-roles/index.d.ts +3 -3
- package/lib/landmark-roles/index.js +2 -2
- package/lib/no-empty-palpable-content/index.d.ts +6 -0
- package/lib/no-empty-palpable-content/index.js +34 -0
- package/lib/no-refer-to-non-existent-id/index.js +1 -1
- package/lib/no-use-event-handler-attr/index.d.ts +1 -1
- package/lib/no-use-event-handler-attr/index.js +4 -4
- package/lib/permitted-contents/debug.browser.d.ts +30 -0
- package/lib/permitted-contents/debug.browser.js +14 -0
- package/lib/permitted-contents/debug.d.ts +1 -0
- package/lib/permitted-contents/debug.js +9 -1
- package/lib/permitted-contents/index.js +4 -4
- package/lib/permitted-contents/matches-selector.d.ts +1 -1
- package/lib/permitted-contents/represent-transparent-nodes.d.ts +1 -1
- package/lib/permitted-contents/represent-transparent-nodes.js +0 -3
- package/lib/permitted-contents/start.js +1 -1
- package/lib/permitted-contents/transparent.js +6 -11
- package/lib/permitted-contents/types.d.ts +12 -12
- package/lib/permitted-contents/utils.d.ts +4 -4
- package/lib/permitted-contents/utils.js +8 -8
- package/lib/require-accessible-name/index.d.ts +1 -1
- package/lib/require-accessible-name/index.js +7 -3
- package/lib/required-attr/index.d.ts +2 -2
- package/lib/required-element/index.d.ts +1 -1
- package/lib/required-element/index.js +1 -1
- package/lib/required-h1/index.js +2 -2
- package/lib/use-list/index.d.ts +2 -2
- package/lib/use-list/index.js +1 -1
- package/lib/wai-aria/checkings/abstract-role.js +1 -1
- package/lib/wai-aria/checkings/implicit-role.js +1 -1
- package/lib/wai-aria/checkings/{non-existant-role.d.ts → non-existent-role.d.ts} +1 -1
- package/lib/wai-aria/checkings/{non-existant-role.js → non-existent-role.js} +4 -4
- package/lib/wai-aria/checkings/permitted-roles.js +1 -1
- package/lib/wai-aria/checkings/presentational-children.js +1 -1
- package/lib/wai-aria/checkings/required-owned-elements.js +40 -10
- package/lib/wai-aria/checkings/value.d.ts +6 -0
- package/lib/wai-aria/checkings/value.js +74 -4
- package/lib/wai-aria/index.js +14 -14
- package/lib/wai-aria/types.d.ts +1 -1
- package/package.json +11 -8
- package/schema.json +6 -0
- package/tsconfig.test.json +0 -3
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/// <reference types="debug" />
|
|
2
|
+
export declare const cmLog: import("debug").Debugger;
|
|
3
|
+
export declare const bgGreen: {
|
|
4
|
+
(): void;
|
|
5
|
+
bold(): void;
|
|
6
|
+
};
|
|
7
|
+
export declare const green: {
|
|
8
|
+
(): void;
|
|
9
|
+
bold(): void;
|
|
10
|
+
};
|
|
11
|
+
export declare const bgRed: {
|
|
12
|
+
(): void;
|
|
13
|
+
bold(): void;
|
|
14
|
+
};
|
|
15
|
+
export declare const bgBlue: {
|
|
16
|
+
(): void;
|
|
17
|
+
bold(): void;
|
|
18
|
+
};
|
|
19
|
+
export declare const blue: {
|
|
20
|
+
(): void;
|
|
21
|
+
bold(): void;
|
|
22
|
+
};
|
|
23
|
+
export declare const bgMagenta: {
|
|
24
|
+
(): void;
|
|
25
|
+
bold(): void;
|
|
26
|
+
};
|
|
27
|
+
export declare const cyan: {
|
|
28
|
+
(): void;
|
|
29
|
+
bold(): void;
|
|
30
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cyan = exports.bgMagenta = exports.blue = exports.bgBlue = exports.bgRed = exports.green = exports.bgGreen = exports.cmLog = void 0;
|
|
4
|
+
const debug_1 = require("../debug");
|
|
5
|
+
exports.cmLog = debug_1.log.extend('content-model');
|
|
6
|
+
const fn = () => { };
|
|
7
|
+
fn.bold = () => { };
|
|
8
|
+
exports.bgGreen = fn;
|
|
9
|
+
exports.green = fn;
|
|
10
|
+
exports.bgRed = fn;
|
|
11
|
+
exports.bgBlue = fn;
|
|
12
|
+
exports.blue = fn;
|
|
13
|
+
exports.bgMagenta = fn;
|
|
14
|
+
exports.cyan = fn;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.cmLog = void 0;
|
|
3
|
+
exports.cyan = exports.bgMagenta = exports.blue = exports.bgBlue = exports.bgRed = exports.green = exports.bgGreen = exports.cmLog = void 0;
|
|
4
4
|
const debug_1 = require("../debug");
|
|
5
5
|
exports.cmLog = debug_1.log.extend('content-model');
|
|
6
|
+
var ansi_colors_1 = require("ansi-colors");
|
|
7
|
+
Object.defineProperty(exports, "bgGreen", { enumerable: true, get: function () { return ansi_colors_1.bgGreen; } });
|
|
8
|
+
Object.defineProperty(exports, "green", { enumerable: true, get: function () { return ansi_colors_1.green; } });
|
|
9
|
+
Object.defineProperty(exports, "bgRed", { enumerable: true, get: function () { return ansi_colors_1.bgRed; } });
|
|
10
|
+
Object.defineProperty(exports, "bgBlue", { enumerable: true, get: function () { return ansi_colors_1.bgBlue; } });
|
|
11
|
+
Object.defineProperty(exports, "blue", { enumerable: true, get: function () { return ansi_colors_1.blue; } });
|
|
12
|
+
Object.defineProperty(exports, "bgMagenta", { enumerable: true, get: function () { return ansi_colors_1.bgMagenta; } });
|
|
13
|
+
Object.defineProperty(exports, "cyan", { enumerable: true, get: function () { return ansi_colors_1.cyan; } });
|
|
@@ -14,10 +14,10 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
14
14
|
if (!el.rule.value) {
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
-
if (el.rule.
|
|
17
|
+
if (el.rule.options.ignoreHasMutableChildren && el.hasMutableChildren()) {
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
|
-
const results = (0, content_model_1.contentModel)(el, el.rule.value, el.rule.
|
|
20
|
+
const results = (0, content_model_1.contentModel)(el, el.rule.value, el.rule.options);
|
|
21
21
|
for (const { type, scope, query, hint } of results) {
|
|
22
22
|
let message = '';
|
|
23
23
|
if (hint) {
|
|
@@ -75,10 +75,10 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
75
75
|
});
|
|
76
76
|
break;
|
|
77
77
|
}
|
|
78
|
-
case '
|
|
78
|
+
case 'NOTHING': {
|
|
79
79
|
report({
|
|
80
80
|
scope: el,
|
|
81
|
-
message: t('{0}
|
|
81
|
+
message: t('{0} disallows {1}', t('the {0}', 'element'), 'contents'),
|
|
82
82
|
});
|
|
83
83
|
break;
|
|
84
84
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ChildNode, Options, Result, Specs } from './types';
|
|
2
|
-
export
|
|
2
|
+
export type SelectorResult = Result<'UNMATCHED_SELECTOR_BUT_MAY_EMPTY' | 'MISSING_NODE' | 'UNMATCHED_SELECTORS'>;
|
|
3
3
|
export declare function matchesSelector(query: string, node: ChildNode | undefined, specs: Specs, options: Options, depth: number): SelectorResult;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ChildNode, Options, Result, Specs } from './types';
|
|
2
|
-
export declare const transparentMode: Map<
|
|
2
|
+
export declare const transparentMode: Map<ChildNode, true>;
|
|
3
3
|
export declare function representTransparentNodes(nodes: ChildNode[], specs: Specs, options: Options): {
|
|
4
4
|
nodes: ChildNode[];
|
|
5
5
|
errors: Result[];
|
|
@@ -13,9 +13,6 @@ function representTransparentNodes(nodes, specs, options) {
|
|
|
13
13
|
if (parent) {
|
|
14
14
|
const { errors: parentErrors } = representTransparentNodes([parent], specs, options);
|
|
15
15
|
errors.push(...parentErrors);
|
|
16
|
-
// if (!Array.isArray(parentRes)) {
|
|
17
|
-
// return parentRes;
|
|
18
|
-
// }
|
|
19
16
|
}
|
|
20
17
|
for (const node of nodes) {
|
|
21
18
|
if (!node.is(node.ELEMENT_NODE)) {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.transparent = void 0;
|
|
4
|
-
const count_pattern_1 = require("./count-pattern");
|
|
5
4
|
const debug_1 = require("./debug");
|
|
6
|
-
const utils_1 = require("./utils");
|
|
7
5
|
const transparentLog = debug_1.cmLog.extend('transparent');
|
|
8
6
|
function transparent(nodes, specs, options, depth) {
|
|
9
7
|
var _a;
|
|
@@ -19,16 +17,13 @@ function transparent(nodes, specs, options, depth) {
|
|
|
19
17
|
};
|
|
20
18
|
}
|
|
21
19
|
transparentLog('Transparent model element is component root');
|
|
22
|
-
const collection = new utils_1.Collection(nodes);
|
|
23
|
-
const result = (0, count_pattern_1.countPattern)({ zeroOrMore: ':model(flow)' }, collection.unmatched, specs, options, depth);
|
|
24
|
-
collection.addMatched(result.matched);
|
|
25
20
|
return {
|
|
26
|
-
type:
|
|
27
|
-
matched:
|
|
28
|
-
unmatched:
|
|
29
|
-
zeroMatch:
|
|
30
|
-
query:
|
|
31
|
-
hint:
|
|
21
|
+
type: 'MATCHED',
|
|
22
|
+
matched: nodes.slice(),
|
|
23
|
+
unmatched: [],
|
|
24
|
+
zeroMatch: false,
|
|
25
|
+
query: 'transparent',
|
|
26
|
+
hint: {},
|
|
32
27
|
};
|
|
33
28
|
}
|
|
34
29
|
exports.transparent = transparent;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Element as _Element } from '@markuplint/ml-core';
|
|
1
|
+
import type { Element as _Element, ChildNode as _ChildNode } from '@markuplint/ml-core';
|
|
2
2
|
import type { ContentModel, MLMLSpec } from '@markuplint/ml-spec';
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
3
|
+
export type Element = _Element<TagRule[], Options>;
|
|
4
|
+
export type ChildNode = _ChildNode<TagRule[], Options>;
|
|
5
|
+
export type Specs = {
|
|
6
6
|
cites: MLMLSpec['cites'];
|
|
7
7
|
def: MLMLSpec['def'];
|
|
8
8
|
specs: {
|
|
@@ -12,13 +12,13 @@ export declare type Specs = {
|
|
|
12
12
|
};
|
|
13
13
|
}[];
|
|
14
14
|
};
|
|
15
|
-
export
|
|
15
|
+
export type ContentModelResult = {
|
|
16
16
|
type: MatchedReason | UnmatchedReason;
|
|
17
17
|
scope: ChildNode;
|
|
18
18
|
query: Result['query'];
|
|
19
19
|
hint: Result['hint'];
|
|
20
20
|
};
|
|
21
|
-
export
|
|
21
|
+
export type Result<T extends string = MatchedReason> = {
|
|
22
22
|
type: MatchedReason | UnmatchedReason | T;
|
|
23
23
|
matched: ChildNode[];
|
|
24
24
|
unmatched: ChildNode[];
|
|
@@ -30,16 +30,16 @@ export declare type Result<T extends string = MatchedReason> = {
|
|
|
30
30
|
transparent?: Element;
|
|
31
31
|
};
|
|
32
32
|
};
|
|
33
|
-
export
|
|
34
|
-
export
|
|
35
|
-
export
|
|
36
|
-
export
|
|
33
|
+
export type MatchedReason = 'MATCHED' | 'MATCHED_ZERO';
|
|
34
|
+
export type UnmatchedReason = 'NOTHING' | 'UNEXPECTED_EXTRA_NODE' | 'TRANSPARENT_MODEL_DISALLOWS' | MissingNodeReason;
|
|
35
|
+
export type MissingNodeReason = 'MISSING_NODE_REQUIRED' | 'MISSING_NODE_ONE_OR_MORE';
|
|
36
|
+
export type TransparentModel = {
|
|
37
37
|
el: Element;
|
|
38
38
|
additionalCondition: string;
|
|
39
39
|
};
|
|
40
|
-
export
|
|
40
|
+
export type TagRule = {
|
|
41
41
|
tag: string;
|
|
42
42
|
} & ContentModel;
|
|
43
|
-
export
|
|
43
|
+
export type Options = {
|
|
44
44
|
ignoreHasMutableChildren: boolean;
|
|
45
45
|
};
|
|
@@ -7,7 +7,7 @@ export declare function matches(selector: string, node: ChildNode, specs: Specs)
|
|
|
7
7
|
not?: undefined;
|
|
8
8
|
} | {
|
|
9
9
|
matched: boolean;
|
|
10
|
-
not:
|
|
10
|
+
not: ChildNode | undefined;
|
|
11
11
|
};
|
|
12
12
|
export declare function isRequire(content: PermittedContentPattern): content is PermittedContentRequire;
|
|
13
13
|
export declare function isOptional(content: PermittedContentPattern): content is PermittedContentOptional;
|
|
@@ -18,10 +18,10 @@ export declare function isTransparent(content: PermittedContentPattern): content
|
|
|
18
18
|
export declare class Collection {
|
|
19
19
|
#private;
|
|
20
20
|
constructor(origin: readonly ChildNode[]);
|
|
21
|
-
get matched():
|
|
21
|
+
get matched(): ChildNode[];
|
|
22
22
|
get matchedCount(): number;
|
|
23
|
-
get nodes():
|
|
24
|
-
get unmatched():
|
|
23
|
+
get nodes(): ChildNode[];
|
|
24
|
+
get unmatched(): ChildNode[];
|
|
25
25
|
addMatched(nodes: ChildNode[]): boolean;
|
|
26
26
|
back(): void;
|
|
27
27
|
lock(): void;
|
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.UnsupportedError = exports.Collection = exports.isTransparent = exports.isChoice = exports.isZeroOrMore = exports.isOneOrMore = exports.isOptional = exports.isRequire = exports.matches = exports.isModel = exports.getChildNodesWithoutWhitespaces = void 0;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
6
|
const selector_1 = require("@markuplint/selector");
|
|
7
|
-
const
|
|
7
|
+
const debug_1 = require("./debug");
|
|
8
8
|
const represent_transparent_nodes_1 = require("./represent-transparent-nodes");
|
|
9
9
|
const getChildNodesWithoutWhitespacesCaches = new Map();
|
|
10
10
|
function getChildNodesWithoutWhitespaces(el) {
|
|
@@ -142,33 +142,33 @@ class Collection {
|
|
|
142
142
|
const raw = n.is(n.TEXT_NODE) ? `:text(${n.raw.replace(/\n/g, '\\n')})` : n.raw;
|
|
143
143
|
if (tslib_1.__classPrivateFieldGet(this, _Collection_locked, "f").has(n)) {
|
|
144
144
|
if (represent_transparent_nodes_1.transparentMode.has(n)) {
|
|
145
|
-
out.push(
|
|
145
|
+
out.push(debug_1.bgBlue.bold(raw));
|
|
146
146
|
}
|
|
147
147
|
else {
|
|
148
|
-
out.push(
|
|
148
|
+
out.push(debug_1.bgGreen.bold(raw));
|
|
149
149
|
}
|
|
150
150
|
continue;
|
|
151
151
|
}
|
|
152
152
|
if (tslib_1.__classPrivateFieldGet(this, _Collection_matched, "f").has(n)) {
|
|
153
153
|
if (represent_transparent_nodes_1.transparentMode.has(n)) {
|
|
154
|
-
out.push(
|
|
154
|
+
out.push(debug_1.blue.bold(raw));
|
|
155
155
|
}
|
|
156
156
|
else {
|
|
157
|
-
out.push(
|
|
157
|
+
out.push(debug_1.green.bold(raw));
|
|
158
158
|
}
|
|
159
159
|
continue;
|
|
160
160
|
}
|
|
161
161
|
if (highlightExtraNodes) {
|
|
162
162
|
if (represent_transparent_nodes_1.transparentMode.has(n)) {
|
|
163
|
-
out.push(
|
|
163
|
+
out.push(debug_1.bgMagenta.bold(raw));
|
|
164
164
|
}
|
|
165
165
|
else {
|
|
166
|
-
out.push(
|
|
166
|
+
out.push(debug_1.bgRed.bold(raw));
|
|
167
167
|
}
|
|
168
168
|
continue;
|
|
169
169
|
}
|
|
170
170
|
if (represent_transparent_nodes_1.transparentMode.has(n)) {
|
|
171
|
-
out.push((0,
|
|
171
|
+
out.push((0, debug_1.cyan)(raw));
|
|
172
172
|
}
|
|
173
173
|
else {
|
|
174
174
|
out.push(raw);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
+
const ml_spec_1 = require("@markuplint/ml-spec");
|
|
4
5
|
const helpers_1 = require("../helpers");
|
|
5
6
|
exports.default = (0, ml_core_1.createRule)({
|
|
6
7
|
defaultOptions: {
|
|
@@ -15,15 +16,18 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
15
16
|
if ((0, helpers_1.accnameMayBeMutable)(el, document)) {
|
|
16
17
|
return;
|
|
17
18
|
}
|
|
18
|
-
|
|
19
|
+
if (!(0, ml_spec_1.isExposed)(el, document.specs, el.rule.options.ariaVersion)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const computed = (0, ml_core_1.getComputedRole)(document.specs, el, el.rule.options.ariaVersion);
|
|
19
23
|
if (!computed.role) {
|
|
20
24
|
return;
|
|
21
25
|
}
|
|
22
|
-
const roleSpec = (0, ml_core_1.getRoleSpec)(document.specs, computed.role.name, el.namespaceURI, el.rule.
|
|
26
|
+
const roleSpec = (0, ml_core_1.getRoleSpec)(document.specs, computed.role.name, el.namespaceURI, el.rule.options.ariaVersion);
|
|
23
27
|
if (!roleSpec || !roleSpec.accessibleNameRequired) {
|
|
24
28
|
return;
|
|
25
29
|
}
|
|
26
|
-
const hasAccessibleName = !!el.getAccessibleName(el.rule.
|
|
30
|
+
const hasAccessibleName = !!el.getAccessibleName(el.rule.options.ariaVersion).trim();
|
|
27
31
|
if (!hasAccessibleName) {
|
|
28
32
|
report({ scope: el, message: t('Require {0}', 'accessible name') });
|
|
29
33
|
}
|
|
@@ -26,7 +26,7 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
26
26
|
if (el.rule.value === document.rule.value) {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
|
-
if (el.rule.
|
|
29
|
+
if (el.rule.options.ignoreHasMutableContents && el.hasMutableChildren()) {
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
for (const query of el.rule.value) {
|
package/lib/required-h1/index.js
CHANGED
|
@@ -11,7 +11,7 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
11
11
|
if (document.nodeList.length === 0) {
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
|
-
if (!document.rule.
|
|
14
|
+
if (!document.rule.options['in-document-fragment'] && document.isFragment) {
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
17
|
await document.walkOn('Element', node => {
|
|
@@ -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 (document.rule.
|
|
31
|
+
else if (document.rule.options['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,
|
package/lib/use-list/index.d.ts
CHANGED
package/lib/use-list/index.js
CHANGED
|
@@ -67,7 +67,7 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
69
|
const bullets = textNode.rule.value;
|
|
70
|
-
const spaceNeededBullets = textNode.rule.
|
|
70
|
+
const spaceNeededBullets = textNode.rule.options.spaceNeededBullets || [];
|
|
71
71
|
if (isMayListItem(text, bullets, spaceNeededBullets)) {
|
|
72
72
|
report({
|
|
73
73
|
scope: textNode,
|
|
@@ -4,7 +4,7 @@ exports.checkingAbstractRole = void 0;
|
|
|
4
4
|
const ml_spec_1 = require("@markuplint/ml-spec");
|
|
5
5
|
const checkingAbstractRole = ({ attr }) => t => {
|
|
6
6
|
var _a;
|
|
7
|
-
const { roles } = (0, ml_spec_1.ariaSpecs)(attr.ownerMLDocument.specs, attr.rule.
|
|
7
|
+
const { roles } = (0, ml_spec_1.ariaSpecs)(attr.ownerMLDocument.specs, attr.rule.options.version);
|
|
8
8
|
const tokens = (_a = attr.tokenList) === null || _a === void 0 ? void 0 : _a.allTokens();
|
|
9
9
|
if (!tokens) {
|
|
10
10
|
return;
|
|
@@ -4,7 +4,7 @@ exports.checkingImplicitRole = void 0;
|
|
|
4
4
|
const ml_spec_1 = require("@markuplint/ml-spec");
|
|
5
5
|
const checkingImplicitRole = ({ attr }) => t => {
|
|
6
6
|
var _a;
|
|
7
|
-
const implicitRole = (0, ml_spec_1.getImplicitRoleName)(attr.ownerElement, attr.rule.
|
|
7
|
+
const implicitRole = (0, ml_spec_1.getImplicitRoleName)(attr.ownerElement, attr.rule.options.version, attr.ownerMLDocument.specs);
|
|
8
8
|
const tokens = (_a = attr.tokenList) === null || _a === void 0 ? void 0 : _a.allTokens();
|
|
9
9
|
if (!tokens) {
|
|
10
10
|
return;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.checkingNonExistentRole = void 0;
|
|
4
4
|
const ml_spec_1 = require("@markuplint/ml-spec");
|
|
5
|
-
const
|
|
5
|
+
const checkingNonExistentRole = ({ attr }) => t => {
|
|
6
6
|
var _a;
|
|
7
|
-
const { roles, graphicsRoles } = (0, ml_spec_1.ariaSpecs)(attr.ownerMLDocument.specs, attr.rule.
|
|
7
|
+
const { roles, graphicsRoles } = (0, ml_spec_1.ariaSpecs)(attr.ownerMLDocument.specs, attr.rule.options.version);
|
|
8
8
|
const tokens = (_a = attr.tokenList) === null || _a === void 0 ? void 0 : _a.allTokens();
|
|
9
9
|
if (!tokens) {
|
|
10
10
|
return;
|
|
@@ -25,4 +25,4 @@ const checkingNonExistantRole = ({ attr }) => t => {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
|
-
exports.
|
|
28
|
+
exports.checkingNonExistentRole = checkingNonExistentRole;
|
|
@@ -5,7 +5,7 @@ const ml_spec_1 = require("@markuplint/ml-spec");
|
|
|
5
5
|
const checkingPermittedRoles = ({ attr }) => t => {
|
|
6
6
|
var _a;
|
|
7
7
|
const el = attr.ownerElement;
|
|
8
|
-
const permittedRoles = (0, ml_spec_1.getPermittedRoles)(el, el.rule.
|
|
8
|
+
const permittedRoles = (0, ml_spec_1.getPermittedRoles)(el, el.rule.options.version, attr.ownerMLDocument.specs);
|
|
9
9
|
if (permittedRoles.length === 0) {
|
|
10
10
|
return {
|
|
11
11
|
scope: attr,
|
|
@@ -50,7 +50,7 @@ function getAncestorHasPresentationalChildren(el) {
|
|
|
50
50
|
var _a;
|
|
51
51
|
let current = el.parentElement;
|
|
52
52
|
while (current) {
|
|
53
|
-
const computed = (0, ml_spec_1.getComputedRole)(el.ownerMLDocument.specs, current, el.rule.
|
|
53
|
+
const computed = (0, ml_spec_1.getComputedRole)(el.ownerMLDocument.specs, current, el.rule.options.version);
|
|
54
54
|
if ((_a = computed.role) === null || _a === void 0 ? void 0 : _a.childrenPresentational) {
|
|
55
55
|
return computed;
|
|
56
56
|
}
|
|
@@ -28,18 +28,13 @@ const checkingRequiredOwnedElements = ({ el, role }) => t => {
|
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
// TODO: Needs to resolve `aria-own`
|
|
31
|
-
if (el.isEmpty()) {
|
|
32
|
-
return {
|
|
33
|
-
scope: el,
|
|
34
|
-
message: t('{0}. Or, {1}', t('require {0}', role.requiredOwnedElements.length === 1
|
|
35
|
-
? t('the "{0*}" {1}', role.requiredOwnedElements[0], 'role')
|
|
36
|
-
: t('the {0}', 'roles') + `: ${t(role.requiredOwnedElements)}`), t('require {0}', 'aria-busy="true"')),
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
31
|
const children = Array.from(el.childNodes).map(child => {
|
|
40
32
|
if (child.is(child.ELEMENT_NODE)) {
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
if (child.matches('[aria-busy="true" i]')) {
|
|
34
|
+
return [child, 'BUSY'];
|
|
35
|
+
}
|
|
36
|
+
const computedChild = (0, ml_spec_1.getComputedRole)(child.ownerMLDocument.specs, child, child.rule.options.version);
|
|
37
|
+
if (role.requiredOwnedElements.some(ownedRole => (0, ml_spec_1.isRequiredOwnedElement)(computedChild, ownedRole, child.ownerMLDocument.specs, child.rule.options.version))) {
|
|
43
38
|
return [child, 'REQUIRED'];
|
|
44
39
|
}
|
|
45
40
|
return [child, 'OTHER'];
|
|
@@ -49,6 +44,9 @@ const checkingRequiredOwnedElements = ({ el, role }) => t => {
|
|
|
49
44
|
}
|
|
50
45
|
return [null, 'NO_ELEMENT'];
|
|
51
46
|
});
|
|
47
|
+
if (children.some(([, type]) => type === 'BUSY')) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
52
50
|
/**
|
|
53
51
|
* > Any element that will be owned by the element with this role.
|
|
54
52
|
* > For example, an element with the role list
|
|
@@ -61,6 +59,30 @@ const checkingRequiredOwnedElements = ({ el, role }) => t => {
|
|
|
61
59
|
// TODO: https://github.com/markuplint/markuplint/issues/490
|
|
62
60
|
return;
|
|
63
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Has mutable children
|
|
64
|
+
*
|
|
65
|
+
* Ex:
|
|
66
|
+
*
|
|
67
|
+
* ```jsx
|
|
68
|
+
* <table>
|
|
69
|
+
* <tbody>
|
|
70
|
+
* {list.map((item) => <tr><td>{item}</td></tr>)}
|
|
71
|
+
* </tbody>
|
|
72
|
+
* </table>
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
if (el.hasMutableChildren(true)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (mayBeBeforeCreated(el)) {
|
|
79
|
+
return {
|
|
80
|
+
scope: el,
|
|
81
|
+
message: t('{0}. Or, {1}', t('require {0}', role.requiredOwnedElements.length === 1
|
|
82
|
+
? t('the "{0*}" {1}', role.requiredOwnedElements[0], 'role')
|
|
83
|
+
: t('the {0}', 'roles') + `: ${t(role.requiredOwnedElements)}`), t('require {0}', 'aria-busy="true"')),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
64
86
|
return {
|
|
65
87
|
scope: el,
|
|
66
88
|
message: t('{0} expects {1}', t('the "{0*}" {1}', role.name, 'role'), role.requiredOwnedElements.length === 1
|
|
@@ -69,3 +91,11 @@ const checkingRequiredOwnedElements = ({ el, role }) => t => {
|
|
|
69
91
|
};
|
|
70
92
|
};
|
|
71
93
|
exports.checkingRequiredOwnedElements = checkingRequiredOwnedElements;
|
|
94
|
+
function mayBeBeforeCreated(el) {
|
|
95
|
+
if (el.isEmpty()) {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
return Array.from(el.children).every(child => {
|
|
99
|
+
return ['script', 'template'].includes(child.localName);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
@@ -4,4 +4,10 @@ import type { ARIAProperty, ARIARole } from '@markuplint/ml-spec';
|
|
|
4
4
|
export declare const checkingValue: AttrChecker<boolean, Options, {
|
|
5
5
|
role?: ARIARole | null;
|
|
6
6
|
propSpecs: ARIAProperty[];
|
|
7
|
+
booleanish?: boolean;
|
|
7
8
|
}>;
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
|
|
12
|
+
*/
|
|
13
|
+
export declare function checkAriaValue(type: string, value: string, tokenEnum: string[], booleanish?: boolean): boolean;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.checkingValue = void 0;
|
|
4
|
-
const
|
|
5
|
-
const checkingValue = ({ attr, role, propSpecs }) => t => {
|
|
3
|
+
exports.checkAriaValue = exports.checkingValue = void 0;
|
|
4
|
+
const checkingValue = ({ attr, role, propSpecs, booleanish }) => t => {
|
|
6
5
|
var _a;
|
|
7
6
|
if (attr.isDynamicValue) {
|
|
8
7
|
return;
|
|
9
8
|
}
|
|
10
9
|
const propSpec = propSpecs.find(p => p.name === attr.name);
|
|
11
|
-
const result =
|
|
10
|
+
const result = checkAria(propSpec, attr.value, role === null || role === void 0 ? void 0 : role.name, booleanish);
|
|
12
11
|
if (result.isValid) {
|
|
13
12
|
return;
|
|
14
13
|
}
|
|
@@ -19,3 +18,74 @@ const checkingValue = ({ attr, role, propSpecs }) => t => {
|
|
|
19
18
|
};
|
|
20
19
|
};
|
|
21
20
|
exports.checkingValue = checkingValue;
|
|
21
|
+
function checkAria(propSpec, currentValue, role, booleanish) {
|
|
22
|
+
if (!propSpec) {
|
|
23
|
+
return {
|
|
24
|
+
currentValue,
|
|
25
|
+
// For skipping checking
|
|
26
|
+
isValid: true,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
let valueType = propSpec.value;
|
|
30
|
+
if (role && propSpec.conditionalValue) {
|
|
31
|
+
for (const cond of propSpec.conditionalValue) {
|
|
32
|
+
if (cond.role.includes(role)) {
|
|
33
|
+
valueType = cond.value;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const isValid = checkAriaValue(valueType, currentValue, propSpec.enum, booleanish);
|
|
39
|
+
return {
|
|
40
|
+
...propSpec,
|
|
41
|
+
currentValue,
|
|
42
|
+
isValid,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
|
|
48
|
+
*/
|
|
49
|
+
function checkAriaValue(type, value, tokenEnum, booleanish) {
|
|
50
|
+
switch (type) {
|
|
51
|
+
case 'token': {
|
|
52
|
+
return tokenEnum.includes(value);
|
|
53
|
+
}
|
|
54
|
+
case 'token list': {
|
|
55
|
+
const list = value.split(/\s+/g).map(s => s.trim());
|
|
56
|
+
return list.every(token => tokenEnum.includes(token));
|
|
57
|
+
}
|
|
58
|
+
case 'string':
|
|
59
|
+
case 'ID reference':
|
|
60
|
+
case 'ID reference list': {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
case 'true/false': {
|
|
64
|
+
if (booleanish && value === '') {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return ['true', 'false'].includes(value);
|
|
68
|
+
}
|
|
69
|
+
case 'tristate': {
|
|
70
|
+
if (booleanish && value === '') {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return ['mixed', 'true', 'false', 'undefined'].includes(value);
|
|
74
|
+
}
|
|
75
|
+
case 'true/false/undefined': {
|
|
76
|
+
if (booleanish && value === '') {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
return ['true', 'false', 'undefined'].includes(value);
|
|
80
|
+
}
|
|
81
|
+
case 'integer': {
|
|
82
|
+
return parseInt(value).toString() === value;
|
|
83
|
+
}
|
|
84
|
+
case 'number': {
|
|
85
|
+
return parseFloat(value).toString() === value;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// For skipping checking
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
exports.checkAriaValue = checkAriaValue;
|