@markuplint/rules 3.0.0 → 3.0.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/lib/debug.js +1 -1
- package/lib/permitted-contents/choice.js +34 -1
- package/lib/permitted-contents/count-pattern.js +62 -62
- package/lib/permitted-contents/matches-selector.js +4 -4
- package/lib/permitted-contents/order.js +20 -12
- package/lib/permitted-contents/types.d.ts +10 -4
- package/lib/permitted-contents/utils.d.ts +19 -1
- package/lib/permitted-contents/utils.js +105 -1
- package/package.json +5 -5
package/lib/debug.js
CHANGED
|
@@ -3,4 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.log = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const debug_1 = tslib_1.__importDefault(require("debug"));
|
|
6
|
-
exports.log = (0, debug_1.default)('
|
|
6
|
+
exports.log = (0, debug_1.default)('ml-rules');
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.choice = void 0;
|
|
4
|
+
const debug_1 = require("./debug");
|
|
4
5
|
const order_1 = require("./order");
|
|
5
6
|
const utils_1 = require("./utils");
|
|
7
|
+
const indexes = new WeakMap();
|
|
6
8
|
function choice(pattern, elements, specs, options, depth) {
|
|
9
|
+
const choiceLog = debug_1.cmLog.extend(`choice#${depth}`);
|
|
7
10
|
const collection = new utils_1.Collection(elements);
|
|
8
11
|
const unmatchedResults = [];
|
|
12
|
+
let i = 0;
|
|
9
13
|
for (const some of pattern.choice) {
|
|
14
|
+
choiceLog('Patterns[%s]: %s', i, (0, utils_1.modelLog)(some, ''));
|
|
10
15
|
const result = (0, order_1.order)(some, collection.unmatched, specs, options, depth + 1);
|
|
11
16
|
if (result.type === 'UNEXPECTED_EXTRA_NODE' || result.type === 'MATCHED' || result.type === 'MATCHED_ZERO') {
|
|
17
|
+
choiceLog('Results[%s]: %s', i, choiceLogString(pattern.choice, i));
|
|
12
18
|
collection.addMatched(result.matched);
|
|
13
19
|
return {
|
|
14
20
|
type: result.type,
|
|
@@ -20,11 +26,27 @@ function choice(pattern, elements, specs, options, depth) {
|
|
|
20
26
|
};
|
|
21
27
|
}
|
|
22
28
|
unmatchedResults.push(result);
|
|
29
|
+
indexes.set(result, i);
|
|
30
|
+
i++;
|
|
23
31
|
}
|
|
24
|
-
const barelyMatchedResult = unmatchedResults.sort((a, b) =>
|
|
32
|
+
const barelyMatchedResult = unmatchedResults.sort((a, b) => {
|
|
33
|
+
var _c, _d, _e, _f;
|
|
34
|
+
const computed1 = b.matched.length - a.matched.length;
|
|
35
|
+
if (computed1 !== 0) {
|
|
36
|
+
return computed1;
|
|
37
|
+
}
|
|
38
|
+
const _a = (_d = (_c = a.hint.missing) === null || _c === void 0 ? void 0 : _c.barelyMatchedElements) !== null && _d !== void 0 ? _d : 0;
|
|
39
|
+
const _b = (_f = (_e = b.hint.missing) === null || _e === void 0 ? void 0 : _e.barelyMatchedElements) !== null && _f !== void 0 ? _f : 0;
|
|
40
|
+
const computed2 = _b - _a;
|
|
41
|
+
return computed2;
|
|
42
|
+
})[0];
|
|
25
43
|
if (!barelyMatchedResult) {
|
|
26
44
|
throw new Error('Unreachable code');
|
|
27
45
|
}
|
|
46
|
+
const index = indexes.get(barelyMatchedResult);
|
|
47
|
+
if (index != null) {
|
|
48
|
+
choiceLog('Results[%s]: %s', index, choiceLogString(pattern.choice, index, true));
|
|
49
|
+
}
|
|
28
50
|
return {
|
|
29
51
|
type: barelyMatchedResult.type,
|
|
30
52
|
matched: collection.matched,
|
|
@@ -35,3 +57,14 @@ function choice(pattern, elements, specs, options, depth) {
|
|
|
35
57
|
};
|
|
36
58
|
}
|
|
37
59
|
exports.choice = choice;
|
|
60
|
+
function choiceLogString(choice, index, barely = false) {
|
|
61
|
+
const colorFn = barely ? debug_1.bgBlue : debug_1.bgGreen;
|
|
62
|
+
return choice
|
|
63
|
+
.map((pattern, i) => {
|
|
64
|
+
if (i === index) {
|
|
65
|
+
return colorFn((0, utils_1.modelLog)(pattern, ''));
|
|
66
|
+
}
|
|
67
|
+
return (0, utils_1.modelLog)(pattern, '');
|
|
68
|
+
})
|
|
69
|
+
.join(', ');
|
|
70
|
+
}
|
|
@@ -15,94 +15,72 @@ const utils_1 = require("./utils");
|
|
|
15
15
|
* @returns
|
|
16
16
|
*/
|
|
17
17
|
function countPattern(pattern, elements, specs, options, depth) {
|
|
18
|
-
var _a, _b, _c, _d, _e;
|
|
19
18
|
const ptLog = debug_1.cmLog.extend(`countPattern#${depth}`);
|
|
20
19
|
const collection = new utils_1.Collection(elements);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
let model;
|
|
24
|
-
let type;
|
|
25
|
-
let _type;
|
|
26
|
-
if ((0, utils_1.isRequire)(pattern)) {
|
|
27
|
-
min = (_a = pattern.min) !== null && _a !== void 0 ? _a : 1;
|
|
28
|
-
max = Math.max((_b = pattern.max) !== null && _b !== void 0 ? _b : 1, min);
|
|
29
|
-
model = pattern.require;
|
|
30
|
-
type = 'MISSING_NODE_REQUIRED';
|
|
31
|
-
_type = 'require';
|
|
32
|
-
}
|
|
33
|
-
else if ((0, utils_1.isOptional)(pattern)) {
|
|
34
|
-
min = 0;
|
|
35
|
-
max = Math.max((_c = pattern.max) !== null && _c !== void 0 ? _c : 1, 1);
|
|
36
|
-
model = pattern.optional;
|
|
37
|
-
_type = 'optional';
|
|
38
|
-
}
|
|
39
|
-
else if ((0, utils_1.isOneOrMore)(pattern)) {
|
|
40
|
-
min = 1;
|
|
41
|
-
max = Math.max((_d = pattern.max) !== null && _d !== void 0 ? _d : Infinity, 1);
|
|
42
|
-
model = pattern.oneOrMore;
|
|
43
|
-
type = 'MISSING_NODE_ONE_OR_MORE';
|
|
44
|
-
_type = 'one or more';
|
|
45
|
-
}
|
|
46
|
-
else if ((0, utils_1.isZeroOrMore)(pattern)) {
|
|
47
|
-
min = 0;
|
|
48
|
-
max = Math.max((_e = pattern.max) !== null && _e !== void 0 ? _e : Infinity, 1);
|
|
49
|
-
model = pattern.zeroOrMore;
|
|
50
|
-
_type = 'zero or more';
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
throw new Error('Unreachable code');
|
|
54
|
-
}
|
|
55
|
-
ptLog('%s: %o', _type, model);
|
|
20
|
+
const { model, min, max, repeat, missingType } = (0, utils_1.normalizeModel)(pattern);
|
|
21
|
+
ptLog('Model:\n RegEx: %s\n Schema: %o', (0, utils_1.modelLog)(model, repeat), pattern);
|
|
56
22
|
let prevResult = null;
|
|
23
|
+
let barelyResult = null;
|
|
24
|
+
let loopCount = 0;
|
|
57
25
|
// eslint-disable-next-line no-constant-condition
|
|
58
26
|
while (true) {
|
|
59
|
-
|
|
27
|
+
loopCount++;
|
|
28
|
+
ptLog('Check#%s: %s', loopCount, collection);
|
|
60
29
|
const result = (0, recursive_branch_1.recursiveBranch)(model, collection.unmatched, specs, options, depth);
|
|
61
30
|
const added = collection.addMatched(result.matched);
|
|
31
|
+
const { matchedCount } = collection;
|
|
62
32
|
if (result.type === 'UNMATCHED_SELECTOR_BUT_MAY_EMPTY') {
|
|
63
|
-
ptLog('MATCHED_ZERO: %s',
|
|
64
|
-
return {
|
|
33
|
+
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);
|
|
34
|
+
return compereResult({
|
|
65
35
|
type: 'MATCHED_ZERO',
|
|
66
36
|
matched: collection.matched,
|
|
67
37
|
unmatched: collection.unmatched,
|
|
68
38
|
zeroMatch: true,
|
|
69
39
|
query: result.query,
|
|
70
40
|
hint: result.hint,
|
|
71
|
-
};
|
|
41
|
+
}, barelyResult);
|
|
72
42
|
}
|
|
73
43
|
if (max < collection.matchedCount) {
|
|
74
44
|
collection.max(max);
|
|
75
|
-
ptLog('UNEXPECTED_EXTRA_NODE
|
|
76
|
-
return {
|
|
45
|
+
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);
|
|
46
|
+
return compereResult({
|
|
77
47
|
type: 'UNEXPECTED_EXTRA_NODE',
|
|
78
48
|
matched: collection.matched,
|
|
79
49
|
unmatched: collection.unmatched,
|
|
80
50
|
zeroMatch: result.zeroMatch,
|
|
81
51
|
query: result.query,
|
|
82
|
-
hint: {
|
|
83
|
-
|
|
84
|
-
max,
|
|
85
|
-
},
|
|
86
|
-
};
|
|
52
|
+
hint: (0, utils_1.mergeHints)(result.hint, { max }),
|
|
53
|
+
}, barelyResult);
|
|
87
54
|
}
|
|
88
55
|
if (prevResult) {
|
|
89
56
|
if (result.type === 'MISSING_NODE_ONE_OR_MORE' ||
|
|
90
57
|
result.type === 'MISSING_NODE_REQUIRED' ||
|
|
91
58
|
result.type === 'TRANSPARENT_MODEL_DISALLOWS') {
|
|
92
|
-
ptLog('%s(continued): %s', result.type, collection);
|
|
93
|
-
return {
|
|
59
|
+
ptLog('%s(continued): %s; Needs', result.type, collection, result.query);
|
|
60
|
+
return compereResult({
|
|
94
61
|
type: result.type,
|
|
95
62
|
matched: collection.matched,
|
|
96
63
|
unmatched: collection.unmatched,
|
|
97
64
|
zeroMatch: result.zeroMatch,
|
|
98
65
|
query: result.query,
|
|
99
66
|
hint: result.hint,
|
|
100
|
-
};
|
|
67
|
+
}, barelyResult);
|
|
101
68
|
}
|
|
102
69
|
ptLog('%s(continued): %s', prevResult.type, collection);
|
|
103
|
-
return prevResult;
|
|
70
|
+
return compereResult(prevResult, barelyResult);
|
|
104
71
|
}
|
|
105
72
|
if (added && collection.unmatched.length > 0) {
|
|
73
|
+
if (result.type !== 'MISSING_NODE' && result.type !== 'UNMATCHED_SELECTORS') {
|
|
74
|
+
barelyResult = {
|
|
75
|
+
type: result.type,
|
|
76
|
+
matched: collection.matched,
|
|
77
|
+
unmatched: collection.unmatched,
|
|
78
|
+
zeroMatch: result.zeroMatch,
|
|
79
|
+
query: result.query,
|
|
80
|
+
hint: result.hint,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
ptLog('continue⤴️');
|
|
106
84
|
continue;
|
|
107
85
|
}
|
|
108
86
|
if (collection.matchedCount + (result.zeroMatch ? 1 : 0) < min) {
|
|
@@ -110,16 +88,21 @@ function countPattern(pattern, elements, specs, options, depth) {
|
|
|
110
88
|
result.type === 'MISSING_NODE_ONE_OR_MORE' ||
|
|
111
89
|
result.type === 'TRANSPARENT_MODEL_DISALLOWS'
|
|
112
90
|
? result.type
|
|
113
|
-
:
|
|
114
|
-
ptLog('%s(in %s)
|
|
115
|
-
return {
|
|
91
|
+
: missingType !== null && missingType !== void 0 ? missingType : 'MISSING_NODE_REQUIRED';
|
|
92
|
+
ptLog('%s(in %s); Needs %s', resultType, missingType, result.query);
|
|
93
|
+
return compereResult({
|
|
116
94
|
type: resultType,
|
|
117
95
|
matched: collection.matched,
|
|
118
96
|
unmatched: collection.unmatched,
|
|
119
97
|
zeroMatch: result.zeroMatch,
|
|
120
98
|
query: result.query,
|
|
121
|
-
hint: result.hint,
|
|
122
|
-
|
|
99
|
+
hint: (0, utils_1.mergeHints)(result.hint, {
|
|
100
|
+
missing: {
|
|
101
|
+
barelyMatchedElements: collection.matched.length,
|
|
102
|
+
need: result.query,
|
|
103
|
+
},
|
|
104
|
+
}),
|
|
105
|
+
}, barelyResult);
|
|
123
106
|
}
|
|
124
107
|
const resultType = collection.matched.length === 0 ? 'MATCHED_ZERO' : 'MATCHED';
|
|
125
108
|
const zeroMatch = result.zeroMatch || min === 0 || resultType === 'MATCHED_ZERO';
|
|
@@ -129,27 +112,44 @@ function countPattern(pattern, elements, specs, options, depth) {
|
|
|
129
112
|
unmatched: collection.unmatched,
|
|
130
113
|
zeroMatch,
|
|
131
114
|
query: result.query,
|
|
132
|
-
hint: result.hint,
|
|
115
|
+
hint: (0, utils_1.mergeHints)(result.hint, {
|
|
116
|
+
missing: {
|
|
117
|
+
barelyMatchedElements: collection.matched.length,
|
|
118
|
+
need: result.query,
|
|
119
|
+
},
|
|
120
|
+
}),
|
|
133
121
|
};
|
|
134
122
|
if (!prevResult && collection.unmatched.length) {
|
|
135
|
-
ptLog('continue checking');
|
|
136
123
|
prevResult = matchedResult;
|
|
124
|
+
ptLog('continue⤴️ (add prev)');
|
|
137
125
|
continue;
|
|
138
126
|
}
|
|
139
|
-
ptLog('%s: %s', resultType, collection);
|
|
127
|
+
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);
|
|
140
128
|
if (result.type === 'MISSING_NODE_REQUIRED' ||
|
|
141
129
|
result.type === 'MISSING_NODE_ONE_OR_MORE' ||
|
|
142
130
|
result.type === 'TRANSPARENT_MODEL_DISALLOWS') {
|
|
143
|
-
return {
|
|
131
|
+
return compereResult({
|
|
144
132
|
type: result.type,
|
|
145
133
|
matched: collection.matched,
|
|
146
134
|
unmatched: collection.unmatched,
|
|
147
135
|
zeroMatch: result.zeroMatch,
|
|
148
136
|
query: result.query,
|
|
149
137
|
hint: result.hint,
|
|
150
|
-
};
|
|
138
|
+
}, barelyResult);
|
|
151
139
|
}
|
|
152
|
-
return matchedResult;
|
|
140
|
+
return compereResult(matchedResult, barelyResult);
|
|
153
141
|
}
|
|
154
142
|
}
|
|
155
143
|
exports.countPattern = countPattern;
|
|
144
|
+
const cLog = debug_1.cmLog.extend('countCompereResult');
|
|
145
|
+
function compereResult(a, b) {
|
|
146
|
+
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);
|
|
147
|
+
if (b == null) {
|
|
148
|
+
return a;
|
|
149
|
+
}
|
|
150
|
+
if (a.type === 'MATCHED' || a.type === 'MATCHED_ZERO' || a.type === 'UNEXPECTED_EXTRA_NODE') {
|
|
151
|
+
return a;
|
|
152
|
+
}
|
|
153
|
+
const result = [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];
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
@@ -103,9 +103,9 @@ function matchesSelector(query, node, specs, options, depth) {
|
|
|
103
103
|
unmatched: [node],
|
|
104
104
|
zeroMatch: true,
|
|
105
105
|
query,
|
|
106
|
-
hint: {
|
|
106
|
+
hint: (0, utils_1.cleanObject)({
|
|
107
107
|
not: result.not,
|
|
108
|
-
},
|
|
108
|
+
}),
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
return {
|
|
@@ -114,9 +114,9 @@ function matchesSelector(query, node, specs, options, depth) {
|
|
|
114
114
|
unmatched: [node],
|
|
115
115
|
zeroMatch: false,
|
|
116
116
|
query,
|
|
117
|
-
hint: {
|
|
117
|
+
hint: (0, utils_1.cleanObject)({
|
|
118
118
|
not: result.not,
|
|
119
|
-
},
|
|
119
|
+
}),
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
122
|
return {
|
|
@@ -16,11 +16,12 @@ const utils_1 = require("./utils");
|
|
|
16
16
|
* @returns
|
|
17
17
|
*/
|
|
18
18
|
function order(contents, nodes, specs, options, depth) {
|
|
19
|
-
var _a, _b, _c, _d;
|
|
19
|
+
var _a, _b, _c, _d, _e;
|
|
20
20
|
const orderLog = debug_1.cmLog.extend(`order#${depth}`);
|
|
21
21
|
const btLog = debug_1.cmLog.extend(`backtrack#${depth}`);
|
|
22
22
|
const patterns = (0, helpers_1.deepCopy)(contents);
|
|
23
23
|
const collection = new utils_1.Collection(nodes);
|
|
24
|
+
orderLog('Model:\n RegEx: %s\n Schema: %o', (0, utils_1.modelLog)(patterns, ''), patterns);
|
|
24
25
|
orderLog('Starts: %s', collection);
|
|
25
26
|
let result = undefined;
|
|
26
27
|
let backtrackMode = false;
|
|
@@ -29,28 +30,34 @@ function order(contents, nodes, specs, options, depth) {
|
|
|
29
30
|
while (patterns.length) {
|
|
30
31
|
result = (0, complex_branch_1.complexBranch)(patterns[0], collection.unmatched, specs, options, depth);
|
|
31
32
|
collection.addMatched(result.matched);
|
|
32
|
-
orderLog('stack: %s', collection);
|
|
33
33
|
if (result.type !== 'UNEXPECTED_EXTRA_NODE' && result.type !== 'MATCHED' && result.type !== 'MATCHED_ZERO') {
|
|
34
34
|
unmatchedResults.push(result);
|
|
35
35
|
if (backtrackMode) {
|
|
36
36
|
collection.back();
|
|
37
|
-
btLog('
|
|
37
|
+
btLog('🔙◀BACK');
|
|
38
38
|
backtrackMode = false;
|
|
39
39
|
afterBacktrack = true;
|
|
40
40
|
continue;
|
|
41
41
|
}
|
|
42
|
-
orderLog('conformed (%s): %s', result.type, collection.toString(true));
|
|
43
42
|
const barelyMatchedResult = unmatchedResults.sort((a, b) => b.matched.length - a.matched.length)[0];
|
|
44
43
|
if (!barelyMatchedResult) {
|
|
45
44
|
throw new Error('Unreachable code');
|
|
46
45
|
}
|
|
46
|
+
orderLog('Result (%s): %s%s', result.type, collection.toString(true), ((_a = barelyMatchedResult.hint.missing) === null || _a === void 0 ? void 0 : _a.barelyMatchedElements)
|
|
47
|
+
? `; But ${barelyMatchedResult.hint.missing.barelyMatchedElements} elements hit out of pattern`
|
|
48
|
+
: '');
|
|
47
49
|
return {
|
|
48
50
|
type: barelyMatchedResult.type,
|
|
49
51
|
matched: collection.matched,
|
|
50
52
|
unmatched: collection.unmatched,
|
|
51
53
|
zeroMatch: barelyMatchedResult.zeroMatch,
|
|
52
54
|
query: barelyMatchedResult.query,
|
|
53
|
-
hint: barelyMatchedResult.hint,
|
|
55
|
+
hint: (0, utils_1.mergeHints)(barelyMatchedResult.hint, {
|
|
56
|
+
missing: {
|
|
57
|
+
barelyMatchedElements: collection.matched.length,
|
|
58
|
+
need: barelyMatchedResult.query,
|
|
59
|
+
},
|
|
60
|
+
}),
|
|
54
61
|
};
|
|
55
62
|
}
|
|
56
63
|
if (afterBacktrack) {
|
|
@@ -66,24 +73,25 @@ function order(contents, nodes, specs, options, depth) {
|
|
|
66
73
|
patterns.shift();
|
|
67
74
|
}
|
|
68
75
|
if (collection.unmatched.length) {
|
|
69
|
-
orderLog('
|
|
76
|
+
orderLog('Result (UNEXPECTED_EXTRA_NODE): %s', collection.toString(true));
|
|
70
77
|
return {
|
|
71
78
|
type: 'UNEXPECTED_EXTRA_NODE',
|
|
72
79
|
matched: collection.matched,
|
|
73
80
|
unmatched: collection.unmatched,
|
|
74
81
|
zeroMatch: false,
|
|
75
|
-
query: (
|
|
76
|
-
hint: (
|
|
82
|
+
query: (_b = result === null || result === void 0 ? void 0 : result.query) !== null && _b !== void 0 ? _b : 'N/A',
|
|
83
|
+
hint: (_c = result === null || result === void 0 ? void 0 : result.hint) !== null && _c !== void 0 ? _c : {},
|
|
77
84
|
};
|
|
78
85
|
}
|
|
79
|
-
|
|
86
|
+
const resultType = collection.matched.length ? 'MATCHED' : 'MATCHED_ZERO';
|
|
87
|
+
orderLog('Result (%s): %s', resultType, collection.toString(true));
|
|
80
88
|
return {
|
|
81
|
-
type:
|
|
89
|
+
type: resultType,
|
|
82
90
|
matched: collection.matched,
|
|
83
91
|
unmatched: collection.unmatched,
|
|
84
92
|
zeroMatch: false,
|
|
85
|
-
query: (
|
|
86
|
-
hint: (
|
|
93
|
+
query: (_d = result === null || result === void 0 ? void 0 : result.query) !== null && _d !== void 0 ? _d : 'N/A',
|
|
94
|
+
hint: (_e = result === null || result === void 0 ? void 0 : result.hint) !== null && _e !== void 0 ? _e : {},
|
|
87
95
|
};
|
|
88
96
|
}
|
|
89
97
|
exports.order = order;
|
|
@@ -24,15 +24,21 @@ export type Result<T extends string = MatchedReason> = {
|
|
|
24
24
|
unmatched: ChildNode[];
|
|
25
25
|
zeroMatch: boolean;
|
|
26
26
|
query: string;
|
|
27
|
-
hint:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
hint: Hints;
|
|
28
|
+
};
|
|
29
|
+
export type Hints = {
|
|
30
|
+
max?: number;
|
|
31
|
+
not?: ChildNode;
|
|
32
|
+
transparent?: Element;
|
|
33
|
+
missing?: {
|
|
34
|
+
barelyMatchedElements?: number;
|
|
35
|
+
need?: string;
|
|
31
36
|
};
|
|
32
37
|
};
|
|
33
38
|
export type MatchedReason = 'MATCHED' | 'MATCHED_ZERO';
|
|
34
39
|
export type UnmatchedReason = 'NOTHING' | 'UNEXPECTED_EXTRA_NODE' | 'TRANSPARENT_MODEL_DISALLOWS' | MissingNodeReason;
|
|
35
40
|
export type MissingNodeReason = 'MISSING_NODE_REQUIRED' | 'MISSING_NODE_ONE_OR_MORE';
|
|
41
|
+
export type RepeatSign = '' | '?' | '+' | '*' | `{${number},${number}}`;
|
|
36
42
|
export type TransparentModel = {
|
|
37
43
|
el: Element;
|
|
38
44
|
additionalCondition: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChildNode, Element, Specs } from './types';
|
|
1
|
+
import type { ChildNode, Element, Hints, MissingNodeReason, RepeatSign, Specs } from './types';
|
|
2
2
|
import type { PermittedContentPattern, PermittedContentChoice, PermittedContentOneOrMore, PermittedContentOptional, PermittedContentRequire, PermittedContentTransparent, PermittedContentZeroOrMore, Model } from '@markuplint/ml-spec';
|
|
3
3
|
export declare function getChildNodesWithoutWhitespaces(el: Element): ChildNode[];
|
|
4
4
|
export declare function isModel(model: Model | PermittedContentPattern[]): model is Model;
|
|
@@ -15,6 +15,23 @@ export declare function isOneOrMore(content: PermittedContentPattern): content i
|
|
|
15
15
|
export declare function isZeroOrMore(content: PermittedContentPattern): content is PermittedContentZeroOrMore;
|
|
16
16
|
export declare function isChoice(content: PermittedContentPattern): content is PermittedContentChoice;
|
|
17
17
|
export declare function isTransparent(content: PermittedContentPattern): content is PermittedContentTransparent;
|
|
18
|
+
export declare function normalizeModel(pattern: PermittedContentRequire | PermittedContentOptional | PermittedContentOneOrMore | PermittedContentZeroOrMore): {
|
|
19
|
+
model: PermittedContentPattern[] | Model;
|
|
20
|
+
min: number;
|
|
21
|
+
max: number;
|
|
22
|
+
repeat: RepeatSign;
|
|
23
|
+
missingType: MissingNodeReason | undefined;
|
|
24
|
+
};
|
|
25
|
+
export declare function mergeHints(a: Hints, b: Hints): Partial<{
|
|
26
|
+
missing: Partial<{
|
|
27
|
+
barelyMatchedElements?: number | undefined;
|
|
28
|
+
need?: string | undefined;
|
|
29
|
+
}> | undefined;
|
|
30
|
+
max?: number | undefined;
|
|
31
|
+
not?: import("packages/@markuplint/ml-core/lib").DocumentType<import("./types").TagRule[], import("./types").Options> | import("packages/@markuplint/ml-core/lib/ml-dom/node/character-data").MLCharacterData<import("./types").TagRule[], import("./types").Options, import("packages/@markuplint/ml-ast/lib").MLASTAbstractNode> | import("packages/@markuplint/ml-core/lib").Element<import("./types").TagRule[], import("./types").Options> | import("packages/@markuplint/ml-core/lib").Block<import("./types").TagRule[], import("./types").Options> | undefined;
|
|
32
|
+
transparent?: Element | undefined;
|
|
33
|
+
}>;
|
|
34
|
+
export declare function cleanObject<T extends Object>(object: T): Partial<T>;
|
|
18
35
|
export declare class Collection {
|
|
19
36
|
#private;
|
|
20
37
|
constructor(origin: readonly ChildNode[]);
|
|
@@ -30,3 +47,4 @@ export declare class Collection {
|
|
|
30
47
|
}
|
|
31
48
|
export declare class UnsupportedError extends Error {
|
|
32
49
|
}
|
|
50
|
+
export declare function modelLog(model: Model | PermittedContentPattern[], repeat: RepeatSign): string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var _Collection_locked, _Collection_matched, _Collection_nodes, _Collection_origin;
|
|
3
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;
|
|
4
|
+
exports.modelLog = exports.UnsupportedError = exports.Collection = exports.cleanObject = exports.mergeHints = exports.normalizeModel = 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
7
|
const debug_1 = require("./debug");
|
|
@@ -95,6 +95,81 @@ function isTransparent(content) {
|
|
|
95
95
|
return 'transparent' in content;
|
|
96
96
|
}
|
|
97
97
|
exports.isTransparent = isTransparent;
|
|
98
|
+
function normalizeModel(pattern) {
|
|
99
|
+
var _a, _b, _c, _d, _e;
|
|
100
|
+
let model;
|
|
101
|
+
let min;
|
|
102
|
+
let max;
|
|
103
|
+
let repeat;
|
|
104
|
+
let missingType;
|
|
105
|
+
if (isRequire(pattern)) {
|
|
106
|
+
model = pattern.require;
|
|
107
|
+
min = (_a = pattern.min) !== null && _a !== void 0 ? _a : 1;
|
|
108
|
+
max = Math.max((_b = pattern.max) !== null && _b !== void 0 ? _b : 1, min);
|
|
109
|
+
missingType = 'MISSING_NODE_REQUIRED';
|
|
110
|
+
}
|
|
111
|
+
else if (isOptional(pattern)) {
|
|
112
|
+
model = pattern.optional;
|
|
113
|
+
min = 0;
|
|
114
|
+
max = Math.max((_c = pattern.max) !== null && _c !== void 0 ? _c : 1, 1);
|
|
115
|
+
}
|
|
116
|
+
else if (isOneOrMore(pattern)) {
|
|
117
|
+
model = pattern.oneOrMore;
|
|
118
|
+
min = 1;
|
|
119
|
+
max = Math.max((_d = pattern.max) !== null && _d !== void 0 ? _d : Infinity, 1);
|
|
120
|
+
missingType = 'MISSING_NODE_ONE_OR_MORE';
|
|
121
|
+
}
|
|
122
|
+
else if (isZeroOrMore(pattern)) {
|
|
123
|
+
model = pattern.zeroOrMore;
|
|
124
|
+
min = 0;
|
|
125
|
+
max = Math.max((_e = pattern.max) !== null && _e !== void 0 ? _e : Infinity, 1);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
throw new Error('Unreachable code');
|
|
129
|
+
}
|
|
130
|
+
if (min === 0 && max === 1) {
|
|
131
|
+
repeat = '?';
|
|
132
|
+
}
|
|
133
|
+
else if (min === 0 && !Number.isFinite(max)) {
|
|
134
|
+
repeat = '*';
|
|
135
|
+
}
|
|
136
|
+
else if (min === 1 && max === 1) {
|
|
137
|
+
repeat = '';
|
|
138
|
+
}
|
|
139
|
+
else if (min === 1 && !Number.isFinite(max)) {
|
|
140
|
+
repeat = '+';
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
repeat = `{${min},${max}}`;
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
model,
|
|
147
|
+
min,
|
|
148
|
+
max,
|
|
149
|
+
repeat,
|
|
150
|
+
missingType,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
exports.normalizeModel = normalizeModel;
|
|
154
|
+
function mergeHints(a, b) {
|
|
155
|
+
const missing = [a.missing, b.missing].sort((a, b) => { var _a, _b; return ((_a = b === null || b === void 0 ? void 0 : b.barelyMatchedElements) !== null && _a !== void 0 ? _a : 0) - ((_b = a === null || a === void 0 ? void 0 : a.barelyMatchedElements) !== null && _b !== void 0 ? _b : 0); })[0];
|
|
156
|
+
return cleanObject({
|
|
157
|
+
...a,
|
|
158
|
+
...b,
|
|
159
|
+
missing: missing && cleanObject(missing),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
exports.mergeHints = mergeHints;
|
|
163
|
+
function cleanObject(object) {
|
|
164
|
+
const newObject = {};
|
|
165
|
+
Object.entries(object).forEach(([key, value]) => {
|
|
166
|
+
if (value !== undefined) {
|
|
167
|
+
newObject[key] = value;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
return newObject;
|
|
171
|
+
}
|
|
172
|
+
exports.cleanObject = cleanObject;
|
|
98
173
|
class Collection {
|
|
99
174
|
constructor(origin) {
|
|
100
175
|
_Collection_locked.set(this, new Set());
|
|
@@ -182,3 +257,32 @@ _Collection_locked = new WeakMap(), _Collection_matched = new WeakMap(), _Collec
|
|
|
182
257
|
class UnsupportedError extends Error {
|
|
183
258
|
}
|
|
184
259
|
exports.UnsupportedError = UnsupportedError;
|
|
260
|
+
function modelLog(model, repeat) {
|
|
261
|
+
if (!isModel(model)) {
|
|
262
|
+
return orderLog(model, repeat);
|
|
263
|
+
}
|
|
264
|
+
if (typeof model === 'string') {
|
|
265
|
+
return `<${model}>${repeat}`;
|
|
266
|
+
}
|
|
267
|
+
return `(<${model.join('>|<')}>)${repeat}`;
|
|
268
|
+
}
|
|
269
|
+
exports.modelLog = modelLog;
|
|
270
|
+
function orderLog(order, repeat) {
|
|
271
|
+
return order.length === 1
|
|
272
|
+
? markRepeat(patternLog(order[0]), repeat)
|
|
273
|
+
: markRepeat(order.map(pattern => patternLog(pattern)).join(''), repeat);
|
|
274
|
+
}
|
|
275
|
+
function patternLog(pattern) {
|
|
276
|
+
if (isTransparent(pattern)) {
|
|
277
|
+
// 適当
|
|
278
|
+
return `:transparent(${modelLog(pattern.transparent, '')})`;
|
|
279
|
+
}
|
|
280
|
+
if (isChoice(pattern)) {
|
|
281
|
+
return `(${pattern.choice.map(candidate => orderLog(candidate, '')).join('|')})`;
|
|
282
|
+
}
|
|
283
|
+
const { model, repeat } = normalizeModel(pattern);
|
|
284
|
+
return modelLog(model, repeat);
|
|
285
|
+
}
|
|
286
|
+
function markRepeat(pattern, repeat) {
|
|
287
|
+
return repeat ? `(${pattern})${repeat}` : pattern;
|
|
288
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/rules",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Built-in rules of markuplint",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"./lib/permitted-contents/debug.js": "./lib/permitted-contents/debug.browser.js"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@markuplint/html-spec": "3.0.
|
|
24
|
-
"@markuplint/ml-core": "3.0.
|
|
25
|
-
"@markuplint/ml-spec": "3.0.
|
|
23
|
+
"@markuplint/html-spec": "3.0.1",
|
|
24
|
+
"@markuplint/ml-core": "3.0.1",
|
|
25
|
+
"@markuplint/ml-spec": "3.0.1",
|
|
26
26
|
"@markuplint/types": "3.0.0",
|
|
27
27
|
"@ungap/structured-clone": "^1.0.1",
|
|
28
28
|
"debug": "^4.3.4",
|
|
@@ -32,5 +32,5 @@
|
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/debug": "^4.1.7"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "4ade31aab89b4bcc3527d4b00bcbfa3dbd6eb032"
|
|
36
36
|
}
|