@markuplint/ml-core 5.0.0-rc.4 → 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.
Files changed (68) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +0 -5
  3. package/lib/cursor-offset.js +0 -3
  4. package/lib/fix-applier.js +3 -9
  5. package/lib/ml-core.d.ts +33 -3
  6. package/lib/ml-core.js +276 -62
  7. package/lib/ml-dom/helper/accname.d.ts +0 -8
  8. package/lib/ml-dom/helper/accname.js +7 -10
  9. package/lib/ml-dom/node/attr.js +3 -1
  10. package/lib/ml-dom/node/block.d.ts +6 -0
  11. package/lib/ml-dom/node/block.js +6 -0
  12. package/lib/ml-dom/node/child-node.d.ts +0 -9
  13. package/lib/ml-dom/node/child-node.js +0 -9
  14. package/lib/ml-dom/node/document.d.ts +20 -1
  15. package/lib/ml-dom/node/document.js +24 -13
  16. package/lib/ml-dom/node/element-close-tag.d.ts +12 -0
  17. package/lib/ml-dom/node/element-close-tag.js +12 -0
  18. package/lib/ml-dom/node/element.d.ts +22 -0
  19. package/lib/ml-dom/node/element.js +37 -11
  20. package/lib/ml-dom/node/node-store.d.ts +0 -3
  21. package/lib/ml-dom/node/node-store.js +0 -3
  22. package/lib/ml-dom/node/node.d.ts +34 -1
  23. package/lib/ml-dom/node/node.js +34 -16
  24. package/lib/ml-dom/node/parent-node.js +0 -6
  25. package/lib/ml-dom/node/rule-mapper.d.ts +8 -0
  26. package/lib/ml-dom/node/rule-mapper.js +8 -0
  27. package/lib/ml-rule/ml-rule.d.ts +19 -0
  28. package/lib/ml-rule/ml-rule.js +38 -7
  29. package/lib/ml-rule/types.d.ts +110 -1
  30. package/lib/ml-rule/types.js +28 -1
  31. package/lib/ruleset/index.d.ts +2 -1
  32. package/lib/ruleset/index.js +2 -1
  33. package/lib/test/index.js +1 -1
  34. package/lib/types.d.ts +8 -1
  35. package/lib/virtual-rule.d.ts +10 -0
  36. package/lib/virtual-rule.js +1 -24
  37. package/package.json +13 -13
  38. package/ARCHITECTURE.ja.md +0 -676
  39. package/ARCHITECTURE.md +0 -726
  40. package/SKILL.md +0 -61
  41. package/docs/linting-pipeline.ja.md +0 -307
  42. package/docs/linting-pipeline.md +0 -307
  43. package/docs/maintenance.ja.md +0 -210
  44. package/docs/maintenance.md +0 -210
  45. package/docs/ml-dom/attr.ja.md +0 -103
  46. package/docs/ml-dom/attr.md +0 -103
  47. package/docs/ml-dom/block.ja.md +0 -272
  48. package/docs/ml-dom/block.md +0 -272
  49. package/docs/ml-dom/document.ja.md +0 -134
  50. package/docs/ml-dom/document.md +0 -134
  51. package/docs/ml-dom/element.ja.md +0 -161
  52. package/docs/ml-dom/element.md +0 -161
  53. package/docs/ml-dom/helpers.ja.md +0 -203
  54. package/docs/ml-dom/helpers.md +0 -203
  55. package/docs/ml-dom/node.ja.md +0 -199
  56. package/docs/ml-dom/node.md +0 -199
  57. package/docs/ml-dom/others.ja.md +0 -120
  58. package/docs/ml-dom/others.md +0 -120
  59. package/docs/ml-dom/overview.ja.md +0 -102
  60. package/docs/ml-dom/overview.md +0 -102
  61. package/docs/ml-dom/pretender.ja.md +0 -269
  62. package/docs/ml-dom/pretender.md +0 -269
  63. package/docs/ml-dom/rule-mapping.ja.md +0 -371
  64. package/docs/ml-dom/rule-mapping.md +0 -371
  65. package/docs/ml-dom.ja.md +0 -18
  66. package/docs/ml-dom.md +0 -18
  67. package/docs/rule-system.ja.md +0 -287
  68. package/docs/rule-system.md +0 -287
package/CHANGELOG.md CHANGED
@@ -3,6 +3,62 @@
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
+
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)
34
+
35
+ ### Bug Fixes
36
+
37
+ - **ml-core:** look up dedupe contract under both alias and base rule names ([a5dde7e](https://github.com/markuplint/markuplint/commit/a5dde7e23a12a43d976fbfaa1cc3dec67265447e)), closes [#3844](https://github.com/markuplint/markuplint/issues/3844) [#3871](https://github.com/markuplint/markuplint/issues/3871)
38
+ - **ml-core:** re-verify fixed code and detect N-pass fix cycles ([8c96516](https://github.com/markuplint/markuplint/commit/8c96516d8057acdcf06dc279c2183390f0966e98)), closes [#3890](https://github.com/markuplint/markuplint/issues/3890) [#3891](https://github.com/markuplint/markuplint/issues/3891)
39
+ - **ml-core:** stop accumulating duplicate mapping errors across setCode ([2874d5b](https://github.com/markuplint/markuplint/commit/2874d5b60b24ccc501f7dae1f6ab25fb6e51e58b)), closes [#3900](https://github.com/markuplint/markuplint/issues/3900)
40
+ - **pretenders:** resolve same-named components via imports, not scan order ([#3957](https://github.com/markuplint/markuplint/issues/3957)) ([d46a514](https://github.com/markuplint/markuplint/commit/d46a5148c4d7afb156962f4ed795f40a9324e6c5)), closes [#3951](https://github.com/markuplint/markuplint/issues/3951) [#3951](https://github.com/markuplint/markuplint/issues/3951) [#3951](https://github.com/markuplint/markuplint/issues/3951)
41
+ - **rules:** surface disallowed-element reason via reasonOnly (close [#3815](https://github.com/markuplint/markuplint/issues/3815)) ([#3986](https://github.com/markuplint/markuplint/issues/3986)) ([0142cec](https://github.com/markuplint/markuplint/commit/0142cec667f70fee086f2a6e06d7a26e66bda380))
42
+
43
+ ### Code Refactoring
44
+
45
+ - **rules:** redesign v5 rule system — naming, splits, specConformance ([#3989](https://github.com/markuplint/markuplint/issues/3989)) ([e925565](https://github.com/markuplint/markuplint/commit/e925565ce537848d7d1573369723cbce724a841b)), closes [#4](https://github.com/markuplint/markuplint/issues/4) [#aside-conditional-role-mapping-aria-13](https://github.com/markuplint/markuplint/issues/aside-conditional-role-mapping-aria-13)
46
+
47
+ - fix(ml-core)!: reject pretender on standard HTML elements ([0576425](https://github.com/markuplint/markuplint/commit/0576425baf9b78141523bcd0e4a102062b96bc81)), closes [#3740](https://github.com/markuplint/markuplint/issues/3740)
48
+
49
+ ### Features
50
+
51
+ - **ml-core:** hook-based dedupe for parse-error channel via mirrorsParseErrorCodes ([6a36f17](https://github.com/markuplint/markuplint/commit/6a36f17d292a2400494a3670c93cb2f02999b48b)), closes [#3844](https://github.com/markuplint/markuplint/issues/3844)
52
+ - **ml-core:** surface non-fatal parser errors via opt-in parse-error channel ([d715fbe](https://github.com/markuplint/markuplint/commit/d715fbe586c478b98472a570b3175873cf244aef)), closes [#3844](https://github.com/markuplint/markuplint/issues/3844)
53
+
54
+ ### BREAKING CHANGES
55
+
56
+ - **rules:** with no alias coverage.
57
+ - `pretenders` config entries whose selector matches a
58
+ standard HTML element are now ignored. Configurations that previously
59
+ relied on `<marquee as="div">` to suppress markuplint violations must
60
+ remove the entry; the original element is now linted on its own merits.
61
+
6
62
  # [5.0.0-rc.4](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.3...v5.0.0-rc.4) (2026-04-19)
7
63
 
8
64
  **Note:** Version bump only for package @markuplint/ml-core
package/README.md CHANGED
@@ -5,11 +5,6 @@
5
5
  ## Documentation
6
6
 
7
7
  - [API Document](https://markuplint.dev/api-docs)
8
- - [Architecture](ARCHITECTURE.md) ([日本語](ARCHITECTURE.ja.md)) — Package overview, MLDOM hierarchy, rule system, and linting pipeline
9
- - [MLDOM Reference](docs/ml-dom.md) ([日本語](docs/ml-dom.ja.md)) — Class hierarchy, node properties, tree traversal
10
- - [Rule System](docs/rule-system.md) ([日本語](docs/rule-system.ja.md)) — MLRule, RuleSeed, MLRuleContext, configuration resolution
11
- - [Linting Pipeline](docs/linting-pipeline.md) ([日本語](docs/linting-pipeline.ja.md)) — MLCore engine, verify flow, pretender, plugin system
12
- - [Maintenance Guide](docs/maintenance.md) ([日本語](docs/maintenance.ja.md)) — Commands, recipes, and troubleshooting
13
8
 
14
9
  ## Install
15
10
 
@@ -15,16 +15,13 @@ export function computeCursorOffset(appliedEdits, cursorOffset) {
15
15
  const [start, end] = edit.range;
16
16
  const delta = edit.text.length - (end - start);
17
17
  if (start > cursorOffset) {
18
- // Edit is after cursor — no effect
19
18
  break;
20
19
  }
21
20
  if (end <= cursorOffset) {
22
- // Edit is entirely before cursor — shift by delta.
23
21
  // Range is half-open [start, end), so cursor at `end` is outside the edit.
24
22
  newOffset += delta;
25
23
  }
26
24
  else {
27
- // Cursor falls inside the replaced range [start, end)
28
25
  newOffset = start + edit.text.length;
29
26
  break;
30
27
  }
@@ -19,20 +19,18 @@ export function applyFixes(sourceCode, fixes) {
19
19
  if (fixes.length === 0) {
20
20
  return { output: sourceCode, applied: [], skipped: [], appliedEdits: [] };
21
21
  }
22
- // Tag each edit with its parent FixData index
23
22
  const taggedEdits = [];
24
23
  for (const [i, fix] of fixes.entries()) {
25
24
  for (const edit of fix.edits) {
26
25
  taggedEdits.push({ edit, fixIndex: i });
27
26
  }
28
27
  }
29
- // Sort: range[0] ascending, then range[1] descending (so larger ranges come first at the same start)
28
+ // Ties broken by range[1] descending so larger ranges come first at the same start.
30
29
  taggedEdits.sort((a, b) => {
31
30
  const startDiff = a.edit.range[0] - b.edit.range[0];
32
31
  // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
33
32
  return startDiff || b.edit.range[1] - a.edit.range[1];
34
33
  });
35
- // Track which FixData indices had at least one skipped edit
36
34
  const skippedFixIndices = new Set();
37
35
  const appliedEdits = [];
38
36
  let lastAppliedEnd = -1;
@@ -40,22 +38,18 @@ export function applyFixes(sourceCode, fixes) {
40
38
  let cursor = 0;
41
39
  for (const { edit, fixIndex } of taggedEdits) {
42
40
  const [start, end] = edit.range;
43
- // Overlap check: if this edit starts before the end of the last applied edit, skip it.
44
- // Also skip if a sibling edit from the same FixData was already skipped —
45
- // edits within a single FixData are atomic (all-or-nothing).
41
+ // Edits within a single FixData are atomic (all-or-nothing): if any sibling
42
+ // was skipped, skip the rest.
46
43
  if (start < lastAppliedEnd || skippedFixIndices.has(fixIndex)) {
47
44
  skippedFixIndices.add(fixIndex);
48
45
  continue;
49
46
  }
50
- // Append the source text between the last edit and this one
51
47
  parts.push(sourceCode.slice(cursor, start), edit.text);
52
48
  appliedEdits.push(edit);
53
49
  cursor = end;
54
50
  lastAppliedEnd = end;
55
51
  }
56
- // Append remaining source text
57
52
  parts.push(sourceCode.slice(cursor));
58
- // Classify FixData as applied or skipped
59
53
  const applied = [];
60
54
  const skipped = [];
61
55
  for (const [i, fix] of fixes.entries()) {
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
  */
@@ -22,6 +36,20 @@ export type FixSummary = {
22
36
  * multiple passes are executed.
23
37
  */
24
38
  readonly firstPassEdits: readonly TextEdit[];
39
+ /**
40
+ * Violations remaining in the final fixed code, re-verified after the
41
+ * last fix pass.
42
+ *
43
+ * Unlike {@link VerifyResult.violations} (which reflects the first pass
44
+ * only), this list is accurate for `fixedCode`. Callers that report
45
+ * post-fix results should prefer `fixSummary.finalPassViolations ?? violations`.
46
+ * Entries may carry `fix` data whose offsets refer to `fixedCode`.
47
+ *
48
+ * `undefined` when no fixes remain applied (none were applied, or the
49
+ * applied pass was rolled back); the first-pass violations are then
50
+ * accurate as-is.
51
+ */
52
+ readonly finalPassViolations?: readonly Violation[];
25
53
  };
26
54
  /**
27
55
  * Options for {@link MLCore.verify}.
@@ -60,7 +88,7 @@ export type MLCoreParams = {
60
88
  */
61
89
  export declare class MLCore {
62
90
  #private;
63
- 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);
64
92
  /**
65
93
  * The parsed document, or a {@link ParserError} if parsing failed.
66
94
  */
@@ -77,7 +105,7 @@ export declare class MLCore {
77
105
  *
78
106
  * @param fabric - Partial fabric with the properties to update
79
107
  */
80
- update({ parser, ruleset, rules, locale, schemas, parserOptions, configErrors }: Partial<MLFabric>): void;
108
+ update({ parser, ruleset, rules, locale, schemas, parserOptions, pretenders, configErrors, ruleDeprecations, }: Partial<MLFabric>): void;
81
109
  /**
82
110
  * Runs all configured rules against the parsed document and returns violations.
83
111
  *
@@ -91,7 +119,9 @@ export declare class MLCore {
91
119
  * may be the result of multiple fix passes. This means some violations in the
92
120
  * array may already be resolved in `fixedCode`, and new violations introduced
93
121
  * during later passes are not included in the array. Callers needing an accurate
94
- * violation list for the fixed code should re-verify the output.
122
+ * violation list for the fixed code should use `fixSummary.finalPassViolations`,
123
+ * which is re-verified against the final code whenever at least one fix was
124
+ * applied.
95
125
  *
96
126
  * @param fixOrOptions - Whether to attempt auto-fixing violations, or an options object
97
127
  * @returns Violations from the initial analysis and the (possibly fixed) source code