@markuplint/ml-core 5.0.0-rc.5 → 5.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/CHANGELOG.md +27 -0
- package/lib/ml-core.d.ts +16 -2
- package/lib/ml-core.js +84 -32
- package/lib/types.d.ts +8 -1
- package/package.json +12 -12
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,33 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [5.0.0-rc.6](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.5...v5.0.0-rc.6) (2026-08-30)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- split rule-deprecation notices out of config-error ([#4013](https://github.com/markuplint/markuplint/issues/4013)) ([812e6f3](https://github.com/markuplint/markuplint/commit/812e6f356839af8f257cfd91e6b16cfdfdd7cf33))
|
|
11
|
+
|
|
12
|
+
### BREAKING CHANGES
|
|
13
|
+
|
|
14
|
+
- violations for deprecated rule names now have
|
|
15
|
+
`ruleId: 'rule-deprecation'` instead of `ruleId: 'config-error'`. Any
|
|
16
|
+
consumer filtering `MLCore.verify()` output (or the markuplint CLI/API) by
|
|
17
|
+
`ruleId === 'config-error'` to catch deprecation messages must also check
|
|
18
|
+
for `rule-deprecation`.
|
|
19
|
+
|
|
20
|
+
- feat(markuplint): add --severity-deprecation CLI flag
|
|
21
|
+
|
|
22
|
+
Wires the new severity.deprecation config option (@markuplint/ml-config)
|
|
23
|
+
and the rule-deprecation ruleId (@markuplint/ml-core) through the CLI:
|
|
24
|
+
|
|
25
|
+
- --severity-deprecation flag, mirroring --severity-parse-error
|
|
26
|
+
- --show-config details now also surfaces ruleDeprecations
|
|
27
|
+
- per-run dedupe and failed-file counting generalized to cover both
|
|
28
|
+
config-level ruleIds (config-error and rule-deprecation), not just
|
|
29
|
+
config-error
|
|
30
|
+
|
|
31
|
+
* docs(website): document severity.deprecation (EN + JA)
|
|
32
|
+
|
|
6
33
|
# [5.0.0-rc.5](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.4...v5.0.0-rc.5) (2026-08-28)
|
|
7
34
|
|
|
8
35
|
### Bug Fixes
|
package/lib/ml-core.d.ts
CHANGED
|
@@ -2,6 +2,20 @@ import type { MLFabric } from './types.js';
|
|
|
2
2
|
import type { PlainData, RuleConfigValue, TextEdit, Violation } from '@markuplint/ml-config';
|
|
3
3
|
import { ParserError } from '@markuplint/parser-utils';
|
|
4
4
|
import { Document } from './ml-dom/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* `ruleId` of a genuinely broken config (unresolved rule reference, plugin
|
|
7
|
+
* resolution failure, ...). Exported so consumers that need to recognize
|
|
8
|
+
* config-level violations (e.g. the CLI's per-run dedupe and failed-file
|
|
9
|
+
* counting in `packages/markuplint/src/cli/command.ts`) reference the same
|
|
10
|
+
* literal `MLCore.verify()` emits, instead of duplicating the string.
|
|
11
|
+
*/
|
|
12
|
+
export declare const CONFIG_ERROR_RULE_ID = "config-error";
|
|
13
|
+
/**
|
|
14
|
+
* `ruleId` of a deprecated-but-working rule name notice — see
|
|
15
|
+
* {@link CONFIG_ERROR_RULE_ID} for why this is exported rather than a
|
|
16
|
+
* private literal.
|
|
17
|
+
*/
|
|
18
|
+
export declare const RULE_DEPRECATION_RULE_ID = "rule-deprecation";
|
|
5
19
|
/**
|
|
6
20
|
* Summary of the multi-pass fix process.
|
|
7
21
|
*/
|
|
@@ -74,7 +88,7 @@ export type MLCoreParams = {
|
|
|
74
88
|
*/
|
|
75
89
|
export declare class MLCore {
|
|
76
90
|
#private;
|
|
77
|
-
constructor({ parser, sourceCode, ruleset, rules, locale, schemas, ruleCommonSettings, parserOptions, severity, pretenders, filename, debug, configErrors, }: MLCoreParams);
|
|
91
|
+
constructor({ parser, sourceCode, ruleset, rules, locale, schemas, ruleCommonSettings, parserOptions, severity, pretenders, filename, debug, configErrors, ruleDeprecations, }: MLCoreParams);
|
|
78
92
|
/**
|
|
79
93
|
* The parsed document, or a {@link ParserError} if parsing failed.
|
|
80
94
|
*/
|
|
@@ -91,7 +105,7 @@ export declare class MLCore {
|
|
|
91
105
|
*
|
|
92
106
|
* @param fabric - Partial fabric with the properties to update
|
|
93
107
|
*/
|
|
94
|
-
update({ parser, ruleset, rules, locale, schemas, parserOptions, pretenders, configErrors }: Partial<MLFabric>): void;
|
|
108
|
+
update({ parser, ruleset, rules, locale, schemas, parserOptions, pretenders, configErrors, ruleDeprecations, }: Partial<MLFabric>): void;
|
|
95
109
|
/**
|
|
96
110
|
* Runs all configured rules against the parsed document and returns violations.
|
|
97
111
|
*
|
package/lib/ml-core.js
CHANGED
|
@@ -4,6 +4,20 @@ import { applyFixes } from './fix-applier.js';
|
|
|
4
4
|
import { Document } from './ml-dom/index.js';
|
|
5
5
|
import { expandNamedNodeRules, expandNamedRules } from './virtual-rule.js';
|
|
6
6
|
const resultLog = log.extend('result');
|
|
7
|
+
/**
|
|
8
|
+
* `ruleId` of a genuinely broken config (unresolved rule reference, plugin
|
|
9
|
+
* resolution failure, ...). Exported so consumers that need to recognize
|
|
10
|
+
* config-level violations (e.g. the CLI's per-run dedupe and failed-file
|
|
11
|
+
* counting in `packages/markuplint/src/cli/command.ts`) reference the same
|
|
12
|
+
* literal `MLCore.verify()` emits, instead of duplicating the string.
|
|
13
|
+
*/
|
|
14
|
+
export const CONFIG_ERROR_RULE_ID = 'config-error';
|
|
15
|
+
/**
|
|
16
|
+
* `ruleId` of a deprecated-but-working rule name notice — see
|
|
17
|
+
* {@link CONFIG_ERROR_RULE_ID} for why this is exported rather than a
|
|
18
|
+
* private literal.
|
|
19
|
+
*/
|
|
20
|
+
export const RULE_DEPRECATION_RULE_ID = 'rule-deprecation';
|
|
7
21
|
/**
|
|
8
22
|
* The core linting engine for markuplint.
|
|
9
23
|
*
|
|
@@ -29,6 +43,13 @@ export class MLCore {
|
|
|
29
43
|
* Set once per construction/`update()` and never mutated by re-parsing.
|
|
30
44
|
*/
|
|
31
45
|
#configErrors;
|
|
46
|
+
/**
|
|
47
|
+
* Deprecated-rule-name notices, kept structured and separate from
|
|
48
|
+
* `#configErrors` so `verify()` can report them under their own
|
|
49
|
+
* `rule-deprecation` ruleId. Set once per construction/`update()`, same
|
|
50
|
+
* lifecycle as `#configErrors`.
|
|
51
|
+
*/
|
|
52
|
+
#ruleDeprecations;
|
|
32
53
|
/**
|
|
33
54
|
* Rule-mapping errors for the CURRENT document. Reset (not accumulated) on
|
|
34
55
|
* every `#createDocument()` so repeated `setCode()` calls don't duplicate
|
|
@@ -44,7 +65,7 @@ export class MLCore {
|
|
|
44
65
|
#originalNodeRules;
|
|
45
66
|
#originalChildNodeRules;
|
|
46
67
|
#disabledNamespaces;
|
|
47
|
-
constructor({ parser, sourceCode, ruleset, rules, locale, schemas, ruleCommonSettings, parserOptions, severity, pretenders, filename, debug, configErrors, }) {
|
|
68
|
+
constructor({ parser, sourceCode, ruleset, rules, locale, schemas, ruleCommonSettings, parserOptions, severity, pretenders, filename, debug, configErrors, ruleDeprecations, }) {
|
|
48
69
|
if (debug) {
|
|
49
70
|
enableDebug();
|
|
50
71
|
}
|
|
@@ -58,6 +79,7 @@ export class MLCore {
|
|
|
58
79
|
this.#severity = severity;
|
|
59
80
|
this.#pretenders = [...pretenders];
|
|
60
81
|
this.#configErrors = [...(configErrors ?? [])];
|
|
82
|
+
this.#ruleDeprecations = [...(ruleDeprecations ?? [])];
|
|
61
83
|
// Preserve pre-expansion nodeRules for hot-reload
|
|
62
84
|
this.#originalNodeRules = ruleset.nodeRules ?? [];
|
|
63
85
|
this.#originalChildNodeRules = ruleset.childNodeRules ?? [];
|
|
@@ -101,12 +123,13 @@ export class MLCore {
|
|
|
101
123
|
*
|
|
102
124
|
* @param fabric - Partial fabric with the properties to update
|
|
103
125
|
*/
|
|
104
|
-
update({ parser, ruleset, rules, locale, schemas, parserOptions, pretenders, configErrors }) {
|
|
126
|
+
update({ parser, ruleset, rules, locale, schemas, parserOptions, pretenders, configErrors, ruleDeprecations, }) {
|
|
105
127
|
this.#parser = parser ?? this.#parser;
|
|
106
128
|
this.#locale = locale ?? this.#locale;
|
|
107
129
|
this.#schemas = schemas ?? this.#schemas;
|
|
108
130
|
this.#pretenders = pretenders ? [...pretenders] : this.#pretenders;
|
|
109
131
|
this.#configErrors = [...(configErrors ?? [])];
|
|
132
|
+
this.#ruleDeprecations = [...(ruleDeprecations ?? [])];
|
|
110
133
|
const baseRules = rules ? [...rules] : this.#rules.filter(r => !r.baseRuleId);
|
|
111
134
|
const incomingNodeRules = ruleset?.nodeRules ?? this.#originalNodeRules;
|
|
112
135
|
const incomingChildNodeRules = ruleset?.childNodeRules ?? this.#originalChildNodeRules;
|
|
@@ -170,7 +193,7 @@ export class MLCore {
|
|
|
170
193
|
}
|
|
171
194
|
if (!definedRuleName.has(setRuleName)) {
|
|
172
195
|
configViolations.push({
|
|
173
|
-
ruleId:
|
|
196
|
+
ruleId: CONFIG_ERROR_RULE_ID,
|
|
174
197
|
severity: 'warning',
|
|
175
198
|
message: `Rule not found: ${setRuleName}`,
|
|
176
199
|
col: 1,
|
|
@@ -181,7 +204,7 @@ export class MLCore {
|
|
|
181
204
|
}
|
|
182
205
|
for (const error of [...this.#configErrors, ...this.#mappingErrors]) {
|
|
183
206
|
configViolations.push({
|
|
184
|
-
ruleId:
|
|
207
|
+
ruleId: CONFIG_ERROR_RULE_ID,
|
|
185
208
|
severity: 'warning',
|
|
186
209
|
message: error.message,
|
|
187
210
|
col: 1,
|
|
@@ -189,6 +212,19 @@ export class MLCore {
|
|
|
189
212
|
raw: '',
|
|
190
213
|
});
|
|
191
214
|
}
|
|
215
|
+
const deprecationSeverity = this.#resolveDeprecationSeverity();
|
|
216
|
+
if (deprecationSeverity != null) {
|
|
217
|
+
for (const { deprecatedName, replacedBy } of this.#ruleDeprecations) {
|
|
218
|
+
configViolations.push({
|
|
219
|
+
ruleId: RULE_DEPRECATION_RULE_ID,
|
|
220
|
+
severity: deprecationSeverity,
|
|
221
|
+
message: `Rule "${deprecatedName}" is deprecated and will be removed in v6. Use ${replacedBy.join(', ')} instead.`,
|
|
222
|
+
col: 1,
|
|
223
|
+
line: 1,
|
|
224
|
+
raw: '',
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
192
228
|
violations.push(...configViolations);
|
|
193
229
|
const ruleViolations = await this.#runAllRules(fix);
|
|
194
230
|
violations.push(...ruleViolations);
|
|
@@ -363,6 +399,22 @@ export class MLCore {
|
|
|
363
399
|
}
|
|
364
400
|
}
|
|
365
401
|
}
|
|
402
|
+
/**
|
|
403
|
+
* Resolves `severity.deprecation`, honouring its single-value form only
|
|
404
|
+
* (unlike `severity.parseError`, there's no fixed enum of deprecated rule
|
|
405
|
+
* names to key a per-code `Record` on).
|
|
406
|
+
*
|
|
407
|
+
* Unlike `#createParseError`'s parse-error channel, this defaults to
|
|
408
|
+
* `'warning'` (not off/suppressed) when unset — the deprecation channel
|
|
409
|
+
* is being carved out of the always-on `config-error` channel, not
|
|
410
|
+
* introduced cold, so leaving the option unset must not silence a notice
|
|
411
|
+
* users already see today.
|
|
412
|
+
*
|
|
413
|
+
* @returns the resolved severity, or `null` if suppressed.
|
|
414
|
+
*/
|
|
415
|
+
#resolveDeprecationSeverity() {
|
|
416
|
+
return resolveUniformSeverity(this.#severity.deprecation, 'warning');
|
|
417
|
+
}
|
|
366
418
|
/**
|
|
367
419
|
* Builds a `ruleId: 'parse-error'` violation, honouring
|
|
368
420
|
* `severity.parseError`.
|
|
@@ -377,36 +429,18 @@ export class MLCore {
|
|
|
377
429
|
*/
|
|
378
430
|
#createParseError(message, line, col, raw, code) {
|
|
379
431
|
const cfg = this.#severity.parseError;
|
|
380
|
-
|
|
432
|
+
// Fatal ParserErrors (no `code`) can't be targeted by the per-code
|
|
433
|
+
// Record form, so they fall back to `'error'` there; under the
|
|
434
|
+
// uniform form they default to `'error'` too, while non-fatal entries
|
|
435
|
+
// default to suppressed when unset — see `resolveUniformSeverity`.
|
|
436
|
+
const severity = typeof cfg === 'object'
|
|
437
|
+
? code == null
|
|
438
|
+
? 'error'
|
|
439
|
+
: resolveUniformSeverity(cfg[code], null)
|
|
440
|
+
: resolveUniformSeverity(cfg, code == null ? 'error' : null);
|
|
441
|
+
if (severity == null) {
|
|
381
442
|
return null;
|
|
382
443
|
}
|
|
383
|
-
let severity;
|
|
384
|
-
if (typeof cfg === 'object') {
|
|
385
|
-
if (code == null) {
|
|
386
|
-
// Fatal ParserError without a code; the Record form cannot target
|
|
387
|
-
// it, so fall back to `'error'` (the channel is otherwise enabled).
|
|
388
|
-
severity = 'error';
|
|
389
|
-
}
|
|
390
|
-
else {
|
|
391
|
-
const perCode = cfg[code];
|
|
392
|
-
if (perCode == null || perCode === false || perCode === 'off') {
|
|
393
|
-
return null;
|
|
394
|
-
}
|
|
395
|
-
severity = perCode === true ? 'error' : perCode;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
else if (cfg == null) {
|
|
399
|
-
// New default: non-fatal `parseErrors` entries are off; fatal
|
|
400
|
-
// `ParserError`s (no code) still emit at `'error'`.
|
|
401
|
-
if (code != null) {
|
|
402
|
-
return null;
|
|
403
|
-
}
|
|
404
|
-
severity = 'error';
|
|
405
|
-
}
|
|
406
|
-
else {
|
|
407
|
-
// Uniform string/boolean form (legacy).
|
|
408
|
-
severity = cfg === true ? 'error' : cfg;
|
|
409
|
-
}
|
|
410
444
|
return {
|
|
411
445
|
ruleId: 'parse-error',
|
|
412
446
|
severity,
|
|
@@ -597,6 +631,24 @@ export class MLCore {
|
|
|
597
631
|
}
|
|
598
632
|
}
|
|
599
633
|
}
|
|
634
|
+
/**
|
|
635
|
+
* Normalizes a single-value `Severity | 'off' | boolean | undefined` option
|
|
636
|
+
* (the shape `severity.deprecation` and `severity.parseError`'s uniform/
|
|
637
|
+
* per-code leaf values share) to a resolved severity or `null` (suppressed).
|
|
638
|
+
*
|
|
639
|
+
* Shared so the same three-way rule — `false`/`'off'` → suppressed, `true` →
|
|
640
|
+
* `'error'`, unset → `defaultWhenUnset` — isn't reimplemented at each call
|
|
641
|
+
* site as channels using this shape are added.
|
|
642
|
+
*/
|
|
643
|
+
function resolveUniformSeverity(cfg, defaultWhenUnset) {
|
|
644
|
+
if (cfg === false || cfg === 'off') {
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
647
|
+
if (cfg == null) {
|
|
648
|
+
return defaultWhenUnset;
|
|
649
|
+
}
|
|
650
|
+
return cfg === true ? 'error' : cfg;
|
|
651
|
+
}
|
|
600
652
|
function extractDisabledNamespaces(rules) {
|
|
601
653
|
return Object.entries(rules)
|
|
602
654
|
.filter(([key, value]) => key.endsWith('/*') && value === false)
|
package/lib/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ 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, RuleCommonSettings, SeverityOptions } from '@markuplint/ml-config';
|
|
5
|
+
import type { Pretender, RuleAliasWarning, RuleCommonSettings, SeverityOptions } from '@markuplint/ml-config';
|
|
6
6
|
import type { ExtendedSpec, MLMLSpec } from '@markuplint/ml-spec';
|
|
7
7
|
/**
|
|
8
8
|
* A tuple of the base HTML/ARIA specification and zero or more
|
|
@@ -24,4 +24,11 @@ export type MLFabric = {
|
|
|
24
24
|
readonly severity: SeverityOptions;
|
|
25
25
|
readonly pretenders: readonly Pretender[];
|
|
26
26
|
readonly configErrors?: readonly Readonly<Error>[];
|
|
27
|
+
/**
|
|
28
|
+
* Deprecated-rule-name notices found while applying the rule-alias table
|
|
29
|
+
* (v5 rule-system redesign, #3989). Kept structured, separate from
|
|
30
|
+
* {@link configErrors}, so `MLCore.verify()` can report them under their
|
|
31
|
+
* own `rule-deprecation` ruleId instead of `config-error`.
|
|
32
|
+
*/
|
|
33
|
+
readonly ruleDeprecations?: readonly RuleAliasWarning[];
|
|
27
34
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/ml-core",
|
|
3
|
-
"version": "5.0.0-rc.
|
|
3
|
+
"version": "5.0.0-rc.6",
|
|
4
4
|
"description": "The core module of markuplint",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,20 +34,20 @@
|
|
|
34
34
|
"./lib/configs.js": "./lib/configs.browser.js"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@markuplint/config-presets": "5.0.0-rc.
|
|
38
|
-
"@markuplint/html-parser": "5.0.0-rc.
|
|
39
|
-
"@markuplint/html-spec": "5.0.0-rc.
|
|
40
|
-
"@markuplint/i18n": "5.0.0-rc.
|
|
41
|
-
"@markuplint/ml-ast": "5.0.0-rc.
|
|
42
|
-
"@markuplint/ml-config": "5.0.0-rc.
|
|
43
|
-
"@markuplint/ml-spec": "5.0.0-rc.
|
|
44
|
-
"@markuplint/parser-utils": "5.0.0-rc.
|
|
45
|
-
"@markuplint/selector": "5.0.0-rc.
|
|
46
|
-
"@markuplint/shared": "5.0.0-rc.
|
|
37
|
+
"@markuplint/config-presets": "5.0.0-rc.6",
|
|
38
|
+
"@markuplint/html-parser": "5.0.0-rc.6",
|
|
39
|
+
"@markuplint/html-spec": "5.0.0-rc.6",
|
|
40
|
+
"@markuplint/i18n": "5.0.0-rc.6",
|
|
41
|
+
"@markuplint/ml-ast": "5.0.0-rc.6",
|
|
42
|
+
"@markuplint/ml-config": "5.0.0-rc.6",
|
|
43
|
+
"@markuplint/ml-spec": "5.0.0-rc.6",
|
|
44
|
+
"@markuplint/parser-utils": "5.0.0-rc.6",
|
|
45
|
+
"@markuplint/selector": "5.0.0-rc.6",
|
|
46
|
+
"@markuplint/shared": "5.0.0-rc.6",
|
|
47
47
|
"@types/debug": "4.1.13",
|
|
48
48
|
"debug": "4.4.3",
|
|
49
49
|
"is-plain-object": "5.0.0",
|
|
50
50
|
"type-fest": "5.6.0"
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "c02c3a0783eac6b2fb4707be2dc00b88f6219641"
|
|
53
53
|
}
|