@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
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.recursiveBranch = void 0;
|
|
4
|
+
const matches_selector_1 = require("./matches-selector");
|
|
5
|
+
const order_1 = require("./order");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
function recursiveBranch(model, nodes, specs, options, depth) {
|
|
8
|
+
if (!(0, utils_1.isModel)(model)) {
|
|
9
|
+
return (0, order_1.order)(model, nodes, specs, options, depth + 1);
|
|
10
|
+
}
|
|
11
|
+
if (typeof model === 'string') {
|
|
12
|
+
return (0, matches_selector_1.matchesSelector)(model, nodes[0], specs, options, depth);
|
|
13
|
+
}
|
|
14
|
+
const collection = new utils_1.Collection(nodes);
|
|
15
|
+
let lastUnmatched = null;
|
|
16
|
+
for (const query of model) {
|
|
17
|
+
const result = (0, matches_selector_1.matchesSelector)(query, collection.unmatched[0], specs, options, depth);
|
|
18
|
+
collection.addMatched(result.matched);
|
|
19
|
+
if (result.type === 'MATCHED' || result.type === 'MATCHED_ZERO') {
|
|
20
|
+
return {
|
|
21
|
+
type: result.type,
|
|
22
|
+
matched: collection.matched,
|
|
23
|
+
unmatched: collection.unmatched,
|
|
24
|
+
zeroMatch: result.zeroMatch,
|
|
25
|
+
query: result.query,
|
|
26
|
+
hint: result.hint,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
lastUnmatched = {
|
|
30
|
+
type: result.type,
|
|
31
|
+
matched: collection.matched,
|
|
32
|
+
unmatched: collection.unmatched,
|
|
33
|
+
zeroMatch: result.zeroMatch,
|
|
34
|
+
query: result.query,
|
|
35
|
+
hint: result.hint,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (!lastUnmatched) {
|
|
39
|
+
throw new Error('Unreachable code');
|
|
40
|
+
}
|
|
41
|
+
return lastUnmatched;
|
|
42
|
+
}
|
|
43
|
+
exports.recursiveBranch = recursiveBranch;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ChildNode, Options, Result, Specs } from './types';
|
|
2
|
+
export declare const transparentMode: Map<import("packages/@markuplint/ml-core/lib/ml-dom/node/child-node").MLChildNode<import("./types").TagRule[], Options>, true>;
|
|
3
|
+
export declare function representTransparentNodes(nodes: ChildNode[], specs: Specs, options: Options): {
|
|
4
|
+
nodes: ChildNode[];
|
|
5
|
+
errors: Result[];
|
|
6
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.representTransparentNodes = exports.transparentMode = void 0;
|
|
4
|
+
const ml_spec_1 = require("@markuplint/ml-spec");
|
|
5
|
+
const order_1 = require("./order");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
exports.transparentMode = new Map();
|
|
8
|
+
function representTransparentNodes(nodes, specs, options) {
|
|
9
|
+
var _a;
|
|
10
|
+
const result = [];
|
|
11
|
+
const errors = [];
|
|
12
|
+
const parent = (_a = nodes[0]) === null || _a === void 0 ? void 0 : _a.parentElement;
|
|
13
|
+
if (parent) {
|
|
14
|
+
const { errors: parentErrors } = representTransparentNodes([parent], specs, options);
|
|
15
|
+
errors.push(...parentErrors);
|
|
16
|
+
// if (!Array.isArray(parentRes)) {
|
|
17
|
+
// return parentRes;
|
|
18
|
+
// }
|
|
19
|
+
}
|
|
20
|
+
for (const node of nodes) {
|
|
21
|
+
if (!node.is(node.ELEMENT_NODE)) {
|
|
22
|
+
result.push(node);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const models = (0, ml_spec_1.getContentModel)(node, specs.specs);
|
|
26
|
+
if (models == null || typeof models === 'boolean') {
|
|
27
|
+
result.push(node);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const noTransparentModels = models.filter(m => !(0, utils_1.isTransparent)(m));
|
|
31
|
+
if (noTransparentModels.length === models.length) {
|
|
32
|
+
result.push(node);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const collection = new utils_1.Collection((0, utils_1.getChildNodesWithoutWhitespaces)(node));
|
|
36
|
+
let unmatched;
|
|
37
|
+
if (noTransparentModels.length) {
|
|
38
|
+
const result = (0, order_1.order)(noTransparentModels, collection.unmatched, specs, options, Infinity);
|
|
39
|
+
unmatched = result.unmatched;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
unmatched = collection.unmatched;
|
|
43
|
+
}
|
|
44
|
+
const transparent = models.find(m => (0, utils_1.isTransparent)(m));
|
|
45
|
+
if (!transparent || !(0, utils_1.isTransparent)(transparent)) {
|
|
46
|
+
throw new Error('Unreachable code');
|
|
47
|
+
}
|
|
48
|
+
for (const _child of unmatched) {
|
|
49
|
+
const child = _child;
|
|
50
|
+
if (exports.transparentMode.has(child)) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
exports.transparentMode.set(child, true);
|
|
54
|
+
if (child.is(child.ELEMENT_NODE)) {
|
|
55
|
+
const transparentCondMatched = (0, utils_1.matches)(transparent.transparent, child, specs);
|
|
56
|
+
if (!transparentCondMatched.matched) {
|
|
57
|
+
errors.push({
|
|
58
|
+
type: 'TRANSPARENT_MODEL_DISALLOWS',
|
|
59
|
+
matched: [],
|
|
60
|
+
unmatched: [node],
|
|
61
|
+
zeroMatch: false,
|
|
62
|
+
query: transparent.transparent,
|
|
63
|
+
hint: {
|
|
64
|
+
not: transparentCondMatched.not,
|
|
65
|
+
transparent: node,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
result.push(child);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
nodes: result,
|
|
76
|
+
errors,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
exports.representTransparentNodes = representTransparentNodes;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ContentModelResult, Element, Options, Specs } from './types';
|
|
2
|
+
import type { ContentModel } from '@markuplint/ml-spec';
|
|
3
|
+
/**
|
|
4
|
+
* Check start
|
|
5
|
+
*
|
|
6
|
+
* @param contents
|
|
7
|
+
* @param el
|
|
8
|
+
* @param specs
|
|
9
|
+
* @param options
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
export declare function start(contents: ContentModel['contents'], el: Element, specs: Specs, options: Options): ContentModelResult[];
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.start = void 0;
|
|
4
|
+
const order_1 = require("./order");
|
|
5
|
+
const represent_transparent_nodes_1 = require("./represent-transparent-nodes");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
/**
|
|
8
|
+
* Check start
|
|
9
|
+
*
|
|
10
|
+
* @param contents
|
|
11
|
+
* @param el
|
|
12
|
+
* @param specs
|
|
13
|
+
* @param options
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
function start(contents, el, specs, options) {
|
|
17
|
+
var _a;
|
|
18
|
+
if (contents === false) {
|
|
19
|
+
if (el.childNodes.length) {
|
|
20
|
+
return [
|
|
21
|
+
{
|
|
22
|
+
type: 'VOID_ELEMENT',
|
|
23
|
+
scope: el,
|
|
24
|
+
query: ':not(*)',
|
|
25
|
+
hint: {},
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
return [
|
|
30
|
+
{
|
|
31
|
+
type: 'MATCHED',
|
|
32
|
+
scope: el,
|
|
33
|
+
query: '*',
|
|
34
|
+
hint: {},
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
if (contents === true) {
|
|
39
|
+
// Allows all elements
|
|
40
|
+
return [
|
|
41
|
+
{
|
|
42
|
+
type: 'MATCHED',
|
|
43
|
+
scope: el,
|
|
44
|
+
query: '*',
|
|
45
|
+
hint: {},
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
const { nodes, errors } = (0, represent_transparent_nodes_1.representTransparentNodes)((0, utils_1.getChildNodesWithoutWhitespaces)(el), specs, options);
|
|
50
|
+
const result = (0, order_1.order)(contents, nodes, specs, options, 0);
|
|
51
|
+
return [
|
|
52
|
+
{
|
|
53
|
+
type: result.type,
|
|
54
|
+
scope: result.type === 'MISSING_NODE_REQUIRED' || result.type === 'MISSING_NODE_ONE_OR_MORE'
|
|
55
|
+
? el
|
|
56
|
+
: (_a = result.unmatched[0]) !== null && _a !== void 0 ? _a : el,
|
|
57
|
+
query: result.query,
|
|
58
|
+
hint: result.hint,
|
|
59
|
+
},
|
|
60
|
+
...errors.map(error => {
|
|
61
|
+
var _a;
|
|
62
|
+
return ({
|
|
63
|
+
type: error.type,
|
|
64
|
+
scope: (_a = error.unmatched[0]) !== null && _a !== void 0 ? _a : el,
|
|
65
|
+
query: error.query,
|
|
66
|
+
hint: error.hint,
|
|
67
|
+
});
|
|
68
|
+
}),
|
|
69
|
+
];
|
|
70
|
+
}
|
|
71
|
+
exports.start = start;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transparent = void 0;
|
|
4
|
+
const count_pattern_1 = require("./count-pattern");
|
|
5
|
+
const debug_1 = require("./debug");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
const transparentLog = debug_1.cmLog.extend('transparent');
|
|
8
|
+
function transparent(nodes, specs, options, depth) {
|
|
9
|
+
var _a;
|
|
10
|
+
if (nodes.length === 0 || ((_a = nodes[0].parentElement) === null || _a === void 0 ? void 0 : _a.parentElement)) {
|
|
11
|
+
transparentLog('Skipped');
|
|
12
|
+
return {
|
|
13
|
+
type: nodes.length === 0 ? 'MATCHED_ZERO' : 'MATCHED',
|
|
14
|
+
matched: nodes.slice(),
|
|
15
|
+
unmatched: [],
|
|
16
|
+
zeroMatch: nodes.length === 0,
|
|
17
|
+
query: 'transparent',
|
|
18
|
+
hint: {},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
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
|
+
return {
|
|
26
|
+
type: result.type,
|
|
27
|
+
matched: collection.matched,
|
|
28
|
+
unmatched: collection.unmatched,
|
|
29
|
+
zeroMatch: result.zeroMatch,
|
|
30
|
+
query: result.query,
|
|
31
|
+
hint: result.hint,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
exports.transparent = transparent;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Element as _Element } from '@markuplint/ml-core';
|
|
2
|
+
import type { ContentModel, MLMLSpec } from '@markuplint/ml-spec';
|
|
3
|
+
export declare type Element = _Element<TagRule[], Options>;
|
|
4
|
+
export declare type ChildNode = Element['childNodes'][0];
|
|
5
|
+
export declare type Specs = {
|
|
6
|
+
cites: MLMLSpec['cites'];
|
|
7
|
+
def: MLMLSpec['def'];
|
|
8
|
+
specs: {
|
|
9
|
+
name: string;
|
|
10
|
+
contentModel: {
|
|
11
|
+
contents: MLMLSpec['specs'][0]['contentModel']['contents'];
|
|
12
|
+
};
|
|
13
|
+
}[];
|
|
14
|
+
};
|
|
15
|
+
export declare type ContentModelResult = {
|
|
16
|
+
type: MatchedReason | UnmatchedReason;
|
|
17
|
+
scope: ChildNode;
|
|
18
|
+
query: Result['query'];
|
|
19
|
+
hint: Result['hint'];
|
|
20
|
+
};
|
|
21
|
+
export declare type Result<T extends string = MatchedReason> = {
|
|
22
|
+
type: MatchedReason | UnmatchedReason | T;
|
|
23
|
+
matched: ChildNode[];
|
|
24
|
+
unmatched: ChildNode[];
|
|
25
|
+
zeroMatch: boolean;
|
|
26
|
+
query: string;
|
|
27
|
+
hint: {
|
|
28
|
+
max?: number;
|
|
29
|
+
not?: ChildNode;
|
|
30
|
+
transparent?: Element;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export declare type MatchedReason = 'MATCHED' | 'MATCHED_ZERO';
|
|
34
|
+
export declare type UnmatchedReason = 'VOID_ELEMENT' | 'UNEXPECTED_EXTRA_NODE' | 'TRANSPARENT_MODEL_DISALLOWS' | MissingNodeReason;
|
|
35
|
+
export declare type MissingNodeReason = 'MISSING_NODE_REQUIRED' | 'MISSING_NODE_ONE_OR_MORE';
|
|
36
|
+
export declare type TransparentModel = {
|
|
37
|
+
el: Element;
|
|
38
|
+
additionalCondition: string;
|
|
39
|
+
};
|
|
40
|
+
export declare type TagRule = {
|
|
41
|
+
tag: string;
|
|
42
|
+
} & ContentModel;
|
|
43
|
+
export declare type Options = {
|
|
44
|
+
ignoreHasMutableChildren: boolean;
|
|
45
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ChildNode, Element, Specs } from './types';
|
|
2
|
+
import type { PermittedContentPattern, PermittedContentChoice, PermittedContentOneOrMore, PermittedContentOptional, PermittedContentRequire, PermittedContentTransparent, PermittedContentZeroOrMore, Model } from '@markuplint/ml-spec';
|
|
3
|
+
export declare function getChildNodesWithoutWhitespaces(el: Element): ChildNode[];
|
|
4
|
+
export declare function isModel(model: Model | PermittedContentPattern[]): model is Model;
|
|
5
|
+
export declare function matches(selector: string, node: ChildNode, specs: Specs): {
|
|
6
|
+
matched: boolean;
|
|
7
|
+
not?: undefined;
|
|
8
|
+
} | {
|
|
9
|
+
matched: boolean;
|
|
10
|
+
not: import("packages/@markuplint/ml-core/lib/ml-dom/node/child-node").MLChildNode<import("./types").TagRule[], import("./types").Options> | undefined;
|
|
11
|
+
};
|
|
12
|
+
export declare function isRequire(content: PermittedContentPattern): content is PermittedContentRequire;
|
|
13
|
+
export declare function isOptional(content: PermittedContentPattern): content is PermittedContentOptional;
|
|
14
|
+
export declare function isOneOrMore(content: PermittedContentPattern): content is PermittedContentOneOrMore;
|
|
15
|
+
export declare function isZeroOrMore(content: PermittedContentPattern): content is PermittedContentZeroOrMore;
|
|
16
|
+
export declare function isChoice(content: PermittedContentPattern): content is PermittedContentChoice;
|
|
17
|
+
export declare function isTransparent(content: PermittedContentPattern): content is PermittedContentTransparent;
|
|
18
|
+
export declare class Collection {
|
|
19
|
+
#private;
|
|
20
|
+
constructor(origin: readonly ChildNode[]);
|
|
21
|
+
get matched(): import("packages/@markuplint/ml-core/lib/ml-dom/node/child-node").MLChildNode<import("./types").TagRule[], import("./types").Options>[];
|
|
22
|
+
get matchedCount(): number;
|
|
23
|
+
get nodes(): import("packages/@markuplint/ml-core/lib/ml-dom/node/child-node").MLChildNode<import("./types").TagRule[], import("./types").Options>[];
|
|
24
|
+
get unmatched(): import("packages/@markuplint/ml-core/lib/ml-dom/node/child-node").MLChildNode<import("./types").TagRule[], import("./types").Options>[];
|
|
25
|
+
addMatched(nodes: ChildNode[]): boolean;
|
|
26
|
+
back(): void;
|
|
27
|
+
lock(): void;
|
|
28
|
+
max(max: number): void;
|
|
29
|
+
toString(highlightExtraNodes?: boolean): string;
|
|
30
|
+
}
|
|
31
|
+
export declare class UnsupportedError extends Error {
|
|
32
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _Collection_locked, _Collection_matched, _Collection_nodes, _Collection_origin;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const selector_1 = require("@markuplint/selector");
|
|
7
|
+
const ansi_colors_1 = require("ansi-colors");
|
|
8
|
+
const represent_transparent_nodes_1 = require("./represent-transparent-nodes");
|
|
9
|
+
const getChildNodesWithoutWhitespacesCaches = new Map();
|
|
10
|
+
function getChildNodesWithoutWhitespaces(el) {
|
|
11
|
+
let nodes = getChildNodesWithoutWhitespacesCaches.get(el);
|
|
12
|
+
if (nodes) {
|
|
13
|
+
return nodes;
|
|
14
|
+
}
|
|
15
|
+
nodes = Array.from(el.childNodes).filter(node => {
|
|
16
|
+
return !(node.is(node.TEXT_NODE) && node.isWhitespace());
|
|
17
|
+
});
|
|
18
|
+
getChildNodesWithoutWhitespacesCaches.set(el, nodes);
|
|
19
|
+
return nodes;
|
|
20
|
+
}
|
|
21
|
+
exports.getChildNodesWithoutWhitespaces = getChildNodesWithoutWhitespaces;
|
|
22
|
+
function isModel(model) {
|
|
23
|
+
if (typeof model === 'string') {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
let modelMode = false;
|
|
27
|
+
for (const m of model) {
|
|
28
|
+
if (typeof m === 'string') {
|
|
29
|
+
modelMode = true;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (modelMode) {
|
|
33
|
+
throw new TypeError(`Invalid schema: ${JSON.stringify(model)}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return modelMode;
|
|
37
|
+
}
|
|
38
|
+
exports.isModel = isModel;
|
|
39
|
+
function matches(selector, node, specs) {
|
|
40
|
+
const selectorResult = (0, selector_1.createSelector)(selector, specs).search(node);
|
|
41
|
+
const matched = selectorResult.filter((r) => r.matched);
|
|
42
|
+
if (matched.length) {
|
|
43
|
+
return {
|
|
44
|
+
matched: true,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const not = selectorResult
|
|
48
|
+
.map(r => { var _a; return (r.matched ? [] : (_a = r.not) !== null && _a !== void 0 ? _a : []); })
|
|
49
|
+
.flat()
|
|
50
|
+
.map(descendants)
|
|
51
|
+
.flat()
|
|
52
|
+
.shift();
|
|
53
|
+
return {
|
|
54
|
+
matched: false,
|
|
55
|
+
not,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
exports.matches = matches;
|
|
59
|
+
function descendants(selectorResult) {
|
|
60
|
+
let nodes = selectorResult.nodes.slice();
|
|
61
|
+
while (selectorResult.has.length) {
|
|
62
|
+
for (const dep of selectorResult.has) {
|
|
63
|
+
if (!dep.has.length) {
|
|
64
|
+
nodes = dep.nodes;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
selectorResult = dep;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
return nodes;
|
|
73
|
+
}
|
|
74
|
+
function isRequire(content) {
|
|
75
|
+
return 'require' in content;
|
|
76
|
+
}
|
|
77
|
+
exports.isRequire = isRequire;
|
|
78
|
+
function isOptional(content) {
|
|
79
|
+
return 'optional' in content;
|
|
80
|
+
}
|
|
81
|
+
exports.isOptional = isOptional;
|
|
82
|
+
function isOneOrMore(content) {
|
|
83
|
+
return 'oneOrMore' in content;
|
|
84
|
+
}
|
|
85
|
+
exports.isOneOrMore = isOneOrMore;
|
|
86
|
+
function isZeroOrMore(content) {
|
|
87
|
+
return 'zeroOrMore' in content;
|
|
88
|
+
}
|
|
89
|
+
exports.isZeroOrMore = isZeroOrMore;
|
|
90
|
+
function isChoice(content) {
|
|
91
|
+
return 'choice' in content;
|
|
92
|
+
}
|
|
93
|
+
exports.isChoice = isChoice;
|
|
94
|
+
function isTransparent(content) {
|
|
95
|
+
return 'transparent' in content;
|
|
96
|
+
}
|
|
97
|
+
exports.isTransparent = isTransparent;
|
|
98
|
+
class Collection {
|
|
99
|
+
constructor(origin) {
|
|
100
|
+
_Collection_locked.set(this, new Set());
|
|
101
|
+
_Collection_matched.set(this, new Set());
|
|
102
|
+
_Collection_nodes.set(this, void 0);
|
|
103
|
+
_Collection_origin.set(this, void 0);
|
|
104
|
+
tslib_1.__classPrivateFieldSet(this, _Collection_origin, origin.slice(), "f");
|
|
105
|
+
tslib_1.__classPrivateFieldSet(this, _Collection_nodes, new Set(tslib_1.__classPrivateFieldGet(this, _Collection_origin, "f")), "f");
|
|
106
|
+
}
|
|
107
|
+
get matched() {
|
|
108
|
+
return Array.from(tslib_1.__classPrivateFieldGet(this, _Collection_matched, "f"));
|
|
109
|
+
}
|
|
110
|
+
get matchedCount() {
|
|
111
|
+
return tslib_1.__classPrivateFieldGet(this, _Collection_matched, "f").size;
|
|
112
|
+
}
|
|
113
|
+
get nodes() {
|
|
114
|
+
return tslib_1.__classPrivateFieldGet(this, _Collection_origin, "f").slice();
|
|
115
|
+
}
|
|
116
|
+
get unmatched() {
|
|
117
|
+
return Array.from(tslib_1.__classPrivateFieldGet(this, _Collection_nodes, "f")).filter(n => !tslib_1.__classPrivateFieldGet(this, _Collection_matched, "f").has(n));
|
|
118
|
+
}
|
|
119
|
+
addMatched(nodes) {
|
|
120
|
+
const i = tslib_1.__classPrivateFieldGet(this, _Collection_matched, "f").size;
|
|
121
|
+
for (const node of nodes) {
|
|
122
|
+
if (!tslib_1.__classPrivateFieldGet(this, _Collection_nodes, "f").has(node)) {
|
|
123
|
+
throw new ReferenceError(`External Node: ${node.nodeName}`);
|
|
124
|
+
}
|
|
125
|
+
tslib_1.__classPrivateFieldGet(this, _Collection_matched, "f").add(node);
|
|
126
|
+
}
|
|
127
|
+
return i < tslib_1.__classPrivateFieldGet(this, _Collection_matched, "f").size;
|
|
128
|
+
}
|
|
129
|
+
back() {
|
|
130
|
+
tslib_1.__classPrivateFieldSet(this, _Collection_matched, new Set(tslib_1.__classPrivateFieldGet(this, _Collection_locked, "f")), "f");
|
|
131
|
+
}
|
|
132
|
+
lock() {
|
|
133
|
+
tslib_1.__classPrivateFieldSet(this, _Collection_locked, new Set(tslib_1.__classPrivateFieldGet(this, _Collection_matched, "f")), "f");
|
|
134
|
+
}
|
|
135
|
+
max(max) {
|
|
136
|
+
const sliced = Array.from(tslib_1.__classPrivateFieldGet(this, _Collection_matched, "f")).slice(max);
|
|
137
|
+
sliced.forEach(n => tslib_1.__classPrivateFieldGet(this, _Collection_matched, "f").delete(n));
|
|
138
|
+
}
|
|
139
|
+
toString(highlightExtraNodes = false) {
|
|
140
|
+
const out = [];
|
|
141
|
+
for (const n of tslib_1.__classPrivateFieldGet(this, _Collection_origin, "f")) {
|
|
142
|
+
const raw = n.is(n.TEXT_NODE) ? `:text(${n.raw.replace(/\n/g, '\\n')})` : n.raw;
|
|
143
|
+
if (tslib_1.__classPrivateFieldGet(this, _Collection_locked, "f").has(n)) {
|
|
144
|
+
if (represent_transparent_nodes_1.transparentMode.has(n)) {
|
|
145
|
+
out.push(ansi_colors_1.bgBlue.bold(raw));
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
out.push(ansi_colors_1.bgGreen.bold(raw));
|
|
149
|
+
}
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (tslib_1.__classPrivateFieldGet(this, _Collection_matched, "f").has(n)) {
|
|
153
|
+
if (represent_transparent_nodes_1.transparentMode.has(n)) {
|
|
154
|
+
out.push(ansi_colors_1.blue.bold(raw));
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
out.push(ansi_colors_1.green.bold(raw));
|
|
158
|
+
}
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (highlightExtraNodes) {
|
|
162
|
+
if (represent_transparent_nodes_1.transparentMode.has(n)) {
|
|
163
|
+
out.push(ansi_colors_1.bgMagenta.bold(raw));
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
out.push(ansi_colors_1.bgRed.bold(raw));
|
|
167
|
+
}
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (represent_transparent_nodes_1.transparentMode.has(n)) {
|
|
171
|
+
out.push((0, ansi_colors_1.cyan)(raw));
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
out.push(raw);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return `[ ${out.join(', ')} ]`;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
exports.Collection = Collection;
|
|
181
|
+
_Collection_locked = new WeakMap(), _Collection_matched = new WeakMap(), _Collection_nodes = new WeakMap(), _Collection_origin = new WeakMap();
|
|
182
|
+
class UnsupportedError extends Error {
|
|
183
|
+
}
|
|
184
|
+
exports.UnsupportedError = UnsupportedError;
|
|
@@ -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,20 +3,27 @@ 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 => {
|
|
11
|
+
var _a;
|
|
12
|
+
if (((_a = el.pretenderContext) === null || _a === void 0 ? void 0 : _a.type) === 'pretender') {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
8
15
|
if ((0, helpers_1.accnameMayBeMutable)(el, document)) {
|
|
9
16
|
return;
|
|
10
17
|
}
|
|
11
|
-
const
|
|
12
|
-
if (!role) {
|
|
18
|
+
const computed = (0, ml_core_1.getComputedRole)(document.specs, el, el.rule.option.ariaVersion);
|
|
19
|
+
if (!computed.role) {
|
|
13
20
|
return;
|
|
14
21
|
}
|
|
15
|
-
const roleSpec = (0,
|
|
22
|
+
const roleSpec = (0, ml_core_1.getRoleSpec)(document.specs, computed.role.name, el.namespaceURI, el.rule.option.ariaVersion);
|
|
16
23
|
if (!roleSpec || !roleSpec.accessibleNameRequired) {
|
|
17
24
|
return;
|
|
18
25
|
}
|
|
19
|
-
const hasAccessibleName = !!el.getAccessibleName().trim();
|
|
26
|
+
const hasAccessibleName = !!el.getAccessibleName(el.rule.option.ariaVersion).trim();
|
|
20
27
|
if (!hasAccessibleName) {
|
|
21
28
|
report({ scope: el, message: t('Require {0}', 'accessible name') });
|
|
22
29
|
}
|
|
@@ -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.elementType === 'html') {
|
|
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,
|