@markuplint/rules 3.0.0-alpha.66 → 3.0.0-dev.176
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 +22 -10
- package/lib/attr-check.js +32 -23
- package/lib/attr-duplication/index.d.ts +3 -1
- package/lib/attr-duplication/index.js +3 -2
- package/lib/attr-value-quotes/index.d.ts +5 -5
- package/lib/attr-value-quotes/index.js +1 -1
- package/lib/case-sensitive-attr-name/index.d.ts +2 -2
- package/lib/case-sensitive-attr-name/index.js +3 -3
- package/lib/case-sensitive-tag-name/index.d.ts +2 -2
- package/lib/case-sensitive-tag-name/index.js +3 -3
- package/lib/character-reference/index.d.ts +1 -1
- package/lib/character-reference/index.js +1 -1
- package/lib/class-naming/index.d.ts +2 -2
- package/lib/class-naming/index.js +3 -5
- package/lib/create-message.d.ts +13 -2
- package/lib/create-message.js +9 -8
- package/lib/debug.d.ts +1 -1
- package/lib/debug.js +1 -1
- package/lib/deprecated-attr/index.d.ts +3 -1
- package/lib/deprecated-element/index.d.ts +3 -1
- package/lib/deprecated-element/index.js +4 -4
- package/lib/disallowed-element/index.d.ts +1 -1
- package/lib/doctype/index.d.ts +3 -3
- package/lib/doctype/index.js +2 -2
- package/lib/end-tag/index.d.ts +1 -1
- package/lib/end-tag/index.js +3 -18
- package/lib/helpers.d.ts +38 -47
- package/lib/helpers.js +42 -93
- package/lib/id-duplication/index.d.ts +3 -1
- package/lib/index.d.ts +242 -62
- package/lib/index.js +10 -1
- package/lib/ineffective-attr/index.d.ts +3 -1
- package/lib/ineffective-attr/index.js +3 -6
- package/lib/invalid-attr/index.d.ts +40 -12
- package/lib/invalid-attr/index.js +159 -28
- package/lib/label-has-control/index.d.ts +4 -0
- package/lib/label-has-control/index.js +28 -0
- package/lib/landmark-roles/index.d.ts +6 -6
- package/lib/landmark-roles/index.js +10 -6
- package/lib/no-boolean-attr-value/index.d.ts +3 -1
- package/lib/no-boolean-attr-value/index.js +1 -1
- package/lib/no-default-value/index.d.ts +3 -1
- package/lib/no-default-value/index.js +1 -1
- package/lib/no-empty-palpable-content/index.d.ts +6 -0
- package/lib/no-empty-palpable-content/index.js +42 -0
- package/lib/no-hard-code-id/index.d.ts +3 -1
- package/lib/no-hard-code-id/index.js +1 -1
- package/lib/no-refer-to-non-existent-id/index.d.ts +9 -4
- package/lib/no-refer-to-non-existent-id/index.js +65 -5
- package/lib/no-use-event-handler-attr/index.d.ts +3 -3
- package/lib/no-use-event-handler-attr/index.js +6 -6
- package/lib/permitted-contents/choice.d.ts +10 -0
- package/lib/permitted-contents/choice.js +72 -0
- package/lib/permitted-contents/complex-branch.d.ts +20 -0
- package/lib/permitted-contents/complex-branch.js +29 -0
- package/lib/permitted-contents/content-model.d.ts +2 -0
- package/lib/permitted-contents/content-model.js +53 -0
- package/lib/permitted-contents/count-pattern.d.ts +29 -0
- package/lib/permitted-contents/count-pattern.js +162 -0
- 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 +3 -0
- package/lib/permitted-contents/debug.js +13 -0
- package/lib/permitted-contents/index.d.ts +2 -8
- package/lib/permitted-contents/index.js +76 -249
- package/lib/permitted-contents/matches-selector.d.ts +8 -0
- package/lib/permitted-contents/matches-selector.js +187 -0
- package/lib/permitted-contents/order.d.ts +20 -0
- package/lib/permitted-contents/order.js +99 -0
- package/lib/permitted-contents/recursive-branch.d.ts +11 -0
- package/lib/permitted-contents/recursive-branch.js +45 -0
- package/lib/permitted-contents/represent-transparent-nodes.d.ts +10 -0
- package/lib/permitted-contents/represent-transparent-nodes.js +78 -0
- package/lib/permitted-contents/start.d.ts +18 -0
- package/lib/permitted-contents/start.js +73 -0
- package/lib/permitted-contents/transparent.d.ts +2 -0
- package/lib/permitted-contents/transparent.js +31 -0
- package/lib/permitted-contents/types.d.ts +52 -0
- package/lib/permitted-contents/types.js +2 -0
- package/lib/permitted-contents/utils.d.ts +100 -0
- package/lib/permitted-contents/utils.js +302 -0
- package/lib/placeholder-label-option/index.d.ts +2 -0
- package/lib/placeholder-label-option/index.js +88 -0
- package/lib/require-accessible-name/index.d.ts +3 -3
- package/lib/require-accessible-name/index.js +12 -4
- package/lib/require-datetime/index.d.ts +6 -0
- package/lib/require-datetime/index.js +34 -0
- package/lib/require-datetime/types.d.ts +10 -0
- package/lib/require-datetime/types.js +2 -0
- package/lib/require-datetime/utils.d.ts +11 -0
- package/lib/require-datetime/utils.js +137 -0
- package/lib/required-attr/index.d.ts +5 -5
- package/lib/required-attr/index.js +20 -17
- package/lib/required-element/index.d.ts +3 -3
- package/lib/required-element/index.js +3 -2
- package/lib/required-h1/index.d.ts +3 -3
- package/lib/required-h1/index.js +4 -3
- package/lib/use-list/index.d.ts +4 -4
- package/lib/use-list/index.js +9 -7
- package/lib/wai-aria/checkings/_.d.ts +15 -0
- package/lib/wai-aria/checkings/_.js +27 -0
- package/lib/wai-aria/checkings/abstract-role.js +1 -1
- package/lib/wai-aria/checkings/default-value.d.ts +7 -3
- package/lib/wai-aria/checkings/deprecated-props.d.ts +8 -4
- package/lib/wai-aria/checkings/disallowed-prop.d.ts +8 -4
- package/lib/wai-aria/checkings/disallowed-prop.js +27 -3
- package/lib/wai-aria/checkings/implicit-props.d.ts +8 -4
- package/lib/wai-aria/checkings/implicit-props.js +3 -2
- package/lib/wai-aria/checkings/implicit-role.js +2 -2
- package/lib/wai-aria/checkings/interaction-in-hidden.d.ts +11 -0
- package/lib/wai-aria/checkings/interaction-in-hidden.js +49 -0
- package/lib/wai-aria/checkings/no-global-prop.d.ts +7 -3
- 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.d.ts +29 -0
- package/lib/wai-aria/checkings/presentational-children.js +62 -0
- package/lib/wai-aria/checkings/{checking-required-owned-elements.d.ts → required-owned-elements.d.ts} +7 -3
- package/lib/wai-aria/checkings/required-owned-elements.js +103 -0
- package/lib/wai-aria/checkings/required-prop copy.d.ts +15 -0
- package/lib/wai-aria/checkings/required-prop copy.js +27 -0
- package/lib/wai-aria/checkings/required-prop.d.ts +12 -6
- package/lib/wai-aria/checkings/unadopted-explicit-roles.d.ts +15 -0
- package/lib/wai-aria/checkings/unadopted-explicit-roles.js +17 -0
- package/lib/wai-aria/checkings/value.d.ts +19 -4
- package/lib/wai-aria/checkings/value.js +77 -5
- package/lib/wai-aria/index.d.ts +1 -1
- package/lib/wai-aria/index.js +27 -16
- package/lib/wai-aria/types.d.ts +11 -9
- package/lib/xxx/index.d.ts +2 -0
- package/lib/xxx/index.js +32 -0
- package/package.json +18 -12
- package/schema.json +12 -0
- package/test/attr-check.spec.js +77 -0
- package/test/attr-duplication/index.spec.js +159 -0
- package/test/attr-value-quotes/index.spec.js +133 -0
- package/test/case-sensitive-attr-name/index.spec.js +65 -0
- package/test/case-sensitive-tag-name/index.spec.js +80 -0
- package/test/character-reference/index.spec.js +57 -0
- package/test/class-naming/index.spec.js +470 -0
- package/test/create-message.spec.js +497 -0
- package/test/deprecated-attr/index.spec.js +48 -0
- package/test/deprecated-element/index.spec.js +48 -0
- package/test/disallowed-element/index.spec.js +90 -0
- package/test/doctype/index.spec.js +50 -0
- package/test/end-tag/index.spec.js +162 -0
- package/test/id-duplication/index.spec.js +47 -0
- package/test/ineffective-attr/index.spec.js +31 -0
- package/test/invalid-attr/index.spec.js +1632 -0
- package/test/label-has-control/index.spec.js +29 -0
- package/test/landmark-roles/index.spec.js +187 -0
- package/test/no-boolean-attr-value/index.spec.js +41 -0
- package/test/no-default-value/index.spec.js +74 -0
- package/test/no-empty-palpable-content/index.spec.js +115 -0
- package/test/no-hard-code-id/index.spec.js +100 -0
- package/test/no-refer-to-non-existent-id/index.spec.js +254 -0
- package/test/no-use-event-handler-attr/index.spec.js +57 -0
- package/test/permitted-contents/choice.spec.js +174 -0
- package/test/permitted-contents/count-pattern.spec.js +308 -0
- package/test/permitted-contents/index.spec.js +1371 -0
- package/test/permitted-contents/matches-selector.spec.js +59 -0
- package/test/permitted-contents/order.spec.js +351 -0
- package/test/permitted-contents/recursive-branch.spec.js +41 -0
- package/test/permitted-contents/represent-transparent-nodes.spec.js +24 -0
- package/test/permitted-contents/start.spec.js +67 -0
- package/test/placeholder-label-option/index.spec.js +113 -0
- package/test/require-accessible-name/index.spec.js +446 -0
- package/test/require-datetime/index.spec.js +54 -0
- package/test/require-datetime/utils.spec.js +52 -0
- package/test/required-attr/index.spec.js +414 -0
- package/test/required-element/index.spec.js +188 -0
- package/test/required-h1/index.spec.js +69 -0
- package/test/use-list/index.spec.js +109 -0
- package/test/wai-aria/checkings/value.spec.js +33 -0
- package/test/wai-aria/index.spec.js +1173 -0
- package/lib/__foo/index.d.ts +0 -2
- package/lib/__foo/index.js +0 -46
- 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/helper/aria/get-aria.d.ts +0 -7
- package/lib/helper/aria/get-aria.js +0 -53
- package/lib/helper/aria/get-computed-role.d.ts +0 -10
- package/lib/helper/aria/get-computed-role.js +0 -24
- package/lib/helper/aria/get-implicit-role.d.ts +0 -7
- package/lib/helper/aria/get-implicit-role.js +0 -12
- package/lib/helper/aria/get-permitted-roles.d.ts +0 -14
- package/lib/helper/aria/get-permitted-roles.js +0 -26
- package/lib/helper/aria/resolve-version.d.ts +0 -2
- package/lib/helper/aria/resolve-version.js +0 -21
- package/lib/helper/spec/aria-spec.d.ts +0 -5
- package/lib/helper/spec/aria-spec.js +0 -12
- package/lib/helper/spec/get-role-spec.d.ts +0 -11
- package/lib/helper/spec/get-role-spec.js +0 -39
- package/lib/helper/spec/html-spec.d.ts +0 -2
- package/lib/helper/spec/html-spec.js +0 -14
- 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 -230
- 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/wai-aria/checkings/checking-required-owned-elements.js +0 -63
- package/tsconfig.test.json +0 -3
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1,27 +1,50 @@
|
|
|
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");
|
|
5
|
+
const shared_1 = require("@markuplint/shared");
|
|
6
|
+
const HYPERLINK_SELECTOR = 'a[href], area[href]';
|
|
4
7
|
exports.default = (0, ml_core_1.createRule)({
|
|
5
8
|
defaultOptions: {
|
|
6
|
-
ariaVersion:
|
|
9
|
+
ariaVersion: ml_spec_1.ARIA_RECOMMENDED_VERSION,
|
|
10
|
+
fragmentRefersNameAttr: false,
|
|
7
11
|
},
|
|
8
12
|
async verify({ document, report, t }) {
|
|
9
13
|
const idList = new Set();
|
|
14
|
+
const nameList = new Set();
|
|
10
15
|
let hasDynamicId = false;
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
let hasDynamicName = false;
|
|
17
|
+
const isMutable = document.nodeList.some(node => node.is(node.MARKUPLINT_PREPROCESSOR_BLOCK));
|
|
18
|
+
if (isMutable) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
document.querySelectorAll('[id]').forEach(el => {
|
|
22
|
+
const attr = el.getAttributeNode('id');
|
|
23
|
+
if (!attr) {
|
|
13
24
|
return;
|
|
14
25
|
}
|
|
15
26
|
if (attr.isDynamicValue) {
|
|
16
27
|
hasDynamicId = true;
|
|
17
28
|
}
|
|
18
29
|
if (attr.valueType !== 'code') {
|
|
19
|
-
idList.add(attr.value);
|
|
30
|
+
idList.add((0, shared_1.decodeEntities)(attr.value));
|
|
20
31
|
}
|
|
21
32
|
});
|
|
22
33
|
if (hasDynamicId) {
|
|
23
34
|
return;
|
|
24
35
|
}
|
|
36
|
+
document.querySelectorAll('[name]').forEach(el => {
|
|
37
|
+
const attr = el.getAttributeNode('name');
|
|
38
|
+
if (!attr) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (attr.isDynamicValue) {
|
|
42
|
+
hasDynamicName = true;
|
|
43
|
+
}
|
|
44
|
+
if (attr.valueType !== 'code') {
|
|
45
|
+
nameList.add((0, shared_1.decodeEntities)(attr.value));
|
|
46
|
+
}
|
|
47
|
+
});
|
|
25
48
|
await document.walkOn('Attr', attr => {
|
|
26
49
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
27
50
|
const attrSpec = (0, ml_core_1.getAttrSpecs)(attr.ownerElement, document.specs);
|
|
@@ -69,7 +92,7 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
69
92
|
}
|
|
70
93
|
}
|
|
71
94
|
}
|
|
72
|
-
const { props } = (0, ml_core_1.ariaSpecs)(document.specs, attr.rule.
|
|
95
|
+
const { props } = (0, ml_core_1.ariaSpecs)(document.specs, attr.rule.options.ariaVersion);
|
|
73
96
|
const aria = props.find(prop => prop.name === name);
|
|
74
97
|
if (aria) {
|
|
75
98
|
if (aria.value === 'ID reference' && !idList.has(value)) {
|
|
@@ -100,5 +123,42 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
100
123
|
}
|
|
101
124
|
}
|
|
102
125
|
});
|
|
126
|
+
/**
|
|
127
|
+
* @see https://html.spec.whatwg.org/multipage/browsing-the-web.html#scrolling-to-a-fragment
|
|
128
|
+
*/
|
|
129
|
+
await document.walkOn('Element', el => {
|
|
130
|
+
var _a, _b, _c, _d;
|
|
131
|
+
if (el.rule.options.fragmentRefersNameAttr && hasDynamicName) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (!el.matches(HYPERLINK_SELECTOR)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const href = el.getAttributeNode('href');
|
|
138
|
+
if (!href) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const rawFragment = (_a = href.value.match(/^#(.+)/)) === null || _a === void 0 ? void 0 : _a[1];
|
|
142
|
+
if (rawFragment == null) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const decodedFragment = (0, shared_1.decodeHref)(rawFragment);
|
|
146
|
+
// > 2. If fragment is the empty string, then return the special value top of the document.
|
|
147
|
+
// >
|
|
148
|
+
// > 9. If decodedFragment is an ASCII case-insensitive match for the string top, then return the top of the document.
|
|
149
|
+
if (decodedFragment === '' || /^top$/i.test(decodedFragment)) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (!idList.has(decodedFragment) &&
|
|
153
|
+
(el.rule.options.fragmentRefersNameAttr ? !nameList.has(decodedFragment) : true)) {
|
|
154
|
+
report({
|
|
155
|
+
scope: href,
|
|
156
|
+
line: (_b = href.valueNode) === null || _b === void 0 ? void 0 : _b.startLine,
|
|
157
|
+
col: (_c = href.valueNode) === null || _c === void 0 ? void 0 : _c.startCol,
|
|
158
|
+
raw: (_d = href.valueNode) === null || _d === void 0 ? void 0 : _d.raw,
|
|
159
|
+
message: t('Missing {0}', t('"{0*}" ID', decodedFragment)),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
});
|
|
103
163
|
},
|
|
104
164
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
type Options = {
|
|
2
|
+
ignore?: string | string[];
|
|
3
3
|
};
|
|
4
|
-
declare const _default: import(
|
|
4
|
+
declare const _default: Readonly<import('@markuplint/ml-core').RuleSeed<boolean, Options>>;
|
|
5
5
|
export default _default;
|
|
@@ -3,17 +3,17 @@ 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
|
-
|
|
6
|
+
defaultSeverity: 'warning',
|
|
7
7
|
defaultOptions: {},
|
|
8
8
|
async verify({ document, report, t }) {
|
|
9
9
|
await document.walkOn('Attr', attr => {
|
|
10
|
-
if (attr.ownerElement.
|
|
10
|
+
if (attr.ownerElement.elementType !== 'html') {
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
|
-
const ignoreList = Array.isArray(attr.rule.
|
|
14
|
-
? attr.rule.
|
|
15
|
-
: attr.rule.
|
|
16
|
-
? [attr.rule.
|
|
13
|
+
const ignoreList = Array.isArray(attr.rule.options.ignore)
|
|
14
|
+
? attr.rule.options.ignore
|
|
15
|
+
: attr.rule.options.ignore
|
|
16
|
+
? [attr.rule.options.ignore]
|
|
17
17
|
: [];
|
|
18
18
|
const name = attr.name;
|
|
19
19
|
for (const ignore of ignoreList) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChildNode, Options, Result, Specs } from './types';
|
|
2
|
+
import type { PermittedContentChoice } from '@markuplint/ml-spec';
|
|
3
|
+
import type { ReadonlyDeep } from 'type-fest';
|
|
4
|
+
export declare function choice(
|
|
5
|
+
pattern: ReadonlyDeep<PermittedContentChoice>,
|
|
6
|
+
elements: readonly ChildNode[],
|
|
7
|
+
specs: Specs,
|
|
8
|
+
options: Options,
|
|
9
|
+
depth: number,
|
|
10
|
+
): Result;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.choice = void 0;
|
|
4
|
+
const debug_1 = require("./debug");
|
|
5
|
+
const order_1 = require("./order");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
const indexes = new WeakMap();
|
|
8
|
+
function choice(pattern,
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
10
|
+
elements, specs, options, depth) {
|
|
11
|
+
const choiceLog = debug_1.cmLog.extend(`choice#${depth}`);
|
|
12
|
+
const collection = new utils_1.Collection(elements);
|
|
13
|
+
const unmatchedResults = [];
|
|
14
|
+
let i = 0;
|
|
15
|
+
for (const some of pattern.choice) {
|
|
16
|
+
choiceLog('Patterns[%s]: %s', i, (0, utils_1.modelLog)(some, ''));
|
|
17
|
+
const result = (0, order_1.order)(some, collection.unmatched, specs, options, depth + 1);
|
|
18
|
+
if (result.type === 'UNEXPECTED_EXTRA_NODE' || result.type === 'MATCHED' || result.type === 'MATCHED_ZERO') {
|
|
19
|
+
choiceLog('Results[%s]: %s', i, choiceLogString(pattern.choice, i));
|
|
20
|
+
collection.addMatched(result.matched);
|
|
21
|
+
return {
|
|
22
|
+
type: result.type,
|
|
23
|
+
matched: collection.matched,
|
|
24
|
+
unmatched: collection.unmatched,
|
|
25
|
+
zeroMatch: result.zeroMatch,
|
|
26
|
+
query: result.query,
|
|
27
|
+
hint: result.hint,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
unmatchedResults.push(result);
|
|
31
|
+
indexes.set(result, i);
|
|
32
|
+
i++;
|
|
33
|
+
}
|
|
34
|
+
const barelyMatchedResult = unmatchedResults.sort((a, b) => {
|
|
35
|
+
var _c, _d, _e, _f;
|
|
36
|
+
const computed1 = b.matched.length - a.matched.length;
|
|
37
|
+
if (computed1 !== 0) {
|
|
38
|
+
return computed1;
|
|
39
|
+
}
|
|
40
|
+
const _a = (_d = (_c = a.hint.missing) === null || _c === void 0 ? void 0 : _c.barelyMatchedElements) !== null && _d !== void 0 ? _d : 0;
|
|
41
|
+
const _b = (_f = (_e = b.hint.missing) === null || _e === void 0 ? void 0 : _e.barelyMatchedElements) !== null && _f !== void 0 ? _f : 0;
|
|
42
|
+
const computed2 = _b - _a;
|
|
43
|
+
return computed2;
|
|
44
|
+
})[0];
|
|
45
|
+
if (!barelyMatchedResult) {
|
|
46
|
+
throw new Error('Unreachable code');
|
|
47
|
+
}
|
|
48
|
+
const index = indexes.get(barelyMatchedResult);
|
|
49
|
+
if (index != null) {
|
|
50
|
+
choiceLog('Results[%s]: %s', index, choiceLogString(pattern.choice, index, true));
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
type: barelyMatchedResult.type,
|
|
54
|
+
matched: collection.matched,
|
|
55
|
+
unmatched: collection.unmatched,
|
|
56
|
+
zeroMatch: barelyMatchedResult.zeroMatch,
|
|
57
|
+
query: barelyMatchedResult.query,
|
|
58
|
+
hint: barelyMatchedResult.hint,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
exports.choice = choice;
|
|
62
|
+
function choiceLogString(choice, index, barely = false) {
|
|
63
|
+
const colorFn = barely ? debug_1.bgBlue : debug_1.bgGreen;
|
|
64
|
+
return choice
|
|
65
|
+
.map((pattern, i) => {
|
|
66
|
+
if (i === index) {
|
|
67
|
+
return colorFn((0, utils_1.modelLog)(pattern, ''));
|
|
68
|
+
}
|
|
69
|
+
return (0, utils_1.modelLog)(pattern, '');
|
|
70
|
+
})
|
|
71
|
+
.join(', ');
|
|
72
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ChildNode, Options, Result, Specs } from './types';
|
|
2
|
+
import type { PermittedContentPattern } from '@markuplint/ml-spec';
|
|
3
|
+
import type { ReadonlyDeep } from 'type-fest';
|
|
4
|
+
/**
|
|
5
|
+
* Check content condition
|
|
6
|
+
*
|
|
7
|
+
* @param pattern
|
|
8
|
+
* @param elements
|
|
9
|
+
* @param specs
|
|
10
|
+
* @param options
|
|
11
|
+
* @param depth
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
export declare function complexBranch(
|
|
15
|
+
pattern: ReadonlyDeep<PermittedContentPattern>,
|
|
16
|
+
elements: readonly ChildNode[],
|
|
17
|
+
specs: Specs,
|
|
18
|
+
options: Options,
|
|
19
|
+
depth: number,
|
|
20
|
+
): Result;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.complexBranch = void 0;
|
|
4
|
+
const choice_1 = require("./choice");
|
|
5
|
+
const count_pattern_1 = require("./count-pattern");
|
|
6
|
+
const transparent_1 = require("./transparent");
|
|
7
|
+
const utils_1 = require("./utils");
|
|
8
|
+
/**
|
|
9
|
+
* Check content condition
|
|
10
|
+
*
|
|
11
|
+
* @param pattern
|
|
12
|
+
* @param elements
|
|
13
|
+
* @param specs
|
|
14
|
+
* @param options
|
|
15
|
+
* @param depth
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
function complexBranch(pattern,
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
20
|
+
elements, specs, options, depth) {
|
|
21
|
+
if ((0, utils_1.isChoice)(pattern)) {
|
|
22
|
+
return (0, choice_1.choice)(pattern, elements, specs, options, depth);
|
|
23
|
+
}
|
|
24
|
+
if ((0, utils_1.isTransparent)(pattern)) {
|
|
25
|
+
return (0, transparent_1.transparent)(elements);
|
|
26
|
+
}
|
|
27
|
+
return (0, count_pattern_1.countPattern)(pattern, elements, specs, options, depth);
|
|
28
|
+
}
|
|
29
|
+
exports.complexBranch = complexBranch;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.contentModel = void 0;
|
|
4
|
+
const ml_spec_1 = require("@markuplint/ml-spec");
|
|
5
|
+
const start_1 = require("./start");
|
|
6
|
+
function contentModel(
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
8
|
+
el, rules, options) {
|
|
9
|
+
const model = createModel(el, rules);
|
|
10
|
+
if (model == null) {
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
type: 'MATCHED',
|
|
14
|
+
scope: el,
|
|
15
|
+
query: '*',
|
|
16
|
+
hint: {},
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
const result = (0, start_1.start)(model, el, el.ownerMLDocument.specs, options);
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
exports.contentModel = contentModel;
|
|
24
|
+
function createModel(
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
26
|
+
el, rules) {
|
|
27
|
+
const specs = cachedSpecs(el.ownerMLDocument.specs, rules);
|
|
28
|
+
const model = (0, ml_spec_1.getContentModel)(el, specs.specs);
|
|
29
|
+
return model;
|
|
30
|
+
}
|
|
31
|
+
const caches = new Map();
|
|
32
|
+
function cachedSpecs(specs, rules) {
|
|
33
|
+
if (rules.length === 0) {
|
|
34
|
+
return specs;
|
|
35
|
+
}
|
|
36
|
+
const key = JSON.stringify(rules);
|
|
37
|
+
const cached = caches.get(key);
|
|
38
|
+
if (cached) {
|
|
39
|
+
return cached;
|
|
40
|
+
}
|
|
41
|
+
const merged = {
|
|
42
|
+
...specs,
|
|
43
|
+
specs: [
|
|
44
|
+
...specs.specs,
|
|
45
|
+
...rules.map(tag => ({
|
|
46
|
+
name: tag.tag,
|
|
47
|
+
contentModel: tag,
|
|
48
|
+
})),
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
caches.set(key, merged);
|
|
52
|
+
return merged;
|
|
53
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ChildNode, Options, Result, Specs } from './types';
|
|
2
|
+
import type {
|
|
3
|
+
PermittedContentOneOrMore,
|
|
4
|
+
PermittedContentOptional,
|
|
5
|
+
PermittedContentRequire,
|
|
6
|
+
PermittedContentZeroOrMore,
|
|
7
|
+
} from '@markuplint/ml-spec';
|
|
8
|
+
import type { ReadonlyDeep } from 'type-fest';
|
|
9
|
+
/**
|
|
10
|
+
* Check count
|
|
11
|
+
*
|
|
12
|
+
* @param pattern
|
|
13
|
+
* @param elements
|
|
14
|
+
* @param specs
|
|
15
|
+
* @param options
|
|
16
|
+
* @param depth
|
|
17
|
+
* @returns
|
|
18
|
+
*/
|
|
19
|
+
export declare function countPattern(
|
|
20
|
+
pattern:
|
|
21
|
+
| ReadonlyDeep<PermittedContentOneOrMore>
|
|
22
|
+
| ReadonlyDeep<PermittedContentOptional>
|
|
23
|
+
| ReadonlyDeep<PermittedContentRequire>
|
|
24
|
+
| ReadonlyDeep<PermittedContentZeroOrMore>,
|
|
25
|
+
elements: readonly ChildNode[],
|
|
26
|
+
specs: Specs,
|
|
27
|
+
options: Options,
|
|
28
|
+
depth: number,
|
|
29
|
+
): Result;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.countPattern = void 0;
|
|
4
|
+
const debug_1 = require("./debug");
|
|
5
|
+
const recursive_branch_1 = require("./recursive-branch");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
/**
|
|
8
|
+
* Check count
|
|
9
|
+
*
|
|
10
|
+
* @param pattern
|
|
11
|
+
* @param elements
|
|
12
|
+
* @param specs
|
|
13
|
+
* @param options
|
|
14
|
+
* @param depth
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
17
|
+
function countPattern(pattern,
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
19
|
+
elements, specs, options, depth) {
|
|
20
|
+
const ptLog = debug_1.cmLog.extend(`countPattern#${depth}`);
|
|
21
|
+
const collection = new utils_1.Collection(elements);
|
|
22
|
+
const { model, min, max, repeat, missingType } = (0, utils_1.normalizeModel)(pattern);
|
|
23
|
+
ptLog('Model:\n RegEx: %s\n Schema: %o', (0, utils_1.modelLog)(model, repeat), pattern);
|
|
24
|
+
let prevResult = null;
|
|
25
|
+
let barelyResult = null;
|
|
26
|
+
let loopCount = 0;
|
|
27
|
+
// eslint-disable-next-line no-constant-condition
|
|
28
|
+
while (true) {
|
|
29
|
+
loopCount++;
|
|
30
|
+
ptLog('Check#%s: %s', loopCount, collection);
|
|
31
|
+
const result = (0, recursive_branch_1.recursiveBranch)(model, collection.unmatched, specs, options, depth);
|
|
32
|
+
const added = collection.addMatched(result.matched);
|
|
33
|
+
const { matchedCount } = collection;
|
|
34
|
+
if (result.type === 'UNMATCHED_SELECTOR_BUT_MAY_EMPTY') {
|
|
35
|
+
ptLog('MATCHED_ZERO:\n model: %s\n max: %s\n collection: %s\n matched element: %s', (0, utils_1.modelLog)(model, repeat), max, collection, matchedCount);
|
|
36
|
+
return compereResult({
|
|
37
|
+
type: 'MATCHED_ZERO',
|
|
38
|
+
matched: collection.matched,
|
|
39
|
+
unmatched: collection.unmatched,
|
|
40
|
+
zeroMatch: true,
|
|
41
|
+
query: result.query,
|
|
42
|
+
hint: result.hint,
|
|
43
|
+
}, barelyResult);
|
|
44
|
+
}
|
|
45
|
+
if (max < collection.matchedCount) {
|
|
46
|
+
collection.max(max);
|
|
47
|
+
ptLog('UNEXPECTED_EXTRA_NODE:\n model: %s\n max: %s\n collection: %s\n matched element: %s', (0, utils_1.modelLog)(model, repeat), max, collection, matchedCount);
|
|
48
|
+
return compereResult({
|
|
49
|
+
type: 'UNEXPECTED_EXTRA_NODE',
|
|
50
|
+
matched: collection.matched,
|
|
51
|
+
unmatched: collection.unmatched,
|
|
52
|
+
zeroMatch: result.zeroMatch,
|
|
53
|
+
query: result.query,
|
|
54
|
+
hint: (0, utils_1.mergeHints)(result.hint, { max }),
|
|
55
|
+
}, barelyResult);
|
|
56
|
+
}
|
|
57
|
+
if (prevResult) {
|
|
58
|
+
if (result.type === 'MISSING_NODE_ONE_OR_MORE' ||
|
|
59
|
+
result.type === 'MISSING_NODE_REQUIRED' ||
|
|
60
|
+
result.type === 'TRANSPARENT_MODEL_DISALLOWS') {
|
|
61
|
+
ptLog('%s(continued): %s; Needs', result.type, collection, result.query);
|
|
62
|
+
return compereResult({
|
|
63
|
+
type: result.type,
|
|
64
|
+
matched: collection.matched,
|
|
65
|
+
unmatched: collection.unmatched,
|
|
66
|
+
zeroMatch: result.zeroMatch,
|
|
67
|
+
query: result.query,
|
|
68
|
+
hint: result.hint,
|
|
69
|
+
}, barelyResult);
|
|
70
|
+
}
|
|
71
|
+
ptLog('%s(continued): %s', prevResult.type, collection);
|
|
72
|
+
return compereResult(prevResult, barelyResult);
|
|
73
|
+
}
|
|
74
|
+
if (added && collection.unmatched.length > 0) {
|
|
75
|
+
if (result.type !== 'MISSING_NODE' && result.type !== 'UNMATCHED_SELECTORS') {
|
|
76
|
+
barelyResult = {
|
|
77
|
+
type: result.type,
|
|
78
|
+
matched: collection.matched,
|
|
79
|
+
unmatched: collection.unmatched,
|
|
80
|
+
zeroMatch: result.zeroMatch,
|
|
81
|
+
query: result.query,
|
|
82
|
+
hint: result.hint,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
ptLog('continue⤴️');
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (collection.matchedCount + (result.zeroMatch ? 1 : 0) < min) {
|
|
89
|
+
const resultType = result.type === 'MISSING_NODE_REQUIRED' ||
|
|
90
|
+
result.type === 'MISSING_NODE_ONE_OR_MORE' ||
|
|
91
|
+
result.type === 'TRANSPARENT_MODEL_DISALLOWS'
|
|
92
|
+
? result.type
|
|
93
|
+
: missingType !== null && missingType !== void 0 ? missingType : 'MISSING_NODE_REQUIRED';
|
|
94
|
+
ptLog('%s(in %s); Needs %s', resultType, missingType, result.query);
|
|
95
|
+
return compereResult({
|
|
96
|
+
type: resultType,
|
|
97
|
+
matched: collection.matched,
|
|
98
|
+
unmatched: collection.unmatched,
|
|
99
|
+
zeroMatch: result.zeroMatch,
|
|
100
|
+
query: result.query,
|
|
101
|
+
hint: (0, utils_1.mergeHints)(result.hint, {
|
|
102
|
+
missing: {
|
|
103
|
+
barelyMatchedElements: collection.matched.length,
|
|
104
|
+
need: result.query,
|
|
105
|
+
},
|
|
106
|
+
}),
|
|
107
|
+
}, barelyResult);
|
|
108
|
+
}
|
|
109
|
+
const resultType = collection.matched.length === 0 ? 'MATCHED_ZERO' : 'MATCHED';
|
|
110
|
+
const zeroMatch = result.zeroMatch || min === 0 || resultType === 'MATCHED_ZERO';
|
|
111
|
+
const matchedResult = {
|
|
112
|
+
type: resultType,
|
|
113
|
+
matched: collection.matched,
|
|
114
|
+
unmatched: collection.unmatched,
|
|
115
|
+
zeroMatch,
|
|
116
|
+
query: result.query,
|
|
117
|
+
hint: (0, utils_1.mergeHints)(result.hint, {
|
|
118
|
+
missing: {
|
|
119
|
+
barelyMatchedElements: collection.matched.length,
|
|
120
|
+
need: result.query,
|
|
121
|
+
},
|
|
122
|
+
}),
|
|
123
|
+
};
|
|
124
|
+
if (collection.unmatched.length > 0) {
|
|
125
|
+
prevResult = matchedResult;
|
|
126
|
+
ptLog('continue⤴️ (add prev)');
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
ptLog('%s:\n model: %s\n max: %s\n collection: %s\n matched element: %s', resultType, (0, utils_1.modelLog)(model, repeat), max, collection, matchedCount);
|
|
130
|
+
if (result.type === 'MISSING_NODE_REQUIRED' ||
|
|
131
|
+
result.type === 'MISSING_NODE_ONE_OR_MORE' ||
|
|
132
|
+
result.type === 'TRANSPARENT_MODEL_DISALLOWS') {
|
|
133
|
+
return compereResult({
|
|
134
|
+
type: result.type,
|
|
135
|
+
matched: collection.matched,
|
|
136
|
+
unmatched: collection.unmatched,
|
|
137
|
+
zeroMatch: result.zeroMatch,
|
|
138
|
+
query: result.query,
|
|
139
|
+
hint: result.hint,
|
|
140
|
+
}, barelyResult);
|
|
141
|
+
}
|
|
142
|
+
return compereResult(matchedResult, barelyResult);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
exports.countPattern = countPattern;
|
|
146
|
+
const cLog = debug_1.cmLog.extend('countCompereResult');
|
|
147
|
+
function compereResult(
|
|
148
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
149
|
+
a,
|
|
150
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
151
|
+
b) {
|
|
152
|
+
var _a;
|
|
153
|
+
cLog('current: %s %O\nbarely: %s %O', a.type, a.hint, b === null || b === void 0 ? void 0 : b.type, b === null || b === void 0 ? void 0 : b.hint);
|
|
154
|
+
if (b == null) {
|
|
155
|
+
return a;
|
|
156
|
+
}
|
|
157
|
+
if (a.type === 'MATCHED' || a.type === 'MATCHED_ZERO' || a.type === 'UNEXPECTED_EXTRA_NODE') {
|
|
158
|
+
return a;
|
|
159
|
+
}
|
|
160
|
+
const result = (_a = [a, b].sort((a, b) => { var _a, _b, _c, _d; return ((_b = (_a = b.hint.missing) === null || _a === void 0 ? void 0 : _a.barelyMatchedElements) !== null && _b !== void 0 ? _b : 0) - ((_d = (_c = a.hint.missing) === null || _c === void 0 ? void 0 : _c.barelyMatchedElements) !== null && _d !== void 0 ? _d : 0); })[0]) !== null && _a !== void 0 ? _a : a;
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
@@ -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;
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
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; } });
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
declare
|
|
3
|
-
tag: string;
|
|
4
|
-
};
|
|
5
|
-
declare type Options = {
|
|
6
|
-
ignoreHasMutableChildren: boolean;
|
|
7
|
-
};
|
|
8
|
-
declare const _default: import("@markuplint/ml-core").RuleSeed<TagRule[], Options>;
|
|
1
|
+
import type { Options, TagRule } from './types';
|
|
2
|
+
declare const _default: Readonly<import('@markuplint/ml-core').RuleSeed<TagRule[], Options>>;
|
|
9
3
|
export default _default;
|