@markuplint/ml-core 2.3.0 → 3.0.0-alpha.0
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/configs.d.ts +1 -1
- package/lib/configs.js +29 -9
- package/lib/index.d.ts +8 -8
- package/lib/index.js +18 -10
- package/lib/ml-core.d.ts +3 -3
- package/lib/ml-core.js +41 -42
- package/lib/ml-dom/document.d.ts +79 -70
- package/lib/ml-dom/helper/accname.d.ts +2 -2
- package/lib/ml-dom/helper/accname.js +2 -3
- package/lib/ml-dom/helper/create-node.d.ts +3 -4
- package/lib/ml-dom/helper/create-node.js +11 -15
- package/lib/ml-dom/helper/debug.d.ts +2 -2
- package/lib/ml-dom/helper/debug.js +35 -21
- package/lib/ml-dom/helper/getIndent.d.ts +5 -5
- package/lib/ml-dom/helper/getIndent.js +14 -14
- package/lib/ml-dom/helper/mapped-nodes.d.ts +51 -3
- package/lib/ml-dom/helper/match-selector.d.ts +10 -6
- package/lib/ml-dom/helper/node-store.d.ts +6 -3
- package/lib/ml-dom/helper/selector.d.ts +4 -4
- package/lib/ml-dom/helper/walkers.d.ts +5 -4
- package/lib/ml-dom/helper/walkers.js +39 -3
- package/lib/ml-dom/index.d.ts +8 -3
- package/lib/ml-dom/index.js +3 -15
- package/lib/ml-dom/manipulations/child-node-methods.d.ts +33 -0
- package/lib/ml-dom/manipulations/child-node-methods.js +73 -0
- package/lib/ml-dom/manipulations/get-children.d.ts +4 -0
- package/lib/ml-dom/manipulations/get-children.js +10 -0
- package/lib/ml-dom/node/attr.d.ts +98 -0
- package/lib/ml-dom/node/attr.js +157 -0
- package/lib/ml-dom/node/block.d.ts +38 -0
- package/lib/ml-dom/node/block.js +53 -0
- package/lib/ml-dom/node/character-data.d.ts +57 -0
- package/lib/ml-dom/node/character-data.js +87 -0
- package/lib/ml-dom/node/child-node.d.ts +9 -0
- package/lib/ml-dom/node/child-node.js +10 -0
- package/lib/ml-dom/node/comment.d.ts +17 -0
- package/lib/ml-dom/node/comment.js +24 -0
- package/lib/ml-dom/node/document-fragment.d.ts +24 -0
- package/lib/ml-dom/node/document-fragment.js +33 -0
- package/lib/ml-dom/node/document-type.d.ts +38 -0
- package/lib/ml-dom/node/document-type.js +52 -0
- package/lib/ml-dom/node/document.d.ts +1554 -0
- package/lib/ml-dom/node/document.js +2117 -0
- package/lib/ml-dom/node/dom-token-list.d.ts +33 -0
- package/lib/ml-dom/node/dom-token-list.js +137 -0
- package/lib/ml-dom/node/element.d.ts +1825 -0
- package/lib/ml-dom/node/element.js +2460 -0
- package/lib/ml-dom/node/named-node-map.d.ts +42 -0
- package/lib/ml-dom/node/named-node-map.js +64 -0
- package/lib/ml-dom/node/node-list.d.ts +6 -0
- package/lib/ml-dom/node/node-list.js +39 -0
- package/lib/ml-dom/node/node-store.d.ts +14 -0
- package/lib/ml-dom/node/node-store.js +32 -0
- package/lib/ml-dom/node/node.d.ts +475 -0
- package/lib/ml-dom/node/node.js +666 -0
- package/lib/ml-dom/node/parent-node.d.ts +66 -0
- package/lib/ml-dom/node/parent-node.js +131 -0
- package/lib/ml-dom/node/rule-mapper.d.ts +17 -0
- package/lib/ml-dom/node/rule-mapper.js +49 -0
- package/lib/ml-dom/node/text.d.ts +51 -0
- package/lib/ml-dom/node/text.js +76 -0
- package/lib/ml-dom/node/types.d.ts +25 -0
- package/lib/ml-dom/node/types.js +2 -0
- package/lib/ml-dom/node/unexpected-call-error.d.ts +2 -0
- package/lib/ml-dom/node/unexpected-call-error.js +5 -0
- package/lib/ml-dom/rule-mapper.d.ts +7 -7
- package/lib/ml-dom/token/token.d.ts +47 -0
- package/lib/ml-dom/token/token.js +89 -0
- package/lib/ml-dom/tokens/abstract-element.d.ts +47 -42
- package/lib/ml-dom/tokens/attribute.d.ts +38 -38
- package/lib/ml-dom/tokens/comment.d.ts +7 -4
- package/lib/ml-dom/tokens/doctype.d.ts +12 -9
- package/lib/ml-dom/tokens/element-close-tag.d.ts +20 -17
- package/lib/ml-dom/tokens/element.d.ts +18 -15
- package/lib/ml-dom/tokens/node.d.ts +38 -31
- package/lib/ml-dom/tokens/omitted-element.d.ts +7 -4
- package/lib/ml-dom/tokens/preprocessor-specific-attribute.d.ts +20 -20
- package/lib/ml-dom/tokens/preprocessor-specific-block.d.ts +8 -5
- package/lib/ml-dom/tokens/text.d.ts +13 -9
- package/lib/ml-dom/tokens/token.d.ts +13 -13
- package/lib/ml-dom/types.d.ts +35 -13
- package/lib/ml-rule/ml-rule-context.d.ts +13 -10
- package/lib/ml-rule/ml-rule-context.js +12 -6
- package/lib/ml-rule/ml-rule.d.ts +8 -8
- package/lib/ml-rule/ml-rule.js +62 -62
- package/lib/ml-rule/types.d.ts +11 -1
- package/lib/ruleset/index.d.ts +2 -2
- package/lib/selector/is-pure-html-element.d.ts +1 -0
- package/lib/selector/is-pure-html-element.js +7 -0
- package/lib/selector/match-selector.d.ts +14 -0
- package/lib/selector/match-selector.js +230 -0
- package/lib/selector/selector.d.ts +9 -0
- package/lib/selector/selector.js +561 -0
- package/lib/test/index.d.ts +2 -1
- package/lib/test/index.js +7 -2
- package/package.json +10 -9
- package/tsconfig.tsbuildinfo +1 -1
- package/markuplint-recommended.json +0 -196
|
@@ -5,10 +5,9 @@ exports.MLRuleContext = void 0;
|
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
6
|
const i18n_1 = require("@markuplint/i18n");
|
|
7
7
|
class MLRuleContext {
|
|
8
|
-
constructor(document, locale
|
|
8
|
+
constructor(document, locale) {
|
|
9
9
|
_MLRuleContext_reports.set(this, []);
|
|
10
10
|
this.document = document;
|
|
11
|
-
this.globalRule = rule;
|
|
12
11
|
this.translate = (0, i18n_1.translator)(locale);
|
|
13
12
|
this.locale = locale.locale;
|
|
14
13
|
}
|
|
@@ -18,19 +17,26 @@ class MLRuleContext {
|
|
|
18
17
|
message: finish(report.message),
|
|
19
18
|
}));
|
|
20
19
|
}
|
|
21
|
-
report(report) {
|
|
22
|
-
tslib_1.__classPrivateFieldGet(this, _MLRuleContext_reports, "f").push(report);
|
|
23
|
-
}
|
|
24
20
|
provide() {
|
|
25
21
|
return {
|
|
26
22
|
document: this.document,
|
|
27
23
|
translate: this.translate,
|
|
28
24
|
t: this.translate,
|
|
29
|
-
globalRule: this.globalRule,
|
|
30
25
|
reports: this.reports,
|
|
31
26
|
report: this.report.bind(this),
|
|
32
27
|
};
|
|
33
28
|
}
|
|
29
|
+
report(report) {
|
|
30
|
+
if (typeof report === 'function') {
|
|
31
|
+
const r = report(this.translate);
|
|
32
|
+
if (r) {
|
|
33
|
+
tslib_1.__classPrivateFieldGet(this, _MLRuleContext_reports, "f").push(r);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
tslib_1.__classPrivateFieldGet(this, _MLRuleContext_reports, "f").push(report);
|
|
39
|
+
}
|
|
34
40
|
}
|
|
35
41
|
exports.MLRuleContext = MLRuleContext;
|
|
36
42
|
_MLRuleContext_reports = new WeakMap();
|
package/lib/ml-rule/ml-rule.d.ts
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import type { Ruleset } from '..';
|
|
2
|
-
import type
|
|
2
|
+
import type { MLDocument } from '../ml-dom/node/document';
|
|
3
3
|
import type { RuleSeed } from './types';
|
|
4
4
|
import type { LocaleSet } from '@markuplint/i18n';
|
|
5
|
-
import type { GlobalRuleInfo, RuleConfig, RuleConfigValue, RuleInfo,
|
|
5
|
+
import type { GlobalRuleInfo, RuleConfig, RuleConfigValue, RuleInfo, Severity, Violation } from '@markuplint/ml-config';
|
|
6
6
|
export declare class MLRule<T extends RuleConfigValue, O = null> {
|
|
7
7
|
#private;
|
|
8
|
-
readonly
|
|
8
|
+
readonly defaultOptions: O;
|
|
9
9
|
readonly defaultServerity: Severity;
|
|
10
10
|
readonly defaultValue: T;
|
|
11
|
-
readonly
|
|
11
|
+
readonly name: string;
|
|
12
12
|
/**
|
|
13
13
|
* The following getter is unused internally,
|
|
14
14
|
* only for extending from 3rd party library
|
|
15
15
|
*/
|
|
16
|
-
protected get
|
|
16
|
+
protected get f(): RuleSeed<T, O>['fix'];
|
|
17
17
|
/**
|
|
18
18
|
* The following getter is unused internally,
|
|
19
19
|
* only for extending from 3rd party library
|
|
20
20
|
*/
|
|
21
|
-
protected get
|
|
21
|
+
protected get v(): RuleSeed<T, O>['verify'];
|
|
22
22
|
constructor(o: RuleSeed<T, O> & {
|
|
23
23
|
name: string;
|
|
24
24
|
});
|
|
25
|
-
verify(document: Document<T, O>, locale: LocaleSet, globalRule: RuleInfo<T, O>, fix: boolean): Promise<Violation[]>;
|
|
26
25
|
getRuleInfo(ruleSet: Ruleset, ruleName: string): GlobalRuleInfo<T, O>;
|
|
27
|
-
_optimize(rules: Rules | undefined, ruleName: string): RuleInfo<T, O>;
|
|
28
26
|
optimizeOption(configSettings: T | RuleConfig<T, O> | undefined): RuleInfo<T, O>;
|
|
27
|
+
verify(document: MLDocument<T, O>, locale: LocaleSet, fix: boolean): Promise<Violation[]>;
|
|
28
|
+
private _optimize;
|
|
29
29
|
}
|
|
30
30
|
export declare type AnyMLRule = MLRule<RuleConfigValue, unknown>;
|
package/lib/ml-rule/ml-rule.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
2
|
+
var _MLRule_f, _MLRule_v;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.MLRule = void 0;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
@@ -7,8 +7,8 @@ const ml_rule_context_1 = require("./ml-rule-context");
|
|
|
7
7
|
class MLRule {
|
|
8
8
|
constructor(o) {
|
|
9
9
|
var _a, _b;
|
|
10
|
-
_MLRule_v.set(this, void 0);
|
|
11
10
|
_MLRule_f.set(this, void 0);
|
|
11
|
+
_MLRule_v.set(this, void 0);
|
|
12
12
|
this.name = o.name;
|
|
13
13
|
this.defaultServerity = o.defaultServerity || 'error';
|
|
14
14
|
this.defaultValue = (_a = o.defaultValue) !== null && _a !== void 0 ? _a : true;
|
|
@@ -20,65 +20,15 @@ class MLRule {
|
|
|
20
20
|
* The following getter is unused internally,
|
|
21
21
|
* only for extending from 3rd party library
|
|
22
22
|
*/
|
|
23
|
-
get
|
|
24
|
-
return tslib_1.__classPrivateFieldGet(this,
|
|
23
|
+
get f() {
|
|
24
|
+
return tslib_1.__classPrivateFieldGet(this, _MLRule_f, "f");
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* The following getter is unused internally,
|
|
28
28
|
* only for extending from 3rd party library
|
|
29
29
|
*/
|
|
30
|
-
get
|
|
31
|
-
return tslib_1.__classPrivateFieldGet(this,
|
|
32
|
-
}
|
|
33
|
-
async verify(document, locale, globalRule, fix) {
|
|
34
|
-
if (!tslib_1.__classPrivateFieldGet(this, _MLRule_v, "f")) {
|
|
35
|
-
return [];
|
|
36
|
-
}
|
|
37
|
-
document.setRule(this);
|
|
38
|
-
const context = new ml_rule_context_1.MLRuleContext(document, locale, globalRule);
|
|
39
|
-
const providableContext = context.provide();
|
|
40
|
-
await tslib_1.__classPrivateFieldGet(this, _MLRule_v, "f").call(this, providableContext);
|
|
41
|
-
if (tslib_1.__classPrivateFieldGet(this, _MLRule_f, "f") && fix) {
|
|
42
|
-
await tslib_1.__classPrivateFieldGet(this, _MLRule_f, "f").call(this, providableContext);
|
|
43
|
-
}
|
|
44
|
-
const violation = context.reports.map(report => {
|
|
45
|
-
if ('scope' in report) {
|
|
46
|
-
let line = report.scope.startLine;
|
|
47
|
-
let col = report.scope.startCol;
|
|
48
|
-
let raw = report.scope.raw;
|
|
49
|
-
if ('line' in report) {
|
|
50
|
-
line = report.line;
|
|
51
|
-
col = report.col;
|
|
52
|
-
raw = report.raw;
|
|
53
|
-
}
|
|
54
|
-
const violation = {
|
|
55
|
-
severity: report.scope.rule.severity,
|
|
56
|
-
message: report.message,
|
|
57
|
-
line,
|
|
58
|
-
col,
|
|
59
|
-
raw,
|
|
60
|
-
ruleId: this.name,
|
|
61
|
-
};
|
|
62
|
-
if (report.scope.rule.reason || globalRule.reason) {
|
|
63
|
-
violation.reason = report.scope.rule.reason || globalRule.reason;
|
|
64
|
-
}
|
|
65
|
-
return violation;
|
|
66
|
-
}
|
|
67
|
-
const violation = {
|
|
68
|
-
severity: globalRule.severity,
|
|
69
|
-
message: report.message,
|
|
70
|
-
line: report.line,
|
|
71
|
-
col: report.col,
|
|
72
|
-
raw: report.raw,
|
|
73
|
-
ruleId: this.name,
|
|
74
|
-
};
|
|
75
|
-
if (globalRule.reason) {
|
|
76
|
-
violation.reason = globalRule.reason;
|
|
77
|
-
}
|
|
78
|
-
return violation;
|
|
79
|
-
});
|
|
80
|
-
document.setRule(null);
|
|
81
|
-
return violation;
|
|
30
|
+
get v() {
|
|
31
|
+
return tslib_1.__classPrivateFieldGet(this, _MLRule_v, "f");
|
|
82
32
|
}
|
|
83
33
|
getRuleInfo(ruleSet, ruleName) {
|
|
84
34
|
const info = this._optimize(ruleSet.rules, ruleName);
|
|
@@ -88,11 +38,6 @@ class MLRule {
|
|
|
88
38
|
childNodeRules: ruleSet.childNodeRules.map(r => this._optimize(r.rules, ruleName)).filter(r => !r.disabled),
|
|
89
39
|
};
|
|
90
40
|
}
|
|
91
|
-
_optimize(rules, ruleName) {
|
|
92
|
-
const rule = (rules && rules[ruleName]) || false;
|
|
93
|
-
const info = this.optimizeOption(rule);
|
|
94
|
-
return info;
|
|
95
|
-
}
|
|
96
41
|
optimizeOption(configSettings) {
|
|
97
42
|
if (configSettings === undefined || typeof configSettings === 'boolean') {
|
|
98
43
|
return {
|
|
@@ -132,6 +77,61 @@ class MLRule {
|
|
|
132
77
|
reason: undefined,
|
|
133
78
|
};
|
|
134
79
|
}
|
|
80
|
+
async verify(document, locale, fix) {
|
|
81
|
+
if (!tslib_1.__classPrivateFieldGet(this, _MLRule_v, "f")) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
document.setRule(this);
|
|
85
|
+
const context = new ml_rule_context_1.MLRuleContext(document, locale);
|
|
86
|
+
const providableContext = context.provide();
|
|
87
|
+
await tslib_1.__classPrivateFieldGet(this, _MLRule_v, "f").call(this, providableContext);
|
|
88
|
+
if (tslib_1.__classPrivateFieldGet(this, _MLRule_f, "f") && fix) {
|
|
89
|
+
await tslib_1.__classPrivateFieldGet(this, _MLRule_f, "f").call(this, providableContext);
|
|
90
|
+
}
|
|
91
|
+
const violation = context.reports.map(report => {
|
|
92
|
+
if ('scope' in report) {
|
|
93
|
+
let line = report.scope.startLine;
|
|
94
|
+
let col = report.scope.startCol;
|
|
95
|
+
let raw = report.scope.raw;
|
|
96
|
+
if ('line' in report && report.line != null) {
|
|
97
|
+
line = report.line;
|
|
98
|
+
col = report.col;
|
|
99
|
+
raw = report.raw;
|
|
100
|
+
}
|
|
101
|
+
const violation = {
|
|
102
|
+
severity: report.scope.rule.severity,
|
|
103
|
+
message: report.message,
|
|
104
|
+
line,
|
|
105
|
+
col,
|
|
106
|
+
raw,
|
|
107
|
+
ruleId: this.name,
|
|
108
|
+
};
|
|
109
|
+
if (report.scope.rule.reason || document.rule.reason) {
|
|
110
|
+
violation.reason = report.scope.rule.reason || document.rule.reason;
|
|
111
|
+
}
|
|
112
|
+
return violation;
|
|
113
|
+
}
|
|
114
|
+
const violation = {
|
|
115
|
+
severity: document.rule.severity,
|
|
116
|
+
message: report.message,
|
|
117
|
+
line: report.line,
|
|
118
|
+
col: report.col,
|
|
119
|
+
raw: report.raw,
|
|
120
|
+
ruleId: this.name,
|
|
121
|
+
};
|
|
122
|
+
if (document.rule.reason) {
|
|
123
|
+
violation.reason = document.rule.reason;
|
|
124
|
+
}
|
|
125
|
+
return violation;
|
|
126
|
+
});
|
|
127
|
+
document.setRule(null);
|
|
128
|
+
return violation;
|
|
129
|
+
}
|
|
130
|
+
_optimize(rules, ruleName) {
|
|
131
|
+
const rule = (rules && rules[ruleName]) || false;
|
|
132
|
+
const info = this.optimizeOption(rule);
|
|
133
|
+
return info;
|
|
134
|
+
}
|
|
135
135
|
}
|
|
136
136
|
exports.MLRule = MLRule;
|
|
137
|
-
|
|
137
|
+
_MLRule_f = new WeakMap(), _MLRule_v = new WeakMap();
|
package/lib/ml-rule/types.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { Attr, Element } from '../ml-dom';
|
|
1
2
|
import type { MLRuleContext } from './ml-rule-context';
|
|
2
|
-
import type {
|
|
3
|
+
import type { Translator } from '@markuplint/i18n';
|
|
4
|
+
import type { Report, RuleConfigValue, Severity } from '@markuplint/ml-config';
|
|
3
5
|
export declare type RuleSeed<T extends RuleConfigValue = boolean, O = null> = {
|
|
4
6
|
defaultServerity?: Severity;
|
|
5
7
|
defaultValue?: T;
|
|
@@ -7,4 +9,12 @@ export declare type RuleSeed<T extends RuleConfigValue = boolean, O = null> = {
|
|
|
7
9
|
verify(context: ReturnType<MLRuleContext<T, O>['provide']>): void | Promise<void>;
|
|
8
10
|
fix?(context: ReturnType<MLRuleContext<T, O>['provide']>): void | Promise<void>;
|
|
9
11
|
};
|
|
12
|
+
export declare type Checker<T extends RuleConfigValue, O = null, P extends Record<string, unknown> = {}> = (params: P) => CheckerReport<T, O>;
|
|
13
|
+
export declare type ElementChecker<T extends RuleConfigValue, O = null, P extends Record<string, unknown> = {}> = (params: P & {
|
|
14
|
+
el: Element<T, O>;
|
|
15
|
+
}) => CheckerReport<T, O>;
|
|
16
|
+
export declare type AttrChecker<T extends RuleConfigValue, O = null, P extends Record<string, unknown> = {}> = (params: P & {
|
|
17
|
+
attr: Attr<T, O>;
|
|
18
|
+
}) => CheckerReport<T, O>;
|
|
19
|
+
export declare type CheckerReport<T extends RuleConfigValue, O = null> = (t: Translator) => Report<T, O> | undefined | null;
|
|
10
20
|
export declare type AnyRuleSeed = RuleSeed<any, any>;
|
package/lib/ruleset/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ChildNodeRule, Config, NodeRule, Rules } from '@markuplint/ml-config';
|
|
2
2
|
export default class Ruleset {
|
|
3
|
-
readonly rules: Readonly<Rules>;
|
|
4
|
-
readonly nodeRules: ReadonlyArray<NodeRule>;
|
|
5
3
|
readonly childNodeRules: ReadonlyArray<ChildNodeRule>;
|
|
4
|
+
readonly nodeRules: ReadonlyArray<NodeRule>;
|
|
5
|
+
readonly rules: Readonly<Rules>;
|
|
6
6
|
constructor(config: Config);
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isPureHTMLElement(el: Element): boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Specificity } from './selector';
|
|
2
|
+
import type { RegexSelector } from '@markuplint/ml-config';
|
|
3
|
+
export declare type SelectorMatches = SelectorMatched | SelectorUnmatched;
|
|
4
|
+
declare type SelectorMatched = {
|
|
5
|
+
matched: true;
|
|
6
|
+
selector: string;
|
|
7
|
+
specificity: Specificity;
|
|
8
|
+
data?: Record<string, string>;
|
|
9
|
+
};
|
|
10
|
+
declare type SelectorUnmatched = {
|
|
11
|
+
matched: false;
|
|
12
|
+
};
|
|
13
|
+
export declare function matchSelector(el: Element, selector: string | RegexSelector | undefined): SelectorMatches;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.matchSelector = void 0;
|
|
4
|
+
const ml_config_1 = require("@markuplint/ml-config");
|
|
5
|
+
const is_pure_html_element_1 = require("./is-pure-html-element");
|
|
6
|
+
const selector_1 = require("./selector");
|
|
7
|
+
function matchSelector(el, selector) {
|
|
8
|
+
if (!selector) {
|
|
9
|
+
return {
|
|
10
|
+
matched: false,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
if (typeof selector === 'string') {
|
|
14
|
+
const sel = (0, selector_1.createSelector)(selector);
|
|
15
|
+
const specificity = sel.match(el);
|
|
16
|
+
if (specificity) {
|
|
17
|
+
return {
|
|
18
|
+
matched: true,
|
|
19
|
+
selector,
|
|
20
|
+
specificity,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
matched: false,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return regexSelect(el, selector);
|
|
28
|
+
}
|
|
29
|
+
exports.matchSelector = matchSelector;
|
|
30
|
+
function regexSelect(el, selector) {
|
|
31
|
+
let edge = new SelectorTarget(selector);
|
|
32
|
+
let edgeSelector = selector.combination;
|
|
33
|
+
while (edgeSelector) {
|
|
34
|
+
const child = new SelectorTarget(edgeSelector);
|
|
35
|
+
child.from(edge, edgeSelector.combinator);
|
|
36
|
+
edge = child;
|
|
37
|
+
edgeSelector = edgeSelector.combination;
|
|
38
|
+
}
|
|
39
|
+
return edge.match(el);
|
|
40
|
+
}
|
|
41
|
+
class SelectorTarget {
|
|
42
|
+
constructor(selector) {
|
|
43
|
+
this._combinatedFrom = null;
|
|
44
|
+
this._selector = selector;
|
|
45
|
+
}
|
|
46
|
+
from(target, combinator) {
|
|
47
|
+
this._combinatedFrom = { target, combinator };
|
|
48
|
+
}
|
|
49
|
+
match(el) {
|
|
50
|
+
const unitCheck = this._matchWithoutCombinateChecking(el);
|
|
51
|
+
if (!unitCheck.matched) {
|
|
52
|
+
return unitCheck;
|
|
53
|
+
}
|
|
54
|
+
if (!this._combinatedFrom) {
|
|
55
|
+
return unitCheck;
|
|
56
|
+
}
|
|
57
|
+
const { target, combinator } = this._combinatedFrom;
|
|
58
|
+
switch (combinator) {
|
|
59
|
+
// Descendant combinator
|
|
60
|
+
case ' ': {
|
|
61
|
+
let ancestor = el.parentElement;
|
|
62
|
+
while (ancestor) {
|
|
63
|
+
const matches = target.match(ancestor);
|
|
64
|
+
if (matches.matched) {
|
|
65
|
+
return mergeMatches(matches, unitCheck, ' ');
|
|
66
|
+
}
|
|
67
|
+
ancestor = ancestor.parentElement;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
matched: false,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// Child combinator
|
|
74
|
+
case '>': {
|
|
75
|
+
const parentNode = el.parentElement;
|
|
76
|
+
if (!parentNode) {
|
|
77
|
+
return { matched: false };
|
|
78
|
+
}
|
|
79
|
+
const matches = target.match(parentNode);
|
|
80
|
+
if (matches.matched) {
|
|
81
|
+
return mergeMatches(matches, unitCheck, ' > ');
|
|
82
|
+
}
|
|
83
|
+
return { matched: false };
|
|
84
|
+
}
|
|
85
|
+
// Next-sibling combinator
|
|
86
|
+
case '+': {
|
|
87
|
+
if (!el.previousElementSibling) {
|
|
88
|
+
return { matched: false };
|
|
89
|
+
}
|
|
90
|
+
const matches = target.match(el.previousElementSibling);
|
|
91
|
+
if (matches.matched) {
|
|
92
|
+
return mergeMatches(matches, unitCheck, ' + ');
|
|
93
|
+
}
|
|
94
|
+
return { matched: false };
|
|
95
|
+
}
|
|
96
|
+
// Subsequent-sibling combinator
|
|
97
|
+
case '~': {
|
|
98
|
+
let prev = el.previousElementSibling;
|
|
99
|
+
while (prev) {
|
|
100
|
+
const matches = target.match(prev);
|
|
101
|
+
if (matches.matched) {
|
|
102
|
+
return mergeMatches(matches, unitCheck, ' ~ ');
|
|
103
|
+
}
|
|
104
|
+
prev = prev.previousElementSibling;
|
|
105
|
+
}
|
|
106
|
+
return { matched: false };
|
|
107
|
+
}
|
|
108
|
+
// Prev-sibling combinator
|
|
109
|
+
case ':has(+)': {
|
|
110
|
+
if (!el.nextElementSibling) {
|
|
111
|
+
return { matched: false };
|
|
112
|
+
}
|
|
113
|
+
const matches = target.match(el.nextElementSibling);
|
|
114
|
+
if (matches.matched) {
|
|
115
|
+
return mergeMatches(matches, unitCheck, ':has(+ ', true);
|
|
116
|
+
}
|
|
117
|
+
return { matched: false };
|
|
118
|
+
}
|
|
119
|
+
// Subsequent-sibling (in front) combinator
|
|
120
|
+
case ':has(~)': {
|
|
121
|
+
let next = el.nextElementSibling;
|
|
122
|
+
while (next) {
|
|
123
|
+
const matches = target.match(next);
|
|
124
|
+
if (matches.matched) {
|
|
125
|
+
return mergeMatches(matches, unitCheck, ':has(~ ', true);
|
|
126
|
+
}
|
|
127
|
+
next = next.nextElementSibling;
|
|
128
|
+
}
|
|
129
|
+
return { matched: false };
|
|
130
|
+
}
|
|
131
|
+
default: {
|
|
132
|
+
throw new Error(`Unsupported ${this._combinatedFrom.combinator} combinator in selector`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
_matchWithoutCombinateChecking(el) {
|
|
137
|
+
return uncombinatedRegexSelect(el, this._selector);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function uncombinatedRegexSelect(el, selector) {
|
|
141
|
+
let matched = true;
|
|
142
|
+
let data = {};
|
|
143
|
+
let tagSelector = '';
|
|
144
|
+
const specificity = [0, 0, 0];
|
|
145
|
+
const specifiedAttr = new Map();
|
|
146
|
+
if (selector.nodeName) {
|
|
147
|
+
const matchedNodeName = (0, ml_config_1.regexSelectorMatches)(selector.nodeName, el.localName, (0, is_pure_html_element_1.isPureHTMLElement)(el));
|
|
148
|
+
if (matchedNodeName) {
|
|
149
|
+
delete matchedNodeName.$0;
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
matched = false;
|
|
153
|
+
}
|
|
154
|
+
data = {
|
|
155
|
+
...data,
|
|
156
|
+
...matchedNodeName,
|
|
157
|
+
};
|
|
158
|
+
tagSelector = el.localName;
|
|
159
|
+
specificity[2] = 1;
|
|
160
|
+
}
|
|
161
|
+
if (selector.attrName) {
|
|
162
|
+
const selectorAttrName = selector.attrName;
|
|
163
|
+
const matchedAttrNameList = Array.from(el.attributes).map(attr => {
|
|
164
|
+
const attrName = attr.name;
|
|
165
|
+
const matchedAttrName = (0, ml_config_1.regexSelectorMatches)(selectorAttrName, attrName, (0, is_pure_html_element_1.isPureHTMLElement)(el));
|
|
166
|
+
if (matchedAttrName) {
|
|
167
|
+
delete matchedAttrName.$0;
|
|
168
|
+
data = {
|
|
169
|
+
...data,
|
|
170
|
+
...matchedAttrName,
|
|
171
|
+
};
|
|
172
|
+
specifiedAttr.set(attrName, '');
|
|
173
|
+
}
|
|
174
|
+
return matchedAttrName;
|
|
175
|
+
});
|
|
176
|
+
if (!matchedAttrNameList.some(_ => !!_)) {
|
|
177
|
+
matched = false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (selector.attrValue) {
|
|
181
|
+
const selectorAttrValue = selector.attrValue;
|
|
182
|
+
const matchedAttrValueList = Array.from(el.attributes).map(attr => {
|
|
183
|
+
const attrName = attr.name;
|
|
184
|
+
const attrValue = attr.value;
|
|
185
|
+
const matchedAttrValue = (0, ml_config_1.regexSelectorMatches)(selectorAttrValue, attrValue, (0, is_pure_html_element_1.isPureHTMLElement)(el));
|
|
186
|
+
if (matchedAttrValue) {
|
|
187
|
+
delete matchedAttrValue.$0;
|
|
188
|
+
data = {
|
|
189
|
+
...data,
|
|
190
|
+
...matchedAttrValue,
|
|
191
|
+
};
|
|
192
|
+
specifiedAttr.set(attrName, attrValue);
|
|
193
|
+
}
|
|
194
|
+
return matchedAttrValue;
|
|
195
|
+
});
|
|
196
|
+
if (!matchedAttrValueList.some(_ => !!_)) {
|
|
197
|
+
matched = false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const attrSelector = Array.from(specifiedAttr.entries())
|
|
201
|
+
.map(([name, value]) => {
|
|
202
|
+
return `[${name}${value ? `="${value}"` : ''}]`;
|
|
203
|
+
})
|
|
204
|
+
.join('');
|
|
205
|
+
specificity[1] += specifiedAttr.size;
|
|
206
|
+
if (matched) {
|
|
207
|
+
return {
|
|
208
|
+
matched,
|
|
209
|
+
selector: `${tagSelector}${attrSelector}`,
|
|
210
|
+
specificity,
|
|
211
|
+
data,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return { matched };
|
|
215
|
+
}
|
|
216
|
+
function mergeMatches(a, b, sep, close = false) {
|
|
217
|
+
return {
|
|
218
|
+
matched: true,
|
|
219
|
+
selector: `${a.selector}${sep}${b.selector}${close ? ')' : ''}`,
|
|
220
|
+
specificity: [
|
|
221
|
+
a.specificity[0] + b.specificity[0],
|
|
222
|
+
a.specificity[1] + b.specificity[1],
|
|
223
|
+
a.specificity[2] + b.specificity[2],
|
|
224
|
+
],
|
|
225
|
+
data: {
|
|
226
|
+
...a.data,
|
|
227
|
+
...b.data,
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare type Specificity = [number, number, number];
|
|
2
|
+
export declare function createSelector(selector: string): Selector;
|
|
3
|
+
export declare function compareSpecificity(a: Specificity, b: Specificity): 1 | 0 | -1;
|
|
4
|
+
declare class Selector {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(selector: string);
|
|
7
|
+
match(el: Element, caller?: ParentNode | null): Specificity | false;
|
|
8
|
+
}
|
|
9
|
+
export {};
|