@markuplint/ml-core 2.0.0-dev.26 → 2.0.0-rc.5
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/convert-ruleset.d.ts +1 -1
- package/lib/convert-ruleset.js +1 -1
- package/lib/debug.js +8 -2
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -1
- package/lib/ml-core.d.ts +2 -1
- package/lib/ml-core.js +25 -16
- package/lib/ml-dom/document.d.ts +5 -2
- package/lib/ml-dom/document.js +99 -51
- package/lib/ml-dom/helper/match-selector.d.ts +12 -1
- package/lib/ml-dom/helper/match-selector.js +108 -90
- package/lib/ml-dom/helper/selector.d.ts +5 -3
- package/lib/ml-dom/helper/selector.js +275 -79
- package/lib/ml-dom/helper/walkers.js +1 -1
- package/lib/ml-dom/rule-mapper.d.ts +16 -0
- package/lib/ml-dom/rule-mapper.js +57 -0
- 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 +8 -7
- package/lib/ml-dom/tokens/node.js +21 -13
- 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-dom/tokens/token.d.ts +0 -2
- package/lib/ml-dom/tokens/token.js +0 -1
- package/lib/ml-rule/ml-rule.d.ts +5 -2
- package/lib/ml-rule/ml-rule.js +19 -3
- package/lib/ml-rule/types.d.ts +3 -3
- package/lib/test/index.d.ts +8 -5
- package/lib/test/index.js +7 -7
- package/markuplint-recommended.json +150 -11
- package/package.json +7 -7
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/create-rule.d.ts +0 -4
- package/lib/create-rule.js +0 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var _MLDOMAbstractElement_fixedNodeName;
|
|
2
|
+
var _MLDOMAbstractElement_fixedNodeName, _MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache, _MLDOMAbstractElement_normalizedString;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const ml_spec_1 = require("@markuplint/ml-spec");
|
|
@@ -15,6 +15,8 @@ class MLDOMAbstractElement extends node_1.default {
|
|
|
15
15
|
this.childModels = new Set();
|
|
16
16
|
this.descendantModels = new Set();
|
|
17
17
|
_MLDOMAbstractElement_fixedNodeName.set(this, void 0);
|
|
18
|
+
_MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache.set(this, null);
|
|
19
|
+
_MLDOMAbstractElement_normalizedString.set(this, null);
|
|
18
20
|
this.nodeName = astNode.nodeName;
|
|
19
21
|
(0, tslib_1.__classPrivateFieldSet)(this, _MLDOMAbstractElement_fixedNodeName, astNode.nodeName, "f");
|
|
20
22
|
this.namespaceURI = astNode.namespace;
|
|
@@ -113,7 +115,7 @@ class MLDOMAbstractElement extends node_1.default {
|
|
|
113
115
|
if (selecor.match(el, this)) {
|
|
114
116
|
return el;
|
|
115
117
|
}
|
|
116
|
-
el = el.
|
|
118
|
+
el = el.getParentElement();
|
|
117
119
|
} while (el !== null && el.type === 'Element');
|
|
118
120
|
return null;
|
|
119
121
|
}
|
|
@@ -145,12 +147,15 @@ class MLDOMAbstractElement extends node_1.default {
|
|
|
145
147
|
return !!this.getAttributeToken(attrName).length;
|
|
146
148
|
}
|
|
147
149
|
matches(selector) {
|
|
148
|
-
return (0, helper_1.createSelector)(selector).match(this);
|
|
150
|
+
return !!(0, helper_1.createSelector)(selector).match(this);
|
|
149
151
|
}
|
|
150
152
|
fixNodeName(name) {
|
|
151
153
|
(0, tslib_1.__classPrivateFieldSet)(this, _MLDOMAbstractElement_fixedNodeName, name, "f");
|
|
152
154
|
}
|
|
153
155
|
getChildElementsAndTextNodeWithoutWhitespaces() {
|
|
156
|
+
if ((0, tslib_1.__classPrivateFieldGet)(this, _MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache, "f")) {
|
|
157
|
+
return (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache, "f");
|
|
158
|
+
}
|
|
154
159
|
const filteredNodes = [];
|
|
155
160
|
this.childNodes.forEach(node => {
|
|
156
161
|
if (node.type === 'Element') {
|
|
@@ -164,6 +169,7 @@ class MLDOMAbstractElement extends node_1.default {
|
|
|
164
169
|
filteredNodes.push(...children);
|
|
165
170
|
}
|
|
166
171
|
});
|
|
172
|
+
(0, tslib_1.__classPrivateFieldSet)(this, _MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache, filteredNodes, "f");
|
|
167
173
|
return filteredNodes;
|
|
168
174
|
}
|
|
169
175
|
/**
|
|
@@ -173,7 +179,7 @@ class MLDOMAbstractElement extends node_1.default {
|
|
|
173
179
|
return this.childNodes.some(node => node.type === 'PSBlock');
|
|
174
180
|
}
|
|
175
181
|
isDescendantByUUIDList(uuidList) {
|
|
176
|
-
let el = this.
|
|
182
|
+
let el = this.getParentElement();
|
|
177
183
|
if (el === null) {
|
|
178
184
|
return false;
|
|
179
185
|
}
|
|
@@ -181,10 +187,29 @@ class MLDOMAbstractElement extends node_1.default {
|
|
|
181
187
|
if (uuidList.includes(el.uuid)) {
|
|
182
188
|
return true;
|
|
183
189
|
}
|
|
184
|
-
el = el.
|
|
190
|
+
el = el.getParentElement();
|
|
185
191
|
} while (el !== null && el.type === 'Element');
|
|
186
192
|
return false;
|
|
187
193
|
}
|
|
194
|
+
toNormalizeString() {
|
|
195
|
+
if ((0, tslib_1.__classPrivateFieldGet)(this, _MLDOMAbstractElement_normalizedString, "f")) {
|
|
196
|
+
return (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMAbstractElement_normalizedString, "f");
|
|
197
|
+
}
|
|
198
|
+
const children = this.getChildElementsAndTextNodeWithoutWhitespaces();
|
|
199
|
+
const attrs = this.attributes.map(attr => attr.toNormalizeString());
|
|
200
|
+
const attrString = attrs.length ? ' ' + attrs.join('') : '';
|
|
201
|
+
const startTag = `<${this.nodeName}${attrString}>`;
|
|
202
|
+
const childNodes = children.map(node => {
|
|
203
|
+
if (node.type === 'Element') {
|
|
204
|
+
return node.toNormalizeString();
|
|
205
|
+
}
|
|
206
|
+
return node.originRaw;
|
|
207
|
+
});
|
|
208
|
+
const endTag = `</${this.nodeName}>`;
|
|
209
|
+
const normalizedString = `${startTag}${childNodes.join('')}${endTag}`;
|
|
210
|
+
(0, tslib_1.__classPrivateFieldSet)(this, _MLDOMAbstractElement_normalizedString, normalizedString, "f");
|
|
211
|
+
return normalizedString;
|
|
212
|
+
}
|
|
188
213
|
}
|
|
189
214
|
exports.default = MLDOMAbstractElement;
|
|
190
|
-
_MLDOMAbstractElement_fixedNodeName = new WeakMap();
|
|
215
|
+
_MLDOMAbstractElement_fixedNodeName = new WeakMap(), _MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache = new WeakMap(), _MLDOMAbstractElement_normalizedString = new WeakMap();
|
|
@@ -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,23 +1,24 @@
|
|
|
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
|
-
import type { RuleConfigValue } from '@markuplint/ml-config';
|
|
6
|
+
import type { AnyRule, RuleConfigValue } from '@markuplint/ml-config';
|
|
7
7
|
import MLDOMToken from './token';
|
|
8
8
|
export default abstract class MLDOMNode<T extends RuleConfigValue, O = null, A extends MLASTAbstructNode = MLASTAbstructNode> extends MLDOMToken<A> implements IMLDOMNode {
|
|
9
9
|
#private;
|
|
10
10
|
readonly type: NodeType;
|
|
11
|
+
readonly rules: Record<string, AnyRule>;
|
|
11
12
|
protected _astToken: A;
|
|
12
13
|
constructor(astNode: A, document: Document<T, O>);
|
|
13
|
-
get parentNode(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | null;
|
|
14
|
+
get parentNode(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | MLDOMPreprocessorSpecificBlock<T, O> | null;
|
|
14
15
|
get prevNode(): AnonymousNode<T, O> | null;
|
|
15
16
|
get nextNode(): AnonymousNode<T, O> | null;
|
|
16
|
-
get syntaxicalParentNode(): MLDOMElement<T, O> | null;
|
|
17
|
+
get syntaxicalParentNode(): MLDOMElement<T, O> | MLDOMPreprocessorSpecificBlock<T, O> | null;
|
|
17
18
|
get prevToken(): AnonymousNode<T, O> | null;
|
|
18
19
|
get nodeStore(): import("../helper").NodeStore;
|
|
19
|
-
toString(): string;
|
|
20
|
-
is(type: NodeType): boolean;
|
|
21
20
|
get rule(): RuleInfo<T, O>;
|
|
22
|
-
|
|
21
|
+
getParentElement(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | null;
|
|
22
|
+
is(type: NodeType): boolean;
|
|
23
|
+
toString(): string;
|
|
23
24
|
}
|
|
@@ -7,6 +7,7 @@ class MLDOMNode extends token_1.default {
|
|
|
7
7
|
constructor(astNode, document) {
|
|
8
8
|
super(astNode);
|
|
9
9
|
this.type = 'Node';
|
|
10
|
+
this.rules = {};
|
|
10
11
|
_MLDOMNode_doc.set(this, void 0);
|
|
11
12
|
/**
|
|
12
13
|
* prevToken cache props
|
|
@@ -69,26 +70,33 @@ class MLDOMNode extends token_1.default {
|
|
|
69
70
|
get nodeStore() {
|
|
70
71
|
return (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").nodeStore;
|
|
71
72
|
}
|
|
72
|
-
toString() {
|
|
73
|
-
return this.raw;
|
|
74
|
-
}
|
|
75
|
-
is(type) {
|
|
76
|
-
return this.type === type;
|
|
77
|
-
}
|
|
78
73
|
get rule() {
|
|
79
74
|
if (!(0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").currentRule) {
|
|
80
75
|
throw new Error('Invalid call.');
|
|
81
76
|
}
|
|
82
77
|
const name = (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").currentRule.name;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
78
|
+
const rule = this.rules[name];
|
|
79
|
+
return (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").currentRule.optimizeOption(rule);
|
|
80
|
+
}
|
|
81
|
+
getParentElement() {
|
|
82
|
+
let parent = this.parentNode;
|
|
83
|
+
if (!parent) {
|
|
84
|
+
return null;
|
|
87
85
|
}
|
|
88
|
-
|
|
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;
|
|
89
97
|
}
|
|
90
|
-
|
|
91
|
-
return
|
|
98
|
+
toString() {
|
|
99
|
+
return this.raw;
|
|
92
100
|
}
|
|
93
101
|
}
|
|
94
102
|
exports.default = MLDOMNode;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { MLToken } from '@markuplint/ml-ast';
|
|
2
|
-
import type { Rules } from '@markuplint/ml-config';
|
|
3
2
|
export default class MLDOMToken<A extends MLToken> {
|
|
4
3
|
#private;
|
|
5
4
|
readonly uuid: string;
|
|
6
|
-
readonly rules: Rules;
|
|
7
5
|
protected readonly _astToken: A;
|
|
8
6
|
constructor(astToken: A);
|
|
9
7
|
get originRaw(): string;
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
class MLDOMToken {
|
|
6
6
|
constructor(astToken) {
|
|
7
|
-
this.rules = {};
|
|
8
7
|
_MLDOMToken_startLine.set(this, void 0);
|
|
9
8
|
_MLDOMToken_endLine.set(this, void 0);
|
|
10
9
|
_MLDOMToken_startCol.set(this, void 0);
|
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,13 +80,27 @@ 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,
|
|
87
101
|
value: this.defaultValue,
|
|
88
102
|
option: this.defaultOptions,
|
|
103
|
+
reason: undefined,
|
|
89
104
|
};
|
|
90
105
|
}
|
|
91
106
|
if (!Array.isArray(configSettings) && typeof configSettings === 'object' && configSettings !== null) {
|
|
@@ -114,6 +129,7 @@ class MLRule {
|
|
|
114
129
|
// @ts-ignore TODO: Wait for fix to bug of type guards in TypeScript
|
|
115
130
|
value: configSettings == null ? this.defaultValue : configSettings,
|
|
116
131
|
option: this.defaultOptions,
|
|
132
|
+
reason: undefined,
|
|
117
133
|
};
|
|
118
134
|
}
|
|
119
135
|
}
|
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
|
};
|
package/lib/test/index.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
import type { MLMarkupLanguageParser } from '@markuplint/ml-ast';
|
|
1
2
|
import type { Config, RuleConfigValue } from '@markuplint/ml-config';
|
|
2
3
|
import type { ExtendedSpec, MLMLSpec } from '@markuplint/ml-spec';
|
|
3
4
|
import { Document } from '../ml-dom';
|
|
4
|
-
export declare
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
export declare type CreateTestOptions = {
|
|
6
|
+
config?: Config;
|
|
7
|
+
parser?: MLMarkupLanguageParser;
|
|
8
|
+
};
|
|
9
|
+
export declare function createTestDocument<T extends RuleConfigValue = any, O = any>(sourceCode: string, options?: CreateTestOptions): Document<T, O>;
|
|
10
|
+
export declare function createTestNodeList(sourceCode: string, options?: CreateTestOptions): readonly import("../ml-dom").AnonymousNode<any, any>[];
|
|
11
|
+
export declare function createTestElement(sourceCode: string, options?: CreateTestOptions): import("../ml-dom").Element<any, any>;
|
|
8
12
|
/**
|
|
9
13
|
* for test suite
|
|
10
14
|
*/
|
|
11
15
|
export declare function dummySchemas(): [MLMLSpec, ...ExtendedSpec[]];
|
|
12
|
-
export {};
|
package/lib/test/index.js
CHANGED
|
@@ -4,20 +4,20 @@ exports.dummySchemas = exports.createTestElement = exports.createTestNodeList =
|
|
|
4
4
|
const html_parser_1 = require("@markuplint/html-parser");
|
|
5
5
|
const convert_ruleset_1 = require("../convert-ruleset");
|
|
6
6
|
const ml_dom_1 = require("../ml-dom");
|
|
7
|
-
function createTestDocument(sourceCode,
|
|
8
|
-
const ast = (0, html_parser_1.parse)(sourceCode);
|
|
9
|
-
const ruleset = (0, convert_ruleset_1.convertRuleset)(config);
|
|
7
|
+
function createTestDocument(sourceCode, options) {
|
|
8
|
+
const ast = (options === null || options === void 0 ? void 0 : options.parser) ? options.parser.parse(sourceCode) : (0, html_parser_1.parse)(sourceCode);
|
|
9
|
+
const ruleset = (0, convert_ruleset_1.convertRuleset)(options === null || options === void 0 ? void 0 : options.config);
|
|
10
10
|
const document = new ml_dom_1.Document(ast, ruleset, [{}, {}]);
|
|
11
11
|
return document;
|
|
12
12
|
}
|
|
13
13
|
exports.createTestDocument = createTestDocument;
|
|
14
|
-
function createTestNodeList(sourceCode) {
|
|
15
|
-
const document = createTestDocument(sourceCode);
|
|
14
|
+
function createTestNodeList(sourceCode, options) {
|
|
15
|
+
const document = createTestDocument(sourceCode, options);
|
|
16
16
|
return document.nodeList;
|
|
17
17
|
}
|
|
18
18
|
exports.createTestNodeList = createTestNodeList;
|
|
19
|
-
function createTestElement(sourceCode) {
|
|
20
|
-
const document = createTestDocument(sourceCode);
|
|
19
|
+
function createTestElement(sourceCode, options) {
|
|
20
|
+
const document = createTestDocument(sourceCode, options);
|
|
21
21
|
const el = document.nodeList[0];
|
|
22
22
|
if (el.type === 'Element') {
|
|
23
23
|
return el;
|
|
@@ -1,54 +1,193 @@
|
|
|
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,
|
|
8
16
|
"id-duplication": true,
|
|
17
|
+
"indentation": false,
|
|
18
|
+
"ineffective-attr": true,
|
|
19
|
+
"invalid-attr": {
|
|
20
|
+
"option": {
|
|
21
|
+
"attrs": {
|
|
22
|
+
"autofocus": {
|
|
23
|
+
"disallowed": true
|
|
24
|
+
},
|
|
25
|
+
"accesskey": {
|
|
26
|
+
"disallowed": true
|
|
27
|
+
},
|
|
28
|
+
"tabindex": {
|
|
29
|
+
"enum": ["-1", "0"]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"landmark-roles": true,
|
|
35
|
+
"no-boolean-attr-value": true,
|
|
36
|
+
"no-default-value": false,
|
|
37
|
+
"no-hard-code-id": false,
|
|
38
|
+
"no-refer-to-non-existent-id": true,
|
|
39
|
+
"no-use-event-handler-attr": false,
|
|
9
40
|
"permitted-contents": true,
|
|
10
41
|
"required-attr": true,
|
|
11
|
-
"
|
|
12
|
-
"landmark-roles": true,
|
|
42
|
+
"required-element": false,
|
|
13
43
|
"required-h1": true,
|
|
14
44
|
"wai-aria": true
|
|
15
45
|
},
|
|
16
46
|
"nodeRules": [
|
|
17
47
|
{
|
|
18
|
-
"selector": "html",
|
|
48
|
+
"selector": ":where(html)",
|
|
19
49
|
"rules": {
|
|
20
50
|
"required-attr": ["lang"]
|
|
21
51
|
}
|
|
22
52
|
},
|
|
23
53
|
{
|
|
24
|
-
"selector": "
|
|
54
|
+
"selector": ":where(head)",
|
|
55
|
+
"rules": {
|
|
56
|
+
"required-element": ["meta[charset=\"UTF-8\" i]"]
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"selector": ":where(meta[property])",
|
|
61
|
+
"rules": {
|
|
62
|
+
"invalid-attr": {
|
|
63
|
+
"option": {
|
|
64
|
+
"attrs": {
|
|
65
|
+
"property": {
|
|
66
|
+
"pattern": "/^og:[a-z_]+/"
|
|
67
|
+
},
|
|
68
|
+
"content": {
|
|
69
|
+
"type": "NoEmptyAny"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"required-attr": false
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"selector": ":where(meta[itemprop])",
|
|
79
|
+
"rules": {
|
|
80
|
+
"invalid-attr": {
|
|
81
|
+
"option": {
|
|
82
|
+
"attrs": {
|
|
83
|
+
"content": {
|
|
84
|
+
"type": "NoEmptyAny"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"selector": ":where(script[src])",
|
|
25
93
|
"rules": {
|
|
26
94
|
"required-attr": ["defer"]
|
|
27
95
|
}
|
|
28
96
|
},
|
|
29
97
|
{
|
|
30
|
-
"selector": "
|
|
98
|
+
"selector": "h1, h2, h3, h4, h5, h6",
|
|
99
|
+
"rules": {
|
|
100
|
+
"disallowed-element": {
|
|
101
|
+
"value": ["small"],
|
|
102
|
+
"reason": "The small element must not be used for subheadings. https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-small-element"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"selector": ":where(img)",
|
|
31
108
|
"rules": {
|
|
32
|
-
"required-attr": [
|
|
109
|
+
"required-attr": [
|
|
110
|
+
"width",
|
|
111
|
+
"height",
|
|
112
|
+
"alt",
|
|
113
|
+
{
|
|
114
|
+
"name": "decoding",
|
|
115
|
+
"value": "async"
|
|
116
|
+
}
|
|
117
|
+
]
|
|
33
118
|
}
|
|
34
119
|
},
|
|
35
120
|
{
|
|
36
|
-
"selector": "iframe",
|
|
121
|
+
"selector": ":where(iframe)",
|
|
37
122
|
"rules": {
|
|
38
|
-
"required-attr": [
|
|
123
|
+
"required-attr": [
|
|
124
|
+
"title",
|
|
125
|
+
{
|
|
126
|
+
"name": "loading",
|
|
127
|
+
"value": "lazy"
|
|
128
|
+
}
|
|
129
|
+
]
|
|
39
130
|
}
|
|
40
131
|
},
|
|
41
132
|
{
|
|
42
|
-
"selector": "a[target=_blank], area[target=_blank]",
|
|
133
|
+
"selector": ":where(a[target=_blank], area[target=_blank])",
|
|
43
134
|
"rules": {
|
|
44
|
-
"required-attr":
|
|
135
|
+
"required-attr": {
|
|
136
|
+
"value": [
|
|
137
|
+
{
|
|
138
|
+
"name": "rel",
|
|
139
|
+
"value": "/(?<![^\\s]+)noreferrer(?![^\\s]+)/"
|
|
140
|
+
}
|
|
141
|
+
],
|
|
142
|
+
"reason": "The \"rel\" attribute should be required with \"noreferrer\" if the \"a\" element has the \"target=_black\""
|
|
143
|
+
}
|
|
45
144
|
}
|
|
46
145
|
},
|
|
47
146
|
{
|
|
48
|
-
"selector": "abbr",
|
|
147
|
+
"selector": ":where(abbr)",
|
|
49
148
|
"rules": {
|
|
50
149
|
"required-attr": ["title"]
|
|
51
150
|
}
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"selector": ":where(video, audio)",
|
|
154
|
+
"rules": {
|
|
155
|
+
"required-element": ["track"]
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"selector": ":where(video[autoplay])",
|
|
160
|
+
"rules": {
|
|
161
|
+
"required-attr": ["muted"]
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"selector": ":where(th, td)",
|
|
166
|
+
"rules": {
|
|
167
|
+
"invalid-attr": {
|
|
168
|
+
"option": {
|
|
169
|
+
"attrs": {
|
|
170
|
+
"span": {
|
|
171
|
+
"disallowed": false
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"selector": ":where(body :not(button))",
|
|
180
|
+
"rules": {
|
|
181
|
+
"invalid-attr": {
|
|
182
|
+
"option": {
|
|
183
|
+
"attrs": {
|
|
184
|
+
"onclick": {
|
|
185
|
+
"disallowed": false
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
52
191
|
}
|
|
53
192
|
]
|
|
54
193
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/ml-core",
|
|
3
|
-
"version": "2.0.0-
|
|
3
|
+
"version": "2.0.0-rc.5",
|
|
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,17 @@
|
|
|
17
17
|
"clean": "tsc --build --clean"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@markuplint/i18n": "
|
|
21
|
-
"@markuplint/ml-ast": "
|
|
22
|
-
"@markuplint/ml-config": "
|
|
23
|
-
"@markuplint/ml-spec": "
|
|
20
|
+
"@markuplint/i18n": "2.0.0-rc.4",
|
|
21
|
+
"@markuplint/ml-ast": "2.0.0-rc.5",
|
|
22
|
+
"@markuplint/ml-config": "2.0.0-rc.5",
|
|
23
|
+
"@markuplint/ml-spec": "2.0.0-rc.5",
|
|
24
24
|
"debug": "^4.3.2",
|
|
25
25
|
"postcss-selector-parser": "^6.0.6",
|
|
26
26
|
"tslib": "^2.3.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@markuplint/html-parser": "
|
|
29
|
+
"@markuplint/html-parser": "2.0.0-rc.5",
|
|
30
30
|
"@types/debug": "^4.1.7"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "6faa4e54f16d3700d23953330abea89ccb9d6150"
|
|
33
33
|
}
|