@markuplint/ml-core 4.13.2 → 5.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/ARCHITECTURE.ja.md +524 -0
- package/ARCHITECTURE.md +524 -0
- package/CHANGELOG.md +52 -2
- package/README.md +5 -0
- package/SKILL.md +61 -0
- package/docs/linting-pipeline.ja.md +307 -0
- package/docs/linting-pipeline.md +307 -0
- package/docs/maintenance.ja.md +210 -0
- package/docs/maintenance.md +210 -0
- package/docs/ml-dom/attr.ja.md +103 -0
- package/docs/ml-dom/attr.md +103 -0
- package/docs/ml-dom/block.ja.md +272 -0
- package/docs/ml-dom/block.md +272 -0
- package/docs/ml-dom/document.ja.md +141 -0
- package/docs/ml-dom/document.md +141 -0
- package/docs/ml-dom/element.ja.md +176 -0
- package/docs/ml-dom/element.md +176 -0
- package/docs/ml-dom/helpers.ja.md +203 -0
- package/docs/ml-dom/helpers.md +203 -0
- package/docs/ml-dom/node.ja.md +199 -0
- package/docs/ml-dom/node.md +199 -0
- package/docs/ml-dom/others.ja.md +120 -0
- package/docs/ml-dom/others.md +120 -0
- package/docs/ml-dom/overview.ja.md +102 -0
- package/docs/ml-dom/overview.md +102 -0
- package/docs/ml-dom/pretender.ja.md +269 -0
- package/docs/ml-dom/pretender.md +269 -0
- package/docs/ml-dom/rule-mapping.ja.md +371 -0
- package/docs/ml-dom/rule-mapping.md +371 -0
- package/docs/ml-dom.ja.md +18 -0
- package/docs/ml-dom.md +18 -0
- package/docs/rule-system.ja.md +287 -0
- package/docs/rule-system.md +287 -0
- package/lib/convert-ruleset.d.ts +7 -0
- package/lib/convert-ruleset.js +7 -0
- package/lib/debug.d.ts +4 -0
- package/lib/debug.js +4 -0
- package/lib/index.d.ts +4 -3
- package/lib/index.js +1 -1
- package/lib/ml-core.d.ts +37 -1
- package/lib/ml-core.js +171 -82
- package/lib/ml-dom/helper/accname.d.ts +8 -0
- package/lib/ml-dom/helper/accname.js +71 -55
- package/lib/ml-dom/helper/create-node.js +1 -0
- package/lib/ml-dom/helper/get-indent.d.ts +4 -1
- package/lib/ml-dom/helper/get-indent.js +21 -30
- package/lib/ml-dom/node/attr.d.ts +65 -4
- package/lib/ml-dom/node/attr.js +151 -53
- package/lib/ml-dom/node/block.d.ts +23 -2
- package/lib/ml-dom/node/block.js +24 -1
- package/lib/ml-dom/node/child-node.d.ts +9 -0
- package/lib/ml-dom/node/child-node.js +9 -0
- package/lib/ml-dom/node/comment.d.ts +7 -0
- package/lib/ml-dom/node/comment.js +7 -0
- package/lib/ml-dom/node/document-fragment.d.ts +8 -0
- package/lib/ml-dom/node/document-fragment.js +8 -0
- package/lib/ml-dom/node/document-type.d.ts +22 -0
- package/lib/ml-dom/node/document-type.js +25 -0
- package/lib/ml-dom/node/document.d.ts +88 -7
- package/lib/ml-dom/node/document.js +128 -32
- package/lib/ml-dom/node/dom-token-list.js +17 -30
- package/lib/ml-dom/node/element-close-tag.js +1 -0
- package/lib/ml-dom/node/element.d.ts +151 -5
- package/lib/ml-dom/node/element.js +242 -50
- package/lib/ml-dom/node/node-store.js +6 -15
- package/lib/ml-dom/node/node.d.ts +19 -1
- package/lib/ml-dom/node/node.js +175 -166
- package/lib/ml-dom/node/parent-node.js +14 -30
- package/lib/ml-dom/node/rule-mapper.js +7 -20
- package/lib/ml-dom/node/text.d.ts +19 -0
- package/lib/ml-dom/node/text.js +21 -0
- package/lib/ml-dom/node/types.d.ts +68 -0
- package/lib/ml-dom/token/token.d.ts +42 -0
- package/lib/ml-dom/token/token.js +59 -39
- package/lib/ml-rule/create-rule.d.ts +17 -1
- package/lib/ml-rule/ml-rule-context.js +7 -11
- package/lib/ml-rule/ml-rule.d.ts +66 -1
- package/lib/ml-rule/ml-rule.js +95 -25
- package/lib/ml-rule/types.d.ts +41 -0
- package/lib/plugin/plugin.d.ts +8 -0
- package/lib/plugin/plugin.js +8 -0
- package/lib/plugin/types.d.ts +21 -0
- package/lib/ruleset/index.d.ts +10 -0
- package/lib/ruleset/index.js +13 -0
- package/lib/test/index.d.ts +42 -1
- package/lib/test/index.js +39 -2
- package/lib/types.d.ts +10 -1
- package/lib/violation-collector.d.ts +33 -0
- package/lib/violation-collector.js +48 -28
- package/lib/virtual-rule.d.ts +72 -0
- package/lib/virtual-rule.js +233 -0
- package/package.json +16 -13
package/lib/ml-rule/ml-rule.js
CHANGED
|
@@ -1,45 +1,93 @@
|
|
|
1
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
-
};
|
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _MLRule_f, _MLRule_v;
|
|
13
1
|
import { deleteUndefProp } from '@markuplint/ml-config';
|
|
14
2
|
// @ts-ignore
|
|
15
3
|
import { isPlainObject } from 'is-plain-object';
|
|
16
4
|
import { MLRuleContext } from './ml-rule-context.js';
|
|
5
|
+
/**
|
|
6
|
+
* Represents a single markuplint rule that can verify documents and report violations.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The type of the rule's configuration value
|
|
9
|
+
* @template O - The type of the rule's options
|
|
10
|
+
*/
|
|
17
11
|
export class MLRule {
|
|
12
|
+
/**
|
|
13
|
+
* For virtual rules, the name of the base rule whose verify/fix logic is reused.
|
|
14
|
+
* When set, violations report this as `ruleId` for backwards compatibility.
|
|
15
|
+
*/
|
|
16
|
+
baseRuleId;
|
|
17
|
+
defaultOptions;
|
|
18
|
+
defaultSeverity;
|
|
19
|
+
defaultValue;
|
|
20
|
+
#f;
|
|
21
|
+
/**
|
|
22
|
+
* For multi-entry named nodeRules, the group name shared by all derived virtual rules.
|
|
23
|
+
* Allows `rules["groupName"]: false` to disable all rules in the group.
|
|
24
|
+
*/
|
|
25
|
+
groupName;
|
|
26
|
+
name;
|
|
27
|
+
/**
|
|
28
|
+
* The spec conformance classification of this rule, based on RFC 2119 keyword strength.
|
|
29
|
+
* Set on virtual rules derived from named nodeRules in presets.
|
|
30
|
+
*/
|
|
31
|
+
specConformance;
|
|
32
|
+
#v;
|
|
18
33
|
constructor(o) {
|
|
19
|
-
_MLRule_f.set(this, void 0);
|
|
20
|
-
_MLRule_v.set(this, void 0);
|
|
21
34
|
this.name = o.name;
|
|
35
|
+
this.baseRuleId = o.baseRuleId;
|
|
36
|
+
this.groupName = o.groupName;
|
|
37
|
+
this.specConformance = o.specConformance;
|
|
22
38
|
this.defaultSeverity = o.defaultSeverity ?? 'error';
|
|
23
|
-
//
|
|
39
|
+
// When T is boolean, defaultValue is optional and the runtime default is `true`.
|
|
40
|
+
// For non-boolean T, the type system now enforces that defaultValue is provided.
|
|
41
|
+
// See: https://github.com/markuplint/markuplint/issues/808
|
|
24
42
|
this.defaultValue = (o.defaultValue === undefined ? true : o.defaultValue);
|
|
25
43
|
this.defaultOptions = o.defaultOptions;
|
|
26
|
-
|
|
27
|
-
|
|
44
|
+
this.#v = o.verify;
|
|
45
|
+
this.#f = o.fix;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates a virtual rule that reuses this rule's verify/fix logic
|
|
49
|
+
* under a different name (alias). Used by named nodeRules to produce
|
|
50
|
+
* independent rule instances that can be individually configured.
|
|
51
|
+
*
|
|
52
|
+
* @param aliasName - The alias name (must contain `/`)
|
|
53
|
+
* @param options - Override options for the virtual rule
|
|
54
|
+
* @returns A new MLRule instance sharing the same verify/fix logic
|
|
55
|
+
*/
|
|
56
|
+
createAlias(aliasName, options) {
|
|
57
|
+
return new MLRule({
|
|
58
|
+
name: aliasName,
|
|
59
|
+
baseRuleId: this.name,
|
|
60
|
+
groupName: options?.groupName,
|
|
61
|
+
specConformance: options?.specConformance,
|
|
62
|
+
defaultSeverity: options?.defaultSeverity ?? this.defaultSeverity,
|
|
63
|
+
defaultValue: this.defaultValue,
|
|
64
|
+
defaultOptions: this.defaultOptions,
|
|
65
|
+
verify: this.#v,
|
|
66
|
+
fix: this.#f,
|
|
67
|
+
});
|
|
28
68
|
}
|
|
29
69
|
/**
|
|
30
70
|
* The following getter is unused internally,
|
|
31
71
|
* only for extending from 3rd party library
|
|
32
72
|
*/
|
|
33
73
|
get f() {
|
|
34
|
-
return
|
|
74
|
+
return this.#f;
|
|
35
75
|
}
|
|
36
76
|
/**
|
|
37
77
|
* The following getter is unused internally,
|
|
38
78
|
* only for extending from 3rd party library
|
|
39
79
|
*/
|
|
40
80
|
get v() {
|
|
41
|
-
return
|
|
81
|
+
return this.#v;
|
|
42
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Resolves the full rule information from a ruleset, including node-level
|
|
85
|
+
* and child-node-level overrides.
|
|
86
|
+
*
|
|
87
|
+
* @param ruleSet - The ruleset containing rule definitions and overrides
|
|
88
|
+
* @param ruleName - The name of this rule
|
|
89
|
+
* @returns The global rule info with node and child-node overrides
|
|
90
|
+
*/
|
|
43
91
|
getRuleInfo(ruleSet, ruleName) {
|
|
44
92
|
const info = this._optimize(ruleSet.rules, ruleName);
|
|
45
93
|
return {
|
|
@@ -48,6 +96,13 @@ export class MLRule {
|
|
|
48
96
|
childNodeRules: ruleSet.childNodeRules.map(r => this._optimize(r.rules, ruleName)).filter(r => !r.disabled),
|
|
49
97
|
};
|
|
50
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Normalizes a raw rule setting into a fully resolved {@link RuleInfo} object,
|
|
101
|
+
* applying defaults for any unspecified fields.
|
|
102
|
+
*
|
|
103
|
+
* @param configSettings - The raw rule configuration value
|
|
104
|
+
* @returns The resolved rule info with defaults applied
|
|
105
|
+
*/
|
|
51
106
|
optimizeOption(configSettings) {
|
|
52
107
|
if (configSettings === undefined || typeof configSettings === 'boolean') {
|
|
53
108
|
return {
|
|
@@ -79,16 +134,28 @@ export class MLRule {
|
|
|
79
134
|
reason: undefined,
|
|
80
135
|
};
|
|
81
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Executes this rule's verify (and optionally fix) function against a document,
|
|
139
|
+
* then collects and returns the resulting violations.
|
|
140
|
+
*
|
|
141
|
+
* @param document - The parsed document to verify
|
|
142
|
+
* @param locale - The locale set for translating violation messages
|
|
143
|
+
* @param fix - Whether to also run the fix function
|
|
144
|
+
* @returns An array of violations found by this rule
|
|
145
|
+
*/
|
|
82
146
|
async verify(
|
|
83
147
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
84
148
|
document, locale, fix) {
|
|
85
149
|
document.setRule(this);
|
|
86
150
|
const context = new MLRuleContext(document, locale);
|
|
87
151
|
const providableContext = context.provide();
|
|
88
|
-
await
|
|
89
|
-
if (
|
|
90
|
-
await
|
|
152
|
+
await this.#v(providableContext);
|
|
153
|
+
if (this.#f && fix) {
|
|
154
|
+
await this.#f(providableContext);
|
|
91
155
|
}
|
|
156
|
+
const ruleId = this.baseRuleId ?? this.name;
|
|
157
|
+
// Only include name and specConformance for virtual rules (named nodeRules)
|
|
158
|
+
const aliasName = this.baseRuleId ? this.name : undefined;
|
|
92
159
|
const violation = context.reports.map(report => {
|
|
93
160
|
if ('scope' in report) {
|
|
94
161
|
let line = report.scope.startLine;
|
|
@@ -105,7 +172,9 @@ export class MLRule {
|
|
|
105
172
|
line,
|
|
106
173
|
col,
|
|
107
174
|
raw,
|
|
108
|
-
ruleId
|
|
175
|
+
ruleId,
|
|
176
|
+
name: aliasName,
|
|
177
|
+
specConformance: this.specConformance,
|
|
109
178
|
reason: report.scope.rule.reason ?? document.rule.reason,
|
|
110
179
|
};
|
|
111
180
|
deleteUndefProp(violation);
|
|
@@ -117,7 +186,9 @@ export class MLRule {
|
|
|
117
186
|
line: report.line,
|
|
118
187
|
col: report.col,
|
|
119
188
|
raw: report.raw,
|
|
120
|
-
ruleId
|
|
189
|
+
ruleId,
|
|
190
|
+
name: aliasName,
|
|
191
|
+
specConformance: this.specConformance,
|
|
121
192
|
reason: document.rule.reason,
|
|
122
193
|
};
|
|
123
194
|
deleteUndefProp(violation);
|
|
@@ -132,7 +203,6 @@ export class MLRule {
|
|
|
132
203
|
return info;
|
|
133
204
|
}
|
|
134
205
|
}
|
|
135
|
-
_MLRule_f = new WeakMap(), _MLRule_v = new WeakMap();
|
|
136
206
|
function isRuleConfig(data) {
|
|
137
207
|
return isPlainObject(data);
|
|
138
208
|
}
|
package/lib/ml-rule/types.d.ts
CHANGED
|
@@ -2,6 +2,13 @@ import type { MLRuleContext } from './ml-rule-context.js';
|
|
|
2
2
|
import type { Attr, Element } from '../ml-dom/index.js';
|
|
3
3
|
import type { Translator } from '@markuplint/i18n';
|
|
4
4
|
import type { PlainData, Report, RuleConfigValue, Severity } from '@markuplint/ml-config';
|
|
5
|
+
/**
|
|
6
|
+
* The definition of a markuplint rule, including verification logic, optional fix logic,
|
|
7
|
+
* and default configuration values.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The type of the rule's configuration value (defaults to boolean)
|
|
10
|
+
* @template O - The type of the rule's options
|
|
11
|
+
*/
|
|
5
12
|
export type RuleSeed<T extends RuleConfigValue = boolean, O extends PlainData = undefined> = {
|
|
6
13
|
readonly meta?: {
|
|
7
14
|
readonly category?: 'validation' | 'style' | 'naming-convention' | 'a11y' | 'maintainability';
|
|
@@ -12,12 +19,46 @@ export type RuleSeed<T extends RuleConfigValue = boolean, O extends PlainData =
|
|
|
12
19
|
verify(context: ReturnType<MLRuleContext<T, O>['provide']>): void | Promise<void>;
|
|
13
20
|
fix?(context: ReturnType<MLRuleContext<T, O>['provide']>): void | Promise<void>;
|
|
14
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* A generic checker function that produces a violation report from parameters.
|
|
24
|
+
*
|
|
25
|
+
* @template T - The type of the rule's configuration value
|
|
26
|
+
* @template O - The type of the rule's options
|
|
27
|
+
* @template P - Additional parameters passed to the checker
|
|
28
|
+
*/
|
|
15
29
|
export type Checker<T extends RuleConfigValue, O extends PlainData = undefined, P extends Record<string, unknown> = {}> = (params: P) => CheckerReport<T, O>;
|
|
30
|
+
/**
|
|
31
|
+
* A checker function that verifies a specific element and produces a violation report.
|
|
32
|
+
*
|
|
33
|
+
* @template T - The type of the rule's configuration value
|
|
34
|
+
* @template O - The type of the rule's options
|
|
35
|
+
* @template P - Additional parameters passed alongside the element
|
|
36
|
+
*/
|
|
16
37
|
export type ElementChecker<T extends RuleConfigValue, O extends PlainData = undefined, P extends Record<string, unknown> = {}> = (params: P & {
|
|
17
38
|
el: Element<T, O>;
|
|
18
39
|
}) => CheckerReport<T, O>;
|
|
40
|
+
/**
|
|
41
|
+
* A checker function that verifies a specific attribute and produces a violation report.
|
|
42
|
+
*
|
|
43
|
+
* @template T - The type of the rule's configuration value
|
|
44
|
+
* @template O - The type of the rule's options
|
|
45
|
+
* @template P - Additional parameters passed alongside the attribute
|
|
46
|
+
*/
|
|
19
47
|
export type AttrChecker<T extends RuleConfigValue, O extends PlainData = undefined, P extends Record<string, unknown> = {}> = (params: P & {
|
|
20
48
|
attr: Attr<T, O>;
|
|
21
49
|
}) => CheckerReport<T, O>;
|
|
50
|
+
/**
|
|
51
|
+
* A function that receives a translator and returns a violation report, or `null`/`undefined`
|
|
52
|
+
* if no violation was found.
|
|
53
|
+
*
|
|
54
|
+
* @template T - The type of the rule's configuration value
|
|
55
|
+
* @template O - The type of the rule's options
|
|
56
|
+
*/
|
|
22
57
|
export type CheckerReport<T extends RuleConfigValue, O extends PlainData = undefined> = (t: Translator) => Report<T, O> | undefined | null;
|
|
58
|
+
/**
|
|
59
|
+
* A RuleSeed with wildcard value and option types.
|
|
60
|
+
*
|
|
61
|
+
* @template T - The type of the rule's configuration value
|
|
62
|
+
* @template O - The type of the rule's options
|
|
63
|
+
*/
|
|
23
64
|
export type AnyRuleSeed<T extends RuleConfigValue = RuleConfigValue, O extends PlainData = PlainData> = RuleSeed<T, O>;
|
package/lib/plugin/plugin.d.ts
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
1
|
import type { PluginCreator, CreatePluginSettings } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Factory function for creating a type-safe plugin creator.
|
|
4
|
+
* Returns the creator object as-is; primarily used for type inference.
|
|
5
|
+
*
|
|
6
|
+
* @template S - The settings type accepted by the plugin
|
|
7
|
+
* @param fn - The plugin creator definition
|
|
8
|
+
* @returns The same creator object, now fully typed
|
|
9
|
+
*/
|
|
2
10
|
export declare function createPlugin<S extends CreatePluginSettings>(fn: Readonly<PluginCreator<S>>): Readonly<PluginCreator<S>>;
|
package/lib/plugin/plugin.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory function for creating a type-safe plugin creator.
|
|
3
|
+
* Returns the creator object as-is; primarily used for type inference.
|
|
4
|
+
*
|
|
5
|
+
* @template S - The settings type accepted by the plugin
|
|
6
|
+
* @param fn - The plugin creator definition
|
|
7
|
+
* @returns The same creator object, now fully typed
|
|
8
|
+
*/
|
|
1
9
|
export function createPlugin(fn) {
|
|
2
10
|
return fn;
|
|
3
11
|
}
|
package/lib/plugin/types.d.ts
CHANGED
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
import type { RuleSeed } from '../ml-rule/index.js';
|
|
2
2
|
import type { Config } from '@markuplint/ml-config';
|
|
3
|
+
/**
|
|
4
|
+
* A resolved markuplint plugin containing named rules and/or shared configurations.
|
|
5
|
+
*/
|
|
3
6
|
export type Plugin = {
|
|
7
|
+
/** The plugin name, used as a prefix for its rules (e.g. `"my-plugin/rule-name"`) */
|
|
4
8
|
readonly name: string;
|
|
9
|
+
/** Custom rules provided by this plugin */
|
|
5
10
|
readonly rules?: Readonly<Record<string, Readonly<RuleSeed<any, any>>>>;
|
|
11
|
+
/** Shared configurations that users can extend from */
|
|
6
12
|
readonly configs?: Readonly<Record<string, Config>>;
|
|
7
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* A factory interface for creating plugins with custom settings.
|
|
16
|
+
*
|
|
17
|
+
* @template S - The settings type accepted by the plugin creator
|
|
18
|
+
*/
|
|
8
19
|
export type PluginCreator<S extends CreatePluginSettings> = {
|
|
20
|
+
/** The plugin name */
|
|
9
21
|
readonly name: string;
|
|
22
|
+
/**
|
|
23
|
+
* Creates the plugin's rules and configs from the given settings.
|
|
24
|
+
*
|
|
25
|
+
* @param setting - The user-provided settings for this plugin
|
|
26
|
+
* @returns The plugin's rules and configurations
|
|
27
|
+
*/
|
|
10
28
|
create(setting: S): Omit<Plugin, 'name'>;
|
|
11
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Base type for plugin settings. A readonly record of string keys to unknown values.
|
|
32
|
+
*/
|
|
12
33
|
export type CreatePluginSettings = Readonly<Record<string, unknown>>;
|
package/lib/ruleset/index.d.ts
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import type { ChildNodeRule, Config, NodeRule, Rules } from '@markuplint/ml-config';
|
|
2
|
+
/**
|
|
3
|
+
* A resolved set of rules, node-specific rule overrides, and child-node-specific
|
|
4
|
+
* rule overrides extracted from a markuplint {@link Config}.
|
|
5
|
+
*/
|
|
2
6
|
export declare class Ruleset {
|
|
7
|
+
/** Rule overrides that apply to child nodes matching specific selectors */
|
|
3
8
|
readonly childNodeRules: readonly ChildNodeRule[];
|
|
9
|
+
/** Rule overrides that apply to nodes matching specific selectors */
|
|
4
10
|
readonly nodeRules: readonly NodeRule[];
|
|
11
|
+
/** The global rule definitions */
|
|
5
12
|
readonly rules: Rules;
|
|
13
|
+
/**
|
|
14
|
+
* @param config - The markuplint configuration to extract rules from
|
|
15
|
+
*/
|
|
6
16
|
constructor(config: Config);
|
|
7
17
|
}
|
package/lib/ruleset/index.js
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A resolved set of rules, node-specific rule overrides, and child-node-specific
|
|
3
|
+
* rule overrides extracted from a markuplint {@link Config}.
|
|
4
|
+
*/
|
|
1
5
|
export class Ruleset {
|
|
6
|
+
/** Rule overrides that apply to child nodes matching specific selectors */
|
|
7
|
+
childNodeRules;
|
|
8
|
+
/** Rule overrides that apply to nodes matching specific selectors */
|
|
9
|
+
nodeRules;
|
|
10
|
+
/** The global rule definitions */
|
|
11
|
+
rules;
|
|
12
|
+
/**
|
|
13
|
+
* @param config - The markuplint configuration to extract rules from
|
|
14
|
+
*/
|
|
2
15
|
constructor(config) {
|
|
3
16
|
this.rules = config.rules ?? {};
|
|
4
17
|
this.nodeRules = config.nodeRules ?? [];
|
package/lib/test/index.d.ts
CHANGED
|
@@ -5,19 +5,60 @@ import type { MLASTNode, MLASTToken, MLParser } from '@markuplint/ml-ast';
|
|
|
5
5
|
import type { Config, PlainData, Pretender, RuleConfigValue } from '@markuplint/ml-config';
|
|
6
6
|
import type { MLMLSpec } from '@markuplint/ml-spec';
|
|
7
7
|
import { MLDocument } from '../ml-dom/node/document.js';
|
|
8
|
+
/**
|
|
9
|
+
* Options for creating test documents and elements.
|
|
10
|
+
*/
|
|
8
11
|
export type CreateTestOptions = {
|
|
12
|
+
/** The markuplint configuration to apply */
|
|
9
13
|
readonly config?: Config;
|
|
14
|
+
/** A parser module or parser instance to use instead of the default HTML parser */
|
|
10
15
|
readonly parser?: {
|
|
11
16
|
readonly parser: Readonly<MLParser>;
|
|
12
17
|
} | Readonly<MLParser>;
|
|
18
|
+
/** The HTML/ARIA specification data to use */
|
|
13
19
|
readonly specs?: MLMLSpec;
|
|
20
|
+
/** Pretender definitions for component mapping */
|
|
14
21
|
readonly pretenders?: readonly Pretender[];
|
|
15
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* Parses markup source code and returns a test document for use in rule tests.
|
|
25
|
+
*
|
|
26
|
+
* @template T - The rule config value type
|
|
27
|
+
* @template O - The rule options type
|
|
28
|
+
* @param sourceCode - The markup source code to parse
|
|
29
|
+
* @param options - Options for parser, config, specs, and pretenders
|
|
30
|
+
* @returns A parsed MLDocument instance
|
|
31
|
+
*/
|
|
16
32
|
export declare function createTestDocument<T extends RuleConfigValue = any, O extends PlainData = any>(sourceCode: string, options?: CreateTestOptions): MLDocument<T, O>;
|
|
33
|
+
/**
|
|
34
|
+
* Parses markup source code and returns the flat list of AST nodes.
|
|
35
|
+
*
|
|
36
|
+
* @param sourceCode - The markup source code to parse
|
|
37
|
+
* @param options - Options for parser, config, specs, and pretenders
|
|
38
|
+
* @returns A readonly array of all nodes in the parsed document
|
|
39
|
+
*/
|
|
17
40
|
export declare function createTestNodeList(sourceCode: string, options?: CreateTestOptions): readonly MLNode<any, any, MLASTNode>[];
|
|
41
|
+
/**
|
|
42
|
+
* Parses markup source code and returns the flat list of tokens.
|
|
43
|
+
*
|
|
44
|
+
* @param sourceCode - The markup source code to parse
|
|
45
|
+
* @param options - Options for parser, config, specs, and pretenders
|
|
46
|
+
* @returns A readonly array of all tokens in the parsed document
|
|
47
|
+
*/
|
|
18
48
|
export declare function createTestTokenList(sourceCode: string, options?: CreateTestOptions): readonly MLToken<MLASTToken>[];
|
|
49
|
+
/**
|
|
50
|
+
* Parses markup source code and returns the first element node.
|
|
51
|
+
* Throws if the source does not produce an element as its first node.
|
|
52
|
+
*
|
|
53
|
+
* @param sourceCode - The markup source code containing an element
|
|
54
|
+
* @param options - Options for parser, config, specs, and pretenders
|
|
55
|
+
* @returns The first element in the parsed document
|
|
56
|
+
* @throws {TypeError} If the first node is not an element
|
|
57
|
+
*/
|
|
19
58
|
export declare function createTestElement(sourceCode: string, options?: CreateTestOptions): MLElement<any, any>;
|
|
20
59
|
/**
|
|
21
|
-
* for test
|
|
60
|
+
* Returns the default HTML spec as a schema tuple for use in test suites.
|
|
61
|
+
*
|
|
62
|
+
* @returns A single-element tuple containing the HTML specification
|
|
22
63
|
*/
|
|
23
64
|
export declare function dummySchemas(): [MLMLSpec];
|
package/lib/test/index.js
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import { ARIA_RECOMMENDED_VERSION } from '@markuplint/ml-spec';
|
|
1
2
|
import { parser } from '@markuplint/html-parser';
|
|
2
3
|
import spec from '@markuplint/html-spec';
|
|
3
4
|
import { convertRuleset } from '../convert-ruleset.js';
|
|
4
5
|
import { MLDocument } from '../ml-dom/node/document.js';
|
|
6
|
+
/**
|
|
7
|
+
* Parses markup source code and returns a test document for use in rule tests.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The rule config value type
|
|
10
|
+
* @template O - The rule options type
|
|
11
|
+
* @param sourceCode - The markup source code to parse
|
|
12
|
+
* @param options - Options for parser, config, specs, and pretenders
|
|
13
|
+
* @returns A parsed MLDocument instance
|
|
14
|
+
*/
|
|
5
15
|
export function createTestDocument(sourceCode, options) {
|
|
6
16
|
const ast = options?.parser
|
|
7
17
|
? 'parser' in options.parser
|
|
@@ -9,17 +19,42 @@ export function createTestDocument(sourceCode, options) {
|
|
|
9
19
|
: options.parser.parse(sourceCode, options.config?.parserOptions)
|
|
10
20
|
: parser.parse(sourceCode, options?.config?.parserOptions);
|
|
11
21
|
const ruleset = convertRuleset(options?.config);
|
|
12
|
-
const document = new MLDocument(ast, ruleset, [options?.specs ?? {}, {}]
|
|
22
|
+
const document = new MLDocument(ast, ruleset, [options?.specs ?? {}, {}], {
|
|
23
|
+
ariaVersion: ARIA_RECOMMENDED_VERSION,
|
|
24
|
+
});
|
|
13
25
|
return document;
|
|
14
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Parses markup source code and returns the flat list of AST nodes.
|
|
29
|
+
*
|
|
30
|
+
* @param sourceCode - The markup source code to parse
|
|
31
|
+
* @param options - Options for parser, config, specs, and pretenders
|
|
32
|
+
* @returns A readonly array of all nodes in the parsed document
|
|
33
|
+
*/
|
|
15
34
|
export function createTestNodeList(sourceCode, options) {
|
|
16
35
|
const document = createTestDocument(sourceCode, options);
|
|
17
36
|
return document.nodeList;
|
|
18
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Parses markup source code and returns the flat list of tokens.
|
|
40
|
+
*
|
|
41
|
+
* @param sourceCode - The markup source code to parse
|
|
42
|
+
* @param options - Options for parser, config, specs, and pretenders
|
|
43
|
+
* @returns A readonly array of all tokens in the parsed document
|
|
44
|
+
*/
|
|
19
45
|
export function createTestTokenList(sourceCode, options) {
|
|
20
46
|
const document = createTestDocument(sourceCode, options);
|
|
21
47
|
return document.getTokenList();
|
|
22
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Parses markup source code and returns the first element node.
|
|
51
|
+
* Throws if the source does not produce an element as its first node.
|
|
52
|
+
*
|
|
53
|
+
* @param sourceCode - The markup source code containing an element
|
|
54
|
+
* @param options - Options for parser, config, specs, and pretenders
|
|
55
|
+
* @returns The first element in the parsed document
|
|
56
|
+
* @throws {TypeError} If the first node is not an element
|
|
57
|
+
*/
|
|
23
58
|
export function createTestElement(sourceCode, options) {
|
|
24
59
|
const document = createTestDocument(sourceCode, options);
|
|
25
60
|
const el = document.nodeList[0];
|
|
@@ -29,7 +64,9 @@ export function createTestElement(sourceCode, options) {
|
|
|
29
64
|
throw new TypeError(`Could not parse it to be an element from: ${sourceCode}`);
|
|
30
65
|
}
|
|
31
66
|
/**
|
|
32
|
-
* for test
|
|
67
|
+
* Returns the default HTML spec as a schema tuple for use in test suites.
|
|
68
|
+
*
|
|
69
|
+
* @returns A single-element tuple containing the HTML specification
|
|
33
70
|
*/
|
|
34
71
|
export function dummySchemas() {
|
|
35
72
|
return [spec];
|
package/lib/types.d.ts
CHANGED
|
@@ -2,15 +2,24 @@ import type { AnyMLRule } from './ml-rule/index.js';
|
|
|
2
2
|
import type { Ruleset } from './ruleset/index.js';
|
|
3
3
|
import type { LocaleSet } from '@markuplint/i18n';
|
|
4
4
|
import type { MLParser, ParserOptions } from '@markuplint/ml-ast';
|
|
5
|
-
import type { Pretender, SeverityOptions } from '@markuplint/ml-config';
|
|
5
|
+
import type { Pretender, RuleCommonSettings, SeverityOptions } from '@markuplint/ml-config';
|
|
6
6
|
import type { ExtendedSpec, MLMLSpec } from '@markuplint/ml-spec';
|
|
7
|
+
/**
|
|
8
|
+
* A tuple of the base HTML/ARIA specification and zero or more
|
|
9
|
+
* framework-specific extended specs (e.g. React, Vue, Svelte).
|
|
10
|
+
*/
|
|
7
11
|
export type MLSchema = readonly [MLMLSpec, ...ExtendedSpec[]];
|
|
12
|
+
/**
|
|
13
|
+
* The set of dependencies required by {@link MLCore} to perform linting.
|
|
14
|
+
* Includes the parser, ruleset, rules, locale, schemas, and other settings.
|
|
15
|
+
*/
|
|
8
16
|
export type MLFabric = {
|
|
9
17
|
readonly parser: Readonly<MLParser>;
|
|
10
18
|
readonly ruleset: Partial<Readonly<Ruleset>>;
|
|
11
19
|
readonly rules: readonly Readonly<AnyMLRule>[];
|
|
12
20
|
readonly locale: LocaleSet;
|
|
13
21
|
readonly schemas: MLSchema;
|
|
22
|
+
readonly ruleCommonSettings: RuleCommonSettings;
|
|
14
23
|
readonly parserOptions: ParserOptions;
|
|
15
24
|
readonly severity: SeverityOptions;
|
|
16
25
|
readonly pretenders: readonly Pretender[];
|
|
@@ -1,12 +1,45 @@
|
|
|
1
1
|
import type { Violation } from '@markuplint/ml-config';
|
|
2
|
+
/**
|
|
3
|
+
* Collects and manages lint violations across multiple files.
|
|
4
|
+
* Supports a maximum violation count to stop collecting early.
|
|
5
|
+
*/
|
|
2
6
|
export declare class ViolationCollector {
|
|
3
7
|
#private;
|
|
8
|
+
/**
|
|
9
|
+
* @param maxCount - Maximum number of violations to collect; 0 means unlimited
|
|
10
|
+
*/
|
|
4
11
|
constructor(maxCount?: number);
|
|
12
|
+
/**
|
|
13
|
+
* Adds violations associated with a specific file path.
|
|
14
|
+
* Stops collecting once the maximum count is reached.
|
|
15
|
+
*
|
|
16
|
+
* @param filePath - The file that produced these violations
|
|
17
|
+
* @param violations - The violations to add
|
|
18
|
+
* @returns The current total number of collected violations
|
|
19
|
+
*/
|
|
5
20
|
pushWithFile(filePath: string, ...violations: readonly Violation[]): number;
|
|
21
|
+
/**
|
|
22
|
+
* The total number of collected violations.
|
|
23
|
+
*/
|
|
6
24
|
get length(): number;
|
|
25
|
+
/**
|
|
26
|
+
* Whether the collector has reached its maximum count and will no longer accept violations.
|
|
27
|
+
*
|
|
28
|
+
* @returns `true` if the collector is locked
|
|
29
|
+
*/
|
|
7
30
|
isLocked(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Returns a copy of all collected violations as an array.
|
|
33
|
+
*
|
|
34
|
+
* @returns An array of violations with their associated file paths
|
|
35
|
+
*/
|
|
8
36
|
toArray(): (Violation & {
|
|
9
37
|
filePath: string;
|
|
10
38
|
})[];
|
|
39
|
+
/**
|
|
40
|
+
* Groups collected violations by their file path.
|
|
41
|
+
*
|
|
42
|
+
* @returns A Map from file path to an array of violations for that file
|
|
43
|
+
*/
|
|
11
44
|
groupByFile(): Map<string, Violation[]>;
|
|
12
45
|
}
|
|
@@ -1,48 +1,69 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
-
};
|
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _ViolationCollector_violations, _ViolationCollector_maxCount, _ViolationCollector_locked;
|
|
1
|
+
/**
|
|
2
|
+
* Collects and manages lint violations across multiple files.
|
|
3
|
+
* Supports a maximum violation count to stop collecting early.
|
|
4
|
+
*/
|
|
13
5
|
export class ViolationCollector {
|
|
6
|
+
#violations = [];
|
|
7
|
+
#maxCount = 0;
|
|
8
|
+
#locked = false;
|
|
9
|
+
/**
|
|
10
|
+
* @param maxCount - Maximum number of violations to collect; 0 means unlimited
|
|
11
|
+
*/
|
|
14
12
|
constructor(maxCount = 0) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
_ViolationCollector_locked.set(this, false);
|
|
18
|
-
__classPrivateFieldSet(this, _ViolationCollector_maxCount, maxCount, "f");
|
|
19
|
-
__classPrivateFieldSet(this, _ViolationCollector_locked, false, "f");
|
|
13
|
+
this.#maxCount = maxCount;
|
|
14
|
+
this.#locked = false;
|
|
20
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Adds violations associated with a specific file path.
|
|
18
|
+
* Stops collecting once the maximum count is reached.
|
|
19
|
+
*
|
|
20
|
+
* @param filePath - The file that produced these violations
|
|
21
|
+
* @param violations - The violations to add
|
|
22
|
+
* @returns The current total number of collected violations
|
|
23
|
+
*/
|
|
21
24
|
pushWithFile(filePath, ...violations) {
|
|
22
|
-
if (
|
|
23
|
-
return
|
|
25
|
+
if (this.#locked) {
|
|
26
|
+
return this.#violations.length;
|
|
24
27
|
}
|
|
25
28
|
for (const violation of violations) {
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
+
this.#violations.push({ ...violation, filePath });
|
|
30
|
+
if (this.#maxCount > 0 && this.#violations.length >= this.#maxCount) {
|
|
31
|
+
this.#locked = true;
|
|
29
32
|
break;
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
|
-
return
|
|
35
|
+
return this.#violations.length;
|
|
33
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* The total number of collected violations.
|
|
39
|
+
*/
|
|
34
40
|
get length() {
|
|
35
|
-
return
|
|
41
|
+
return this.#violations.length;
|
|
36
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Whether the collector has reached its maximum count and will no longer accept violations.
|
|
45
|
+
*
|
|
46
|
+
* @returns `true` if the collector is locked
|
|
47
|
+
*/
|
|
37
48
|
isLocked() {
|
|
38
|
-
return
|
|
49
|
+
return this.#locked;
|
|
39
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Returns a copy of all collected violations as an array.
|
|
53
|
+
*
|
|
54
|
+
* @returns An array of violations with their associated file paths
|
|
55
|
+
*/
|
|
40
56
|
toArray() {
|
|
41
|
-
return [...
|
|
57
|
+
return [...this.#violations];
|
|
42
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Groups collected violations by their file path.
|
|
61
|
+
*
|
|
62
|
+
* @returns A Map from file path to an array of violations for that file
|
|
63
|
+
*/
|
|
43
64
|
groupByFile() {
|
|
44
65
|
const grouped = new Map();
|
|
45
|
-
for (const violation of
|
|
66
|
+
for (const violation of this.#violations) {
|
|
46
67
|
const { filePath, ...violationWithoutPath } = violation;
|
|
47
68
|
if (!grouped.has(filePath)) {
|
|
48
69
|
grouped.set(filePath, []);
|
|
@@ -52,4 +73,3 @@ export class ViolationCollector {
|
|
|
52
73
|
return grouped;
|
|
53
74
|
}
|
|
54
75
|
}
|
|
55
|
-
_ViolationCollector_violations = new WeakMap(), _ViolationCollector_maxCount = new WeakMap(), _ViolationCollector_locked = new WeakMap();
|