@markuplint/ml-core 2.0.0-rc.0 → 2.0.0-rc.6
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/index.d.ts +1 -1
- package/lib/index.js +3 -3
- package/lib/ml-core.d.ts +3 -2
- package/lib/ml-core.js +51 -28
- package/lib/ml-dom/document.d.ts +9 -1
- package/lib/ml-dom/document.js +38 -27
- package/lib/ml-dom/helper/match-selector.d.ts +12 -1
- package/lib/ml-dom/helper/match-selector.js +105 -87
- package/lib/ml-dom/helper/node-store.js +7 -2
- package/lib/ml-dom/helper/selector.d.ts +5 -3
- package/lib/ml-dom/helper/selector.js +264 -85
- package/lib/ml-dom/rule-mapper.d.ts +2 -1
- package/lib/ml-dom/rule-mapper.js +15 -9
- package/lib/ml-dom/tokens/abstract-element.d.ts +1 -0
- package/lib/ml-dom/tokens/abstract-element.js +31 -6
- package/lib/ml-dom/tokens/attribute.d.ts +1 -0
- package/lib/ml-dom/tokens/attribute.js +7 -0
- package/lib/ml-dom/tokens/node.d.ts +6 -5
- package/lib/ml-dom/tokens/node.js +20 -9
- package/lib/ml-dom/tokens/preprocessor-specific-attribute.d.ts +1 -0
- package/lib/ml-dom/tokens/preprocessor-specific-attribute.js +3 -0
- package/lib/ml-rule/ml-rule.d.ts +5 -2
- package/lib/ml-rule/ml-rule.js +17 -3
- package/lib/ml-rule/types.d.ts +3 -3
- package/markuplint-recommended.json +151 -11
- package/package.json +8 -7
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -69,5 +69,12 @@ class MLDOMAttribute extends token_1.default {
|
|
|
69
69
|
toString(withSpace = true) {
|
|
70
70
|
return (withSpace ? this.spacesBeforeName.raw : '') + this.raw;
|
|
71
71
|
}
|
|
72
|
+
toNormalizeString() {
|
|
73
|
+
return (this.name.originRaw +
|
|
74
|
+
this.equal.originRaw +
|
|
75
|
+
this.startQuote.originRaw +
|
|
76
|
+
this.value.originRaw +
|
|
77
|
+
this.endQuote.originRaw);
|
|
78
|
+
}
|
|
72
79
|
}
|
|
73
80
|
exports.default = MLDOMAttribute;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Document } from '../';
|
|
2
2
|
import type { RuleInfo } from '../../';
|
|
3
3
|
import type { AnonymousNode, IMLDOMNode, NodeType } from '../types';
|
|
4
|
-
import type { MLDOMElement, MLDOMOmittedElement } from './';
|
|
4
|
+
import type { MLDOMElement, MLDOMOmittedElement, MLDOMPreprocessorSpecificBlock } from './';
|
|
5
5
|
import type { MLASTAbstructNode } from '@markuplint/ml-ast';
|
|
6
6
|
import type { AnyRule, RuleConfigValue } from '@markuplint/ml-config';
|
|
7
7
|
import MLDOMToken from './token';
|
|
@@ -11,13 +11,14 @@ export default abstract class MLDOMNode<T extends RuleConfigValue, O = null, A e
|
|
|
11
11
|
readonly rules: Record<string, AnyRule>;
|
|
12
12
|
protected _astToken: A;
|
|
13
13
|
constructor(astNode: A, document: Document<T, O>);
|
|
14
|
-
get parentNode(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | null;
|
|
14
|
+
get parentNode(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | MLDOMPreprocessorSpecificBlock<T, O> | null;
|
|
15
15
|
get prevNode(): AnonymousNode<T, O> | null;
|
|
16
16
|
get nextNode(): AnonymousNode<T, O> | null;
|
|
17
|
-
get syntaxicalParentNode(): MLDOMElement<T, O> | null;
|
|
17
|
+
get syntaxicalParentNode(): MLDOMElement<T, O> | MLDOMPreprocessorSpecificBlock<T, O> | null;
|
|
18
18
|
get prevToken(): AnonymousNode<T, O> | null;
|
|
19
19
|
get nodeStore(): import("../helper").NodeStore;
|
|
20
|
-
toString(): string;
|
|
21
|
-
is(type: NodeType): boolean;
|
|
22
20
|
get rule(): RuleInfo<T, O>;
|
|
21
|
+
getParentElement(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | null;
|
|
22
|
+
is(type: NodeType): boolean;
|
|
23
|
+
toString(): string;
|
|
23
24
|
}
|
|
@@ -70,23 +70,34 @@ class MLDOMNode extends token_1.default {
|
|
|
70
70
|
get nodeStore() {
|
|
71
71
|
return (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").nodeStore;
|
|
72
72
|
}
|
|
73
|
-
toString() {
|
|
74
|
-
return this.raw;
|
|
75
|
-
}
|
|
76
|
-
is(type) {
|
|
77
|
-
return this.type === type;
|
|
78
|
-
}
|
|
79
73
|
get rule() {
|
|
80
74
|
if (!(0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").currentRule) {
|
|
81
75
|
throw new Error('Invalid call.');
|
|
82
76
|
}
|
|
83
77
|
const name = (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").currentRule.name;
|
|
84
78
|
const rule = this.rules[name];
|
|
85
|
-
if (rule == null) {
|
|
86
|
-
throw new Error('Invalid call "rule" property.');
|
|
87
|
-
}
|
|
88
79
|
return (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").currentRule.optimizeOption(rule);
|
|
89
80
|
}
|
|
81
|
+
getParentElement() {
|
|
82
|
+
let parent = this.parentNode;
|
|
83
|
+
if (!parent) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
while (parent) {
|
|
87
|
+
if (parent.type === 'PSBlock') {
|
|
88
|
+
parent = parent.parentNode;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
return parent;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
is(type) {
|
|
96
|
+
return this.type === type;
|
|
97
|
+
}
|
|
98
|
+
toString() {
|
|
99
|
+
return this.raw;
|
|
100
|
+
}
|
|
90
101
|
}
|
|
91
102
|
exports.default = MLDOMNode;
|
|
92
103
|
_MLDOMNode_doc = new WeakMap(), _MLDOMNode_prevToken = new WeakMap();
|
package/lib/ml-rule/ml-rule.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { Ruleset } from '..';
|
|
1
2
|
import type Document from '../ml-dom/document';
|
|
2
3
|
import type { RuleSeed } from './types';
|
|
3
4
|
import type { LocaleSet } from '@markuplint/i18n';
|
|
4
|
-
import type { RuleConfig, RuleConfigValue, RuleInfo, Severity, Violation } from '@markuplint/ml-config';
|
|
5
|
+
import type { GlobalRuleInfo, RuleConfig, RuleConfigValue, RuleInfo, Rules, Severity, Violation } from '@markuplint/ml-config';
|
|
5
6
|
export declare class MLRule<T extends RuleConfigValue, O = null> {
|
|
6
7
|
#private;
|
|
7
8
|
readonly name: string;
|
|
@@ -22,6 +23,8 @@ export declare class MLRule<T extends RuleConfigValue, O = null> {
|
|
|
22
23
|
name: string;
|
|
23
24
|
});
|
|
24
25
|
verify(document: Document<T, O>, locale: LocaleSet, globalRule: RuleInfo<T, O>, fix: boolean): Promise<Violation[]>;
|
|
25
|
-
|
|
26
|
+
getRuleInfo(ruleSet: Ruleset, ruleName: string): GlobalRuleInfo<T, O>;
|
|
27
|
+
_optimize(rules: Rules | undefined, ruleName: string): RuleInfo<T, O>;
|
|
28
|
+
optimizeOption(configSettings: T | RuleConfig<T, O> | undefined): RuleInfo<T, O>;
|
|
26
29
|
}
|
|
27
30
|
export declare type AnyMLRule = MLRule<RuleConfigValue, unknown>;
|
package/lib/ml-rule/ml-rule.js
CHANGED
|
@@ -6,12 +6,13 @@ const tslib_1 = require("tslib");
|
|
|
6
6
|
const ml_rule_context_1 = require("./ml-rule-context");
|
|
7
7
|
class MLRule {
|
|
8
8
|
constructor(o) {
|
|
9
|
+
var _a, _b;
|
|
9
10
|
_MLRule_v.set(this, void 0);
|
|
10
11
|
_MLRule_f.set(this, void 0);
|
|
11
12
|
this.name = o.name;
|
|
12
13
|
this.defaultServerity = o.defaultServerity || 'error';
|
|
13
|
-
this.defaultValue = o.defaultValue;
|
|
14
|
-
this.defaultOptions = o.defaultOptions;
|
|
14
|
+
this.defaultValue = (_a = o.defaultValue) !== null && _a !== void 0 ? _a : true;
|
|
15
|
+
this.defaultOptions = (_b = o.defaultOptions) !== null && _b !== void 0 ? _b : null;
|
|
15
16
|
(0, tslib_1.__classPrivateFieldSet)(this, _MLRule_v, o.verify, "f");
|
|
16
17
|
(0, tslib_1.__classPrivateFieldSet)(this, _MLRule_f, o.fix, "f");
|
|
17
18
|
}
|
|
@@ -79,8 +80,21 @@ class MLRule {
|
|
|
79
80
|
document.setRule(null);
|
|
80
81
|
return violation;
|
|
81
82
|
}
|
|
83
|
+
getRuleInfo(ruleSet, ruleName) {
|
|
84
|
+
const info = this._optimize(ruleSet.rules, ruleName);
|
|
85
|
+
return {
|
|
86
|
+
...info,
|
|
87
|
+
nodeRules: ruleSet.nodeRules.map(r => this._optimize(r.rules, ruleName)).filter(r => !r.disabled),
|
|
88
|
+
childNodeRules: ruleSet.childNodeRules.map(r => this._optimize(r.rules, ruleName)).filter(r => !r.disabled),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
_optimize(rules, ruleName) {
|
|
92
|
+
const rule = (rules && rules[ruleName]) || false;
|
|
93
|
+
const info = this.optimizeOption(rule);
|
|
94
|
+
return info;
|
|
95
|
+
}
|
|
82
96
|
optimizeOption(configSettings) {
|
|
83
|
-
if (typeof configSettings === 'boolean') {
|
|
97
|
+
if (configSettings === undefined || typeof configSettings === 'boolean') {
|
|
84
98
|
return {
|
|
85
99
|
disabled: !configSettings,
|
|
86
100
|
severity: this.defaultServerity,
|
package/lib/ml-rule/types.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { MLRuleContext } from './ml-rule-context';
|
|
2
2
|
import type { RuleConfigValue, Severity } from '@markuplint/ml-config';
|
|
3
|
-
export declare type RuleSeed<T extends RuleConfigValue, O = null> = {
|
|
3
|
+
export declare type RuleSeed<T extends RuleConfigValue = boolean, O = null> = {
|
|
4
4
|
defaultServerity?: Severity;
|
|
5
|
-
defaultValue
|
|
6
|
-
defaultOptions
|
|
5
|
+
defaultValue?: T;
|
|
6
|
+
defaultOptions?: O;
|
|
7
7
|
verify(context: ReturnType<MLRuleContext<T, O>['provide']>): void | Promise<void>;
|
|
8
8
|
fix?(context: ReturnType<MLRuleContext<T, O>['provide']>): void | Promise<void>;
|
|
9
9
|
};
|
|
@@ -1,54 +1,194 @@
|
|
|
1
1
|
{
|
|
2
2
|
"rules": {
|
|
3
3
|
"attr-duplication": true,
|
|
4
|
+
"attr-equal-space-after": false,
|
|
5
|
+
"attr-equal-space-before": false,
|
|
6
|
+
"attr-spacing": false,
|
|
7
|
+
"attr-value-quotes": false,
|
|
8
|
+
"case-sensitive-attr-name": false,
|
|
9
|
+
"case-sensitive-tag-name": false,
|
|
4
10
|
"character-reference": true,
|
|
11
|
+
"class-naming": false,
|
|
5
12
|
"deprecated-attr": true,
|
|
6
13
|
"deprecated-element": true,
|
|
14
|
+
"disallowed-element": ["hgroup"],
|
|
7
15
|
"doctype": true,
|
|
16
|
+
"end-tag": false,
|
|
8
17
|
"id-duplication": true,
|
|
18
|
+
"indentation": false,
|
|
19
|
+
"ineffective-attr": true,
|
|
20
|
+
"invalid-attr": {
|
|
21
|
+
"option": {
|
|
22
|
+
"attrs": {
|
|
23
|
+
"autofocus": {
|
|
24
|
+
"disallowed": true
|
|
25
|
+
},
|
|
26
|
+
"accesskey": {
|
|
27
|
+
"disallowed": true
|
|
28
|
+
},
|
|
29
|
+
"tabindex": {
|
|
30
|
+
"enum": ["-1", "0"]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"landmark-roles": true,
|
|
36
|
+
"no-boolean-attr-value": true,
|
|
37
|
+
"no-default-value": false,
|
|
38
|
+
"no-hard-code-id": false,
|
|
39
|
+
"no-refer-to-non-existent-id": true,
|
|
40
|
+
"no-use-event-handler-attr": false,
|
|
9
41
|
"permitted-contents": true,
|
|
10
42
|
"required-attr": true,
|
|
11
|
-
"
|
|
12
|
-
"landmark-roles": true,
|
|
43
|
+
"required-element": false,
|
|
13
44
|
"required-h1": true,
|
|
14
45
|
"wai-aria": true
|
|
15
46
|
},
|
|
16
47
|
"nodeRules": [
|
|
17
48
|
{
|
|
18
|
-
"selector": "html",
|
|
49
|
+
"selector": ":where(html)",
|
|
19
50
|
"rules": {
|
|
20
51
|
"required-attr": ["lang"]
|
|
21
52
|
}
|
|
22
53
|
},
|
|
23
54
|
{
|
|
24
|
-
"selector": "
|
|
55
|
+
"selector": ":where(head)",
|
|
56
|
+
"rules": {
|
|
57
|
+
"required-element": ["meta[charset=\"UTF-8\" i]"]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"selector": ":where(meta[property])",
|
|
62
|
+
"rules": {
|
|
63
|
+
"invalid-attr": {
|
|
64
|
+
"option": {
|
|
65
|
+
"attrs": {
|
|
66
|
+
"property": {
|
|
67
|
+
"pattern": "/^og:[a-z_]+/"
|
|
68
|
+
},
|
|
69
|
+
"content": {
|
|
70
|
+
"type": "NoEmptyAny"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"required-attr": false
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"selector": ":where(meta[itemprop])",
|
|
80
|
+
"rules": {
|
|
81
|
+
"invalid-attr": {
|
|
82
|
+
"option": {
|
|
83
|
+
"attrs": {
|
|
84
|
+
"content": {
|
|
85
|
+
"type": "NoEmptyAny"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"selector": ":where(script[src])",
|
|
25
94
|
"rules": {
|
|
26
95
|
"required-attr": ["defer"]
|
|
27
96
|
}
|
|
28
97
|
},
|
|
29
98
|
{
|
|
30
|
-
"selector": "
|
|
99
|
+
"selector": "h1, h2, h3, h4, h5, h6",
|
|
100
|
+
"rules": {
|
|
101
|
+
"disallowed-element": {
|
|
102
|
+
"value": ["small"],
|
|
103
|
+
"reason": "The small element must not be used for subheadings. https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-small-element"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"selector": ":where(img)",
|
|
31
109
|
"rules": {
|
|
32
|
-
"required-attr": [
|
|
110
|
+
"required-attr": [
|
|
111
|
+
"width",
|
|
112
|
+
"height",
|
|
113
|
+
"alt",
|
|
114
|
+
{
|
|
115
|
+
"name": "decoding",
|
|
116
|
+
"value": "async"
|
|
117
|
+
}
|
|
118
|
+
]
|
|
33
119
|
}
|
|
34
120
|
},
|
|
35
121
|
{
|
|
36
|
-
"selector": "iframe",
|
|
122
|
+
"selector": ":where(iframe)",
|
|
37
123
|
"rules": {
|
|
38
|
-
"required-attr": [
|
|
124
|
+
"required-attr": [
|
|
125
|
+
"title",
|
|
126
|
+
{
|
|
127
|
+
"name": "loading",
|
|
128
|
+
"value": "lazy"
|
|
129
|
+
}
|
|
130
|
+
]
|
|
39
131
|
}
|
|
40
132
|
},
|
|
41
133
|
{
|
|
42
|
-
"selector": "a[target=_blank], area[target=_blank]",
|
|
134
|
+
"selector": ":where(a[target=_blank], area[target=_blank])",
|
|
43
135
|
"rules": {
|
|
44
|
-
"required-attr":
|
|
136
|
+
"required-attr": {
|
|
137
|
+
"value": [
|
|
138
|
+
{
|
|
139
|
+
"name": "rel",
|
|
140
|
+
"value": "/(?<![^\\s]+)noreferrer(?![^\\s]+)/"
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
"reason": "The \"rel\" attribute should be required with \"noreferrer\" if the \"a\" element has the \"target=_black\""
|
|
144
|
+
}
|
|
45
145
|
}
|
|
46
146
|
},
|
|
47
147
|
{
|
|
48
|
-
"selector": "abbr",
|
|
148
|
+
"selector": ":where(abbr)",
|
|
49
149
|
"rules": {
|
|
50
150
|
"required-attr": ["title"]
|
|
51
151
|
}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"selector": ":where(video, audio)",
|
|
155
|
+
"rules": {
|
|
156
|
+
"required-element": ["track"]
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"selector": ":where(video[autoplay])",
|
|
161
|
+
"rules": {
|
|
162
|
+
"required-attr": ["muted"]
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"selector": ":where(th, td)",
|
|
167
|
+
"rules": {
|
|
168
|
+
"invalid-attr": {
|
|
169
|
+
"option": {
|
|
170
|
+
"attrs": {
|
|
171
|
+
"span": {
|
|
172
|
+
"disallowed": false
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"selector": ":where(body :not(button))",
|
|
181
|
+
"rules": {
|
|
182
|
+
"invalid-attr": {
|
|
183
|
+
"option": {
|
|
184
|
+
"attrs": {
|
|
185
|
+
"onclick": {
|
|
186
|
+
"disallowed": false
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
52
192
|
}
|
|
53
193
|
]
|
|
54
194
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/ml-core",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.6",
|
|
4
4
|
"description": "The core module of markuplint",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -17,17 +17,18 @@
|
|
|
17
17
|
"clean": "tsc --build --clean"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@markuplint/i18n": "2.0.0-rc.
|
|
21
|
-
"@markuplint/ml-ast": "2.0.0-rc.
|
|
22
|
-
"@markuplint/ml-config": "2.0.0-rc.
|
|
23
|
-
"@markuplint/ml-spec": "2.0.0-rc.
|
|
20
|
+
"@markuplint/i18n": "2.0.0-rc.5",
|
|
21
|
+
"@markuplint/ml-ast": "2.0.0-rc.6",
|
|
22
|
+
"@markuplint/ml-config": "2.0.0-rc.5",
|
|
23
|
+
"@markuplint/ml-spec": "2.0.0-rc.6",
|
|
24
|
+
"@markuplint/parser-utils": "2.0.0-rc.6",
|
|
24
25
|
"debug": "^4.3.2",
|
|
25
26
|
"postcss-selector-parser": "^6.0.6",
|
|
26
27
|
"tslib": "^2.3.1"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"@markuplint/html-parser": "2.0.0-rc.
|
|
30
|
+
"@markuplint/html-parser": "2.0.0-rc.6",
|
|
30
31
|
"@types/debug": "^4.1.7"
|
|
31
32
|
},
|
|
32
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "7c93367a86f935f6b94780b1fa14f3293f900b87"
|
|
33
34
|
}
|