mdrefine 0.2.0-rc.2 → 0.2.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.
Files changed (130) hide show
  1. package/CHANGELOG.md +577 -0
  2. package/CODE_OF_CONDUCT.md +30 -0
  3. package/CONTRIBUTING.md +189 -16
  4. package/README.md +100 -154
  5. package/SECURITY.md +15 -13
  6. package/config.schema.json +91 -0
  7. package/dist/cli/diff.d.ts +10 -0
  8. package/dist/cli/diff.js +247 -0
  9. package/dist/cli/diff.js.map +1 -0
  10. package/dist/cli/main.js +270 -150
  11. package/dist/cli/main.js.map +1 -1
  12. package/dist/config/load.js +67 -6
  13. package/dist/config/load.js.map +1 -1
  14. package/dist/config/problems.d.ts +7 -0
  15. package/dist/config/problems.js +208 -0
  16. package/dist/config/problems.js.map +1 -0
  17. package/dist/config/resolve.d.ts +42 -109
  18. package/dist/config/resolve.js +193 -52
  19. package/dist/config/resolve.js.map +1 -1
  20. package/dist/core/directives.d.ts +7 -0
  21. package/dist/core/directives.js +25 -13
  22. package/dist/core/directives.js.map +1 -1
  23. package/dist/core/engine.d.ts +42 -4
  24. package/dist/core/engine.js +518 -79
  25. package/dist/core/engine.js.map +1 -1
  26. package/dist/core/frozen.d.ts +6 -0
  27. package/dist/core/frozen.js +15 -0
  28. package/dist/core/frozen.js.map +1 -0
  29. package/dist/core/scope.d.ts +30 -0
  30. package/dist/core/scope.js +122 -0
  31. package/dist/core/scope.js.map +1 -0
  32. package/dist/core/types.d.ts +202 -23
  33. package/dist/core/types.js.map +1 -1
  34. package/dist/index.d.ts +2 -2
  35. package/dist/index.js.map +1 -1
  36. package/dist/node.d.ts +3 -0
  37. package/dist/node.js +4 -0
  38. package/dist/node.js.map +1 -0
  39. package/dist/rules/blocks.d.ts +34 -0
  40. package/dist/rules/blocks.js +550 -0
  41. package/dist/rules/blocks.js.map +1 -0
  42. package/dist/rules/content.d.ts +2 -0
  43. package/dist/rules/content.js +85 -0
  44. package/dist/rules/content.js.map +1 -0
  45. package/dist/rules/dialects.js +10 -6
  46. package/dist/rules/dialects.js.map +1 -1
  47. package/dist/rules/links.js +302 -6
  48. package/dist/rules/links.js.map +1 -1
  49. package/dist/rules/lists.d.ts +2 -0
  50. package/dist/rules/lists.js +924 -0
  51. package/dist/rules/lists.js.map +1 -0
  52. package/dist/rules/structure.js +127 -1
  53. package/dist/rules/structure.js.map +1 -1
  54. package/dist/rules/style.d.ts +8 -2
  55. package/dist/rules/style.js +1137 -165
  56. package/dist/rules/style.js.map +1 -1
  57. package/dist/syntax/block-identifier.d.ts +18 -0
  58. package/dist/syntax/block-identifier.js +24 -0
  59. package/dist/syntax/block-identifier.js.map +1 -0
  60. package/dist/syntax/obsidian.d.ts +29 -11
  61. package/dist/syntax/obsidian.js +9 -10
  62. package/dist/syntax/obsidian.js.map +1 -1
  63. package/dist/syntax/parse.d.ts +87 -3
  64. package/dist/syntax/parse.js +247 -19
  65. package/dist/syntax/parse.js.map +1 -1
  66. package/dist/workspace/access.d.ts +12 -3
  67. package/dist/workspace/access.js +33 -5
  68. package/dist/workspace/access.js.map +1 -1
  69. package/dist/workspace/discovery.d.ts +85 -0
  70. package/dist/workspace/discovery.js +155 -0
  71. package/dist/workspace/discovery.js.map +1 -0
  72. package/dist/workspace/encoding.d.ts +24 -0
  73. package/dist/workspace/encoding.js +113 -0
  74. package/dist/workspace/encoding.js.map +1 -0
  75. package/dist/workspace/files.d.ts +92 -6
  76. package/dist/workspace/files.js +715 -59
  77. package/dist/workspace/files.js.map +1 -1
  78. package/dist/workspace/git.d.ts +54 -0
  79. package/dist/workspace/git.js +198 -0
  80. package/dist/workspace/git.js.map +1 -0
  81. package/dist/workspace/index.d.ts +58 -3
  82. package/dist/workspace/index.js +136 -37
  83. package/dist/workspace/index.js.map +1 -1
  84. package/dist/workspace/selection.d.ts +2 -2
  85. package/dist/workspace/selection.js +3 -3
  86. package/dist/workspace/selection.js.map +1 -1
  87. package/dist/workspace/slug.js +8 -1
  88. package/dist/workspace/slug.js.map +1 -1
  89. package/dist/workspace/vault.js +3 -1
  90. package/dist/workspace/vault.js.map +1 -1
  91. package/docs/api.md +239 -0
  92. package/docs/benchmarks.md +140 -200
  93. package/docs/changelog.md +1 -0
  94. package/docs/cli.md +281 -89
  95. package/docs/configuration.md +193 -480
  96. package/docs/design.md +163 -284
  97. package/docs/dialects.md +169 -0
  98. package/docs/examples.md +151 -109
  99. package/docs/index.md +21 -37
  100. package/docs/integrations.md +144 -0
  101. package/docs/obsidian.md +91 -115
  102. package/docs/plugins.md +147 -212
  103. package/docs/quick-start.md +68 -74
  104. package/docs/rules.md +1237 -0
  105. package/docs/versions.md +56 -0
  106. package/examples/README.md +17 -14
  107. package/examples/automation/summarize-report.mjs +5 -2
  108. package/examples/library/lint-folder.mjs +5 -4
  109. package/examples/library/lint-workspace.mjs +32 -0
  110. package/examples/plugin/notes/release-checklist.md +2 -2
  111. package/examples/plugin/rules.mjs +17 -23
  112. package/examples/workspaces/obsidian-vault/after/mdtools.config.jsonc +2 -2
  113. package/examples/workspaces/obsidian-vault/before/mdtools.config.jsonc +2 -2
  114. package/examples/workspaces/repository-docs/after/README.md +2 -2
  115. package/examples/workspaces/repository-docs/after/mdtools.config.jsonc +0 -2
  116. package/examples/workspaces/repository-docs/before/README.md +2 -2
  117. package/examples/workspaces/repository-docs/before/docs/guide.md +7 -7
  118. package/examples/workspaces/repository-docs/before/docs/reference.md +3 -1
  119. package/examples/workspaces/repository-docs/before/mdtools.config.jsonc +0 -2
  120. package/package.json +38 -12
  121. package/docs/contributing.md +0 -218
  122. package/docs/releases/0.1.0-beta.1.md +0 -39
  123. package/docs/releases/0.1.0-beta.2.md +0 -83
  124. package/docs/releases/0.1.0-beta.3.md +0 -61
  125. package/docs/releases/0.1.0-beta.4.md +0 -50
  126. package/docs/releases/0.1.0-rc.1.md +0 -99
  127. package/docs/releases/0.2.0-rc.1.md +0 -141
  128. package/docs/releases/0.2.0-rc.2.md +0 -225
  129. package/docs/releases.md +0 -144
  130. package/docs/testing.md +0 -93
@@ -1,141 +0,0 @@
1
- # mdrefine 0.2.0-rc.1
2
-
3
- First release candidate of the 0.2 feature release of Markdown Tools. npm
4
- package: `mdrefine`; executable: `mdtools`. Requires Node.js 22.12 or newer.
5
- Upgrade with:
6
-
7
- ```sh
8
- npm install --save-dev --save-exact mdrefine@0.2.0-rc.1
9
- ```
10
-
11
- Changes below are relative to `0.1.0-rc.1`. Release candidates use npm's `rc`
12
- channel, and `latest` follows the newest prerelease until the first stable
13
- release.
14
-
15
- ## Forgejo, Codeberg, and Gitea support
16
-
17
- New `forgejo` and `gitea` dialects and presets support documents hosted on those
18
- forges. `codeberg` is an alias for `forgejo`, accepted in configuration,
19
- presets, overrides, and `--dialect`; rules and plugins receive the canonical
20
- name `forgejo`. Gitea is a separate dialect because its heading anchors and
21
- emphasis behavior differ from Forgejo's. Example configurations are included in
22
- `examples/forgejo.jsonc` and `examples/gitea.jsonc`
23
- ([PR #73](https://github.com/viell-dev/slop-markdown-tools/pull/73) and
24
- [PR #79](https://github.com/viell-dev/slop-markdown-tools/pull/79)).
25
-
26
- Both presets enable `github/alert-marker`, which normalizes known alert types
27
- such as `[!note]` to `[!NOTE]`, along with task-marker and table formatting.
28
-
29
- Both dialects protect definition lists, backslash-delimited math, and shortlinks
30
- from formatting that would change how they render. One-line `\(...\)` math and
31
- `[[...]]` shortlinks stay together; paragraphs with display-math lines,
32
- definition descriptions, or pairs spanning lines are left unreflowed. Inline
33
- rules also preserve backslash math. Gitea additionally protects its `_.py`
34
- emphasis exception, so formatting does not turn literal `__init__.py` into bold
35
- text. Shortlinks are preserved, not resolved as links. On instances configured
36
- to render soft line breaks as hard breaks, disable `style/wrap`.
37
-
38
- ## More accurate fragment validation
39
-
40
- `links/valid` now follows the renderer's heading and HTML-anchor behavior:
41
-
42
- - Forgejo and Gitea recognize trailing heading attributes such as
43
- `## Install {#setup}`. A custom `id` replaces the generated anchor; class-only
44
- blocks are left out of the generated text
45
- ([PR #86](https://github.com/viell-dev/slop-markdown-tools/pull/86)).
46
- - Forgejo and Gitea before 1.26 generate anchors from the heading's last text
47
- line as written, including emphasis markers and link destinations. Gitea 1.26
48
- and later use the rendered text of all its lines. The Gitea dialect accepts
49
- both generations' anchors
50
- ([PR #100](https://github.com/viell-dev/slop-markdown-tools/pull/100) and
51
- [PR #108](https://github.com/viell-dev/slop-markdown-tools/pull/108)).
52
- - Inline HTML in Markdown headings contributes text without ordinary tags and
53
- comments on GitHub and newer Gitea, while tags filtered into visible text
54
- still contribute to the anchor
55
- ([PR #85](https://github.com/viell-dev/slop-markdown-tools/pull/85) and
56
- [PR #108](https://github.com/viell-dev/slop-markdown-tools/pull/108)).
57
- - Explicit HTML anchors, the `id` of an element and the `name` of an `<a>`, are
58
- recognized on GitHub, Forgejo, and Gitea. HTML comments, code, and raw-text
59
- contents such as `<script>` and `<textarea>` do not create anchors
60
- ([PR #104](https://github.com/viell-dev/slop-markdown-tools/pull/104)).
61
- - Headings written as HTML (`<h2>Title</h2>`) get generated anchors on GitHub
62
- and Gitea 1.26 and later. GitHub numbers repeated HTML and Markdown headings
63
- together; newer Gitea does not number them, and an HTML heading with its own
64
- `id` gets no generated anchor
65
- ([PR #105](https://github.com/viell-dev/slop-markdown-tools/pull/105)).
66
- - Fragments with one leading `user-content-` prefix are accepted on GitHub,
67
- Forgejo, and Gitea. GitHub also matches fragments without regard to case;
68
- Forgejo and Gitea remain case-sensitive. CommonMark follows GitHub's anchor
69
- rules; Obsidian keeps its existing behavior
70
- ([PR #103](https://github.com/viell-dev/slop-markdown-tools/pull/103) and
71
- [PR #106](https://github.com/viell-dev/slop-markdown-tools/pull/106)).
72
-
73
- Correct fragments previously reported as missing can now resolve, allowing
74
- `links/path` to rewrite their paths. Links to anchors that the renderer does not
75
- generate can now be reported as missing.
76
-
77
- ## Preserve heading attributes and anchors
78
-
79
- On Forgejo and Gitea, formatting now keeps heading attribute blocks intact and
80
- preserves anchors derived from a heading's source. Marker and path rules leave
81
- the last text line unchanged unless a custom `id` makes its generated anchor
82
- irrelevant; attribute text itself remains protected. Multiline code spans and
83
- Setext-to-ATX conversions also preserve attribute interpretation. The semantic
84
- safety check refuses edits from any rule or plugin that change a heading's
85
- attribute block or move its generated anchors
86
- ([PR #99](https://github.com/viell-dev/slop-markdown-tools/pull/99) and
87
- [PR #101](https://github.com/viell-dev/slop-markdown-tools/pull/101)).
88
-
89
- The new `forgejo/heading-id` problem rule reports non-text heading IDs such as
90
- `{id=5}`. Such IDs can make Forgejo and older Gitea fail to render the document;
91
- newer Gitea renders the heading without an anchor. The `forgejo`, `codeberg`,
92
- and `gitea` presets enable the rule as an error. It suggests quoting the value
93
- and proposes no edit
94
- ([PR #107](https://github.com/viell-dev/slop-markdown-tools/pull/107)).
95
-
96
- ## Parsing and performance
97
-
98
- GFM documents containing URLs found only by GitHub's later autolink transform,
99
- such as `[www.example.com]`, no longer fail formatting with
100
- `Missing source position for text`. Literal autolinks now come from the syntax
101
- extension alone. Built-in formatting is unchanged, but plugins inspecting link
102
- nodes no longer see those transform-only autolinks; ordinary URL and email
103
- autolinks remain available
104
- ([PR #73](https://github.com/viell-dev/slop-markdown-tools/pull/73)).
105
-
106
- The workspace now computes and caches target anchors only for the dialects
107
- needed by fragment checks. GitHub and Obsidian workspaces avoid the extra parse
108
- for Forgejo/Gitea heading attributes and their unused anchor calculations;
109
- fragment-validation results are unchanged
110
- ([PR #109](https://github.com/viell-dev/slop-markdown-tools/pull/109)).
111
-
112
- ## Compatibility and verification
113
-
114
- Existing `0.1.0-rc.1` configurations remain accepted, and the Node.js minimum is
115
- unchanged. The public `Dialect` type adds `forgejo` and `gitea`; `DialectName`
116
- also accepts `codeberg` for configuration input. The library adds `dialects`,
117
- `dialectAliases`, and `canonicalDialect` exports. Hosts and plugins with
118
- exhaustive dialect handling should include the new canonical names. The API and
119
- configuration remain provisional until the first stable release.
120
-
121
- `Config.dialect` and `Override.dialect` now use `DialectName`, so hosts that
122
- pass raw configuration values to an API requiring `Dialect` must canonicalize
123
- them with `canonicalDialect()` first. `resolveConfig()` already returns a
124
- canonical dialect. The configuration schema accepts the new names and alias.
125
-
126
- The Gitea dialect covers 1.21 and later and accepts anchors from both sides of
127
- the 1.26 renderer change; it does not guarantee that a fragment accepted for one
128
- version exists on every version. Heading attribute blocks follow the rules used
129
- by Forgejo 16 and Gitea 1.26 and later. Older Gitea attribute forms, attribute
130
- values nested more than 64 levels, and some raw-text, footnote, and character
131
- reference cases remain unmodeled. See [design and limitations](../design.md) for
132
- the detailed boundaries.
133
-
134
- Runtime dependencies now include `ignore@7.0.12`, `micromark-util-types@2.0.3`,
135
- and `string-width@8.3.0`; `decode-named-character-reference@1.3.0` is a direct
136
- dependency for HTML heading text. Development tools have also been updated.
137
- Regression coverage now includes the new dialects, renderer-specific anchors,
138
- preserved heading attributes, HTML tokenization, and dialect-specific lazy
139
- indexing. The wrapping performance test has a longer timeout to tolerate slow
140
- Windows CI runners; its linear-growth assertion is unchanged
141
- ([PR #84](https://github.com/viell-dev/slop-markdown-tools/pull/84)).
@@ -1,225 +0,0 @@
1
- # mdrefine 0.2.0-rc.2
2
-
3
- Second release candidate of the 0.2 feature release of Markdown Tools. npm
4
- package: `mdrefine`; executable: `mdtools`. Requires Node.js 22.12 or newer.
5
- Upgrade with:
6
-
7
- ```sh
8
- npm install --save-dev --save-exact mdrefine@0.2.0-rc.2
9
- ```
10
-
11
- Changes below are relative to `0.2.0-rc.1`. Release candidates use npm's `rc`
12
- channel, and `latest` follows the newest prerelease until the first stable
13
- release.
14
-
15
- ## Check before upgrading
16
-
17
- Most of this release makes the tool more careful, but five changes can alter
18
- what an existing setup does:
19
-
20
- - **The dialect assumed when none is named.** A workspace without a
21
- configuration file, or with one that names no dialect, was read as CommonMark.
22
- It is now read as GitHub Markdown, and documents inside an Obsidian vault as
23
- Obsidian notes. Name `"dialect": "commonmark"` to keep the old reading.
24
- - **What counts as `$` math.** Two sums of money in a paragraph are no longer
25
- taken for a formula. Text that was left alone because of that is now wrapped
26
- and restyled like other prose.
27
- - **Messages on stderr.** The `lint` summary, the messages for paths and
28
- configuration files that cannot be used, and the messages for plugins that
29
- cannot be loaded are worded differently. Exit codes and `--json` output keep
30
- their meaning; a script should read those.
31
- - **Plugin packages with two entries.** A plugin package that declares both an
32
- `import` and a `require` entry is now loaded through `import`.
33
- - **Library hosts.** A source loader given to `createWorkspace` can be called
34
- more than once for the same file, and link resolutions have a new status and
35
- new fields. See [compatibility](#compatibility-and-verification).
36
-
37
- A configuration that names its dialect, as the documentation has always
38
- recommended, formats and lints the same documents as before. On a large
39
- real-world Obsidian vault of several thousand notes, `0.2.0-rc.1` and this
40
- version gave the same result for every file.
41
-
42
- ## A safer reading when no dialect is named
43
-
44
- In CommonMark a table, or a run of footnote definitions, is an ordinary
45
- paragraph, so formatting without a configuration joined their lines, and in a
46
- vault it joined lines that Obsidian shows separately and could break a wikilink
47
- in two. When nothing names a dialect, the tool now assumes `github`, whose
48
- syntax the Forgejo, Gitea, and Obsidian dialects build on, and `obsidian` for a
49
- document inside a vault
50
- ([PR #130](https://github.com/viell-dev/slop-markdown-tools/pull/130)).
51
-
52
- Only the dialect is assumed. The rules of the `github` and `obsidian` presets
53
- still need the preset. Library callers get `github` as the default of `lint`,
54
- `format`, `resolveConfig`, and `createWorkspace`, and can pass `defaultDialect`
55
- to say what to assume without overriding a dialect that the configuration names.
56
-
57
- ## Obsidian vaults wherever they are
58
-
59
- A vault is recognized by its `.obsidian` folder, and a document belongs to the
60
- nearest vault at or above its own folder
61
- ([PR #138](https://github.com/viell-dev/slop-markdown-tools/pull/138)):
62
-
63
- - A vault in a folder of a larger workspace, such as `docs/vault/` in a
64
- repository, is read in the Obsidian dialect while the documents around it stay
65
- GitHub Markdown.
66
- - A folder of a vault used as the workspace root finds the vault above it.
67
- - A repository checked out inside a vault is not read as the vault's notes.
68
- - Whether paragraphs may be reflowed is read from each vault's own
69
- `.obsidian/app.json`, so vaults with different "Strict line breaks" settings
70
- can share a workspace.
71
-
72
- Links follow the vault as well. In a vault below the workspace root, an Obsidian
73
- link reaches only the vault's files, by paths counted from the vault's folder,
74
- and `links/path` writes `"style": "root"` paths from there. A path that leads
75
- out of the vault to an existing file is reported as
76
- `Local target is outside the vault`
77
- ([PR #146](https://github.com/viell-dev/slop-markdown-tools/pull/146)).
78
-
79
- When the workspace root is only a folder of a vault, the tool no longer takes
80
- the folder for the whole vault. `0.2.0-rc.1` could shorten a link with
81
- `"style": "shortest"` until it named a different note, and called every note
82
- outside the folder missing. A link whose target the rest of the vault could
83
- hold, or outdo, is now left as written and reported as
84
- `Local target could not be checked`; explicit relative paths are still certain
85
- and rewritten
86
- ([PR #147](https://github.com/viell-dev/slop-markdown-tools/pull/147)).
87
-
88
- Two things that stopped every command now do not: a file named `.obsidian`,
89
- which is ignored, and an `.obsidian/app.json` that is not valid JSON, which
90
- leaves the line-break setting unverified with a warning.
91
-
92
- ## Paths that cannot be read
93
-
94
- A directory that the system does not permit the tool to read no longer stops the
95
- run. It is skipped with one warning, the rest of the workspace is processed, and
96
- a link into it is reported as `Local target could not be checked`, not as
97
- missing. A selected document that cannot be read is reported with an
98
- `engine/unreadable-file` error for that file; the others are processed, nothing
99
- is written, and the exit code is `2`. With `--json`, skipped paths are listed
100
- under `skipped`
101
- ([PR #133](https://github.com/viell-dev/slop-markdown-tools/pull/133)).
102
-
103
- ## Dollar math follows the renderer
104
-
105
- Text between two `$` signs was read as math in every dialect but CommonMark, so
106
- a sentence such as `Costs $5 *per* item and $6 *per* box.` had part of its text
107
- exempt from style rules, and a paragraph with two amounts far apart could not be
108
- wrapped between them. Each dialect now applies the conditions that its renderer
109
- was observed to apply
110
- ([PR #150](https://github.com/viell-dev/slop-markdown-tools/pull/150) and
111
- [PR #164](https://github.com/viell-dev/slop-markdown-tools/pull/164)):
112
-
113
- - On GitHub, Forgejo, and Gitea, the opening `$` may not follow a letter or
114
- digit, and the next `$` may not be followed by a letter, a digit, or `_`.
115
- GitHub also wants a single `$` to touch its formula.
116
- - In Obsidian, the opening `$` may not be followed by a space, and a `$` closes
117
- the formula only if no space stands before it and no digit follows it.
118
- Obsidian's Reading view and Live Preview differ in two cases; the tool follows
119
- the one that shows more as a formula.
120
-
121
- `From $5 to 10$` is a formula to all four renderers and stays one for the tool.
122
- Display math is unchanged everywhere. The conditions come from about 150 cases
123
- rendered by the renderers themselves, which are now part of the tests.
124
-
125
- ## Plugins
126
-
127
- - A plugin named as a package is resolved the way Node.js resolves an `import`
128
- written in the configuration file, with a fallback to its CommonJS rules. A
129
- package that declares only an `import` entry now loads
130
- ([PR #125](https://github.com/viell-dev/slop-markdown-tools/pull/125)).
131
- - Conditions set when Node.js is started, with `--conditions` or `--no-addons`
132
- on its command line or in `NODE_OPTIONS`, apply to that lookup
133
- ([PR #144](https://github.com/viell-dev/slop-markdown-tools/pull/144)).
134
- - A plugin that cannot be loaded is reported as
135
- `Cannot load plugin "NAME" named in FILE: REASON`, and one without a usable
136
- default export as `Invalid plugin "NAME" named in FILE`. A plugin named by a
137
- path where no file is gets the reason `no file at PATH`.
138
- - The configuration reference describes the `plugins` key, and the plugin guide
139
- describes how a rule resolves a link: the call, the statuses, and the fields
140
- of the result
141
- ([PR #158](https://github.com/viell-dev/slop-markdown-tools/pull/158)).
142
-
143
- ## Clearer messages
144
-
145
- - `lint` ends with a count of what it reported, as in
146
- `3 file(s) linted; 1 error(s), 2 warning(s).` It used to end with
147
- `0 would change`, whatever it found.
148
- - A path given on the command line that does not exist, is of the wrong kind, or
149
- may not be read is answered in the tool's words, such as
150
- `Workspace root does not exist: …`, `Configuration file cannot be read: …`,
151
- `Input does not exist: …`, or `Excluded path cannot be read: …`, where the
152
- system's raw message used to appear.
153
- - An error in a configuration file names the file
154
- ([PR #143](https://github.com/viell-dev/slop-markdown-tools/pull/143)).
155
-
156
- ## Memory, speed, and installation size
157
-
158
- - The link index keeps the anchors of each linked document, not its parsed form.
159
- Linting a large real-world vault needed about half the memory
160
- ([PR #135](https://github.com/viell-dev/slop-markdown-tools/pull/135)).
161
- - For the Obsidian dialect, the tables for finding a note by name held about 1.6
162
- kB for every file of the workspace, attachments included. They now hold about
163
- 70 bytes per file
164
- ([PR #149](https://github.com/viell-dev/slop-markdown-tools/pull/149)).
165
- - The package no longer installs KaTeX, which the tool never used: 4.6 MB less
166
- on disk, a faster start, and no KaTeX advisory in a consumer's `npm audit`.
167
- The math tokenizer is now the project's own, adapted from
168
- `micromark-extension-math`; its license notice ships as `THIRD_PARTY_NOTICES`
169
- ([PR #150](https://github.com/viell-dev/slop-markdown-tools/pull/150)).
170
- - A document that is one very long list parses in about half the time, through
171
- an update of the syntax-tree builder
172
- ([PR #155](https://github.com/viell-dev/slop-markdown-tools/pull/155)).
173
-
174
- The [benchmark page](../benchmarks.md) has new reference results and states two
175
- limits of the parser that were measured for this release: one document needs
176
- about 70 to 130 times its size in memory while it is parsed, and a single
177
- paragraph of 100 kB or more that is full of inline constructs parses slowly.
178
-
179
- ## Examples, benchmarks, and documentation
180
-
181
- The package now ships working examples: starting configurations, workspaces
182
- before and after formatting, a plugin, and library scripts, described on the
183
- [examples page](../examples.md). `npm run benchmark` measures the tool on
184
- generated documents. The tests are split into a unit suite and an integration
185
- suite that runs the built command line on real files and checks the examples and
186
- the documentation against the tool
187
- ([PR #111](https://github.com/viell-dev/slop-markdown-tools/pull/111)). Code
188
- blocks on the documentation site fit 80 columns
189
- ([PR #129](https://github.com/viell-dev/slop-markdown-tools/pull/129)).
190
-
191
- ## Compatibility and verification
192
-
193
- Existing `0.2.0-rc.1` configurations remain accepted, and the Node.js minimum is
194
- unchanged. The API and configuration remain provisional until the first stable
195
- release.
196
-
197
- For library hosts:
198
-
199
- - `lint`, `format`, and `resolveConfig` accept `defaultDialect`. `resolveConfig`
200
- takes it as its fourth argument.
201
- - `WorkspaceOptions` adds `unreadable`, `vaults`, and `rootInVault`.
202
- - `LinkResolution` adds the status `unreadable` and the fields `unreadable`,
203
- `vault`, `rooted`, and `outside`. A rule must not rewrite a resolved link
204
- whose `unreadable` field is set; the built-in rules do not, and the engine
205
- refuses an edit that respells such a link.
206
- - A Markdown source given as a loader function can be called again when a later
207
- link to the same file is checked for a dialect with different anchors. It was
208
- called at most once before. Loaders must return the same text each time.
209
- - A loader that throws an error with the code `EACCES` or `EPERM` marks the file
210
- as unreadable instead of failing the run.
211
-
212
- Runtime dependencies: `import-meta-resolve@4.2.0`,
213
- `micromark-factory-space@2.1.0`, and `micromark-util-character@2.1.1` are new
214
- direct dependencies; `micromark-extension-math` is gone, and with it `katex`;
215
- `mdast-util-from-markdown` is `2.1.0`. Development tools have also been updated.
216
-
217
- Known limits that this release documents and does not remove: GitHub accepts an
218
- escaped `\$` as the start of a formula and the tool does not; a workspace root
219
- inside a vault cannot check links to notes outside it; and the two parser limits
220
- named above. See [design and limitations](../design.md) for the detailed
221
- boundaries.
222
-
223
- The release was checked with 902 automated tests on Linux and Windows, with the
224
- installed package on all three CI targets, and by comparing reports before and
225
- after on a large real-world vault.
package/docs/releases.md DELETED
@@ -1,144 +0,0 @@
1
- # Releases
2
-
3
- ## Versions and availability
4
-
5
- These documents cover `mdrefine@0.2.0-rc.2`. The executable is `mdtools`;
6
- prereleases use the npm channel named after their prerelease identifier, `rc`
7
- for release candidates and `beta` for betas. Read the
8
- [0.2.0-rc.2 release notes](releases/0.2.0-rc.2.md) for changes and limitations.
9
- Previous releases: [0.2.0-rc.1](releases/0.2.0-rc.1.md),
10
- [0.1.0-rc.1](releases/0.1.0-rc.1.md), [beta.4](releases/0.1.0-beta.4.md),
11
- [beta.3](releases/0.1.0-beta.3.md), [beta.2](releases/0.1.0-beta.2.md), and
12
- [beta.1](releases/0.1.0-beta.1.md).
13
-
14
- The registry is the source of truth for package availability:
15
-
16
- ```sh
17
- npm view mdrefine@0.2.0-rc.2 version --registry=https://registry.npmjs.org/
18
- ```
19
-
20
- An `E404` means the requested package or version is unavailable. A version in
21
- this repository or its documentation does not imply publication. Check
22
- [GitHub releases](https://github.com/viell-dev/slop-markdown-tools/releases) for
23
- release announcements and downloadable artifacts.
24
-
25
- The npm package is published under account `viell`. Until the first stable
26
- release, `latest` points to the newest prerelease of any kind, alongside its
27
- channel tag such as `rc` or `beta`, so default installations receive fixes. Once
28
- a stable release exists, `latest` follows stable releases and prerelease channel
29
- tags remain separate.
30
-
31
- ## Prepare without publishing
32
-
33
- Use Node.js 24 and npm 10 or newer from a clean checkout:
34
-
35
- ```sh
36
- npm ci
37
- npm run release:prepare
38
- npm publish ./artifacts/mdrefine-0.2.0-rc.2.tgz --dry-run --ignore-scripts --access public --tag rc
39
- ```
40
-
41
- Preparation runs all checks, packs the allowlisted files, installs that exact
42
- tarball into a temporary consumer, exercises the installed command and library,
43
- and compiles a TypeScript consumer. It retains the tested tarball, file
44
- manifest, and SHA-256 checksum in ignored `artifacts/`. No registry upload, Git
45
- tag, or GitHub release occurs. Local artifacts must be regenerated after any
46
- change.
47
-
48
- The manual **Release** GitHub Actions workflow performs the same checks plus a
49
- dependency audit and uploads the artifact for 14 days. Leave `publish` false to
50
- prepare only. CI runs full checks on Linux/Node.js 24, compatibility tests on
51
- Linux/Node.js 22 and Windows/Node.js 24, and installed-package checks on all
52
- three targets.
53
-
54
- ## Publication prerequisites
55
-
56
- Publication requires explicit authorization from the repository owner for each
57
- release. Preparing a PR or artifact does not supply that authorization. For
58
- subsequent releases, verify these prerequisites rather than repeating the
59
- completed bootstrap:
60
-
61
- 1. Merge the release PR with all required checks passing. Review the tarball
62
- manifest, release notes, version, and registry name again.
63
- 2. Arrange npm account access, verified email, and required two-factor
64
- authentication. Verify the intended account with `npm whoami`. Bootstrap
65
- publication may need an authenticated local publish before package settings
66
- are available for trusted publishing.
67
- 3. Configure npm's
68
- [trusted publisher](https://docs.npmjs.com/trusted-publishers/) for user
69
- `viell-dev`, repository `slop-markdown-tools`, workflow `release.yml`, and
70
- environment `npm-release`. Allow direct `npm publish`. No long-lived npm
71
- token is stored in GitHub.
72
- 4. Restrict the GitHub `npm-release` environment to `main` and configure an
73
- approval gate if an independent approver is available. Verify branch rules
74
- still require PRs and the three CI checks. The workflow uses Node.js 24 and
75
- checks that npm supports trusted publishing.
76
- 5. Repository variable `NPM_PUBLISH_ENABLED` is `true` after verified trusted
77
- publisher setup. This enables the workflow's capability; it does not
78
- authorize a release. Preparation uses `publish: false` regardless of this
79
- variable's value.
80
-
81
- Trusted-publisher settings were verified on 2026-09-18. The first release used
82
- local authentication and has no OIDC provenance. For workflow releases, verify
83
- the publication job and the registry provenance attestations after each release.
84
-
85
- ## Publish an authorized prerelease
86
-
87
- Dispatch **Release** on `main` with the exact package version, `publish: true`,
88
- and the actual publishing agent's identity as `model via harness`. The workflow
89
- builds and checks the package again, verifies the artifact checksum, publishes
90
- that tarball to the npm channel matching its prerelease identifier (`rc` or
91
- `beta`) with provenance, and creates a GitHub prerelease at the workflow's
92
- commit. Tags use exact versions without a `v` prefix. Stable publication
93
- deliberately needs a separate policy change; this workflow accepts only beta and
94
- rc versions and derives the channel tag from the version. Complete the npm tag
95
- synchronization below before reporting a pre-stable release complete.
96
-
97
- For an authenticated first publication that cannot use OIDC yet, use the exact
98
- reviewed tarball with `npm publish <tarball> --ignore-scripts --access public
99
- --tag beta` only after authorization. Then create the matching GitHub
100
- prerelease at the exact source commit, attach the tarball and checksum, and use
101
- the reviewed notes with the actual publishing agent attribution. Complete npm
102
- trusted publisher setup afterward.
103
-
104
- If npm succeeds but GitHub release creation fails, do not republish or bump the
105
- version blindly. Verify the published package integrity against the retained
106
- artifact and finish only the missing GitHub step at the same commit. Published
107
- versions, tags, and release assets must never be overwritten; corrections use a
108
- new version. The workflow refuses an existing npm version or tag to make a
109
- partial release visible instead of silently accepting it.
110
-
111
- GitHub enforces immutability for future releases and their assets. Attach all
112
- assets before publishing a release. The existing beta.1 release predates that
113
- setting, so its assets are not retroactively locked; its version tag remains
114
- protected by the repository ruleset. Do not replace its assets or recreate the
115
- release to change that history.
116
-
117
- ## Synchronize npm tags before the first stable release
118
-
119
- After each authorized prerelease publication, wait for npm processing to finish
120
- and verify that the channel tag (`rc` today) points to the expected version.
121
- Until the first stable release, move `latest` to that same version using an
122
- authenticated local npm session. For the current release candidate:
123
-
124
- ```sh
125
- npm_config_cache="$PWD/.npm-cache" npm dist-tag add mdrefine@0.2.0-rc.2 latest
126
- npm_config_cache="$PWD/.npm-cache" npm dist-tag ls mdrefine
127
- ```
128
-
129
- Use the exact newly published version on future releases. npm's
130
- [OIDC authentication](https://docs.npmjs.com/trusted-publishers/) supports
131
- publication, but does not authenticate `dist-tag` updates. The Release workflow
132
- records this required follow-up in its summary; complete browser authentication
133
- locally if npm requests it. Keep the waiting command alive and never put
134
- authentication secrets in chat or repository files.
135
-
136
- Tag synchronization is part of an authorized prerelease. It does not publish
137
- another version or change package contents. If promotion fails, retry only the
138
- tag update after resolving authentication; never rerun publication. Stop
139
- promoting prereleases to `latest` when the first stable release is published.
140
-
141
- Verify both tags, a fresh default installation, the GitHub release and its
142
- assets, registry provenance, and the documentation site before reporting the
143
- release complete. All subsequent changes, including prerelease maintenance,
144
- continue through PRs.
package/docs/testing.md DELETED
@@ -1,93 +0,0 @@
1
- # Testing
2
-
3
- The tests are split by what they exercise. Unit tests call the library's source
4
- directly. Integration tests run the built command-line tool and library the way
5
- a consumer does: as a separate process, against real files.
6
-
7
- ```sh
8
- npm test # build, then run both suites
9
- npm run test:unit # library behavior only; needs no build
10
- npm run test:integration # build, then the CLI, examples, and documentation
11
- npm run test:package # pack, install into a temporary project, and use it
12
- ```
13
-
14
- The two suites run one after the other, never at the same time: integration
15
- tests start many processes, and that load would make the time limits of a few
16
- unit tests unreliable. `npm run check` runs both suites after the type, lint,
17
- formatting, and documentation-site checks. GitHub Actions runs them on Linux
18
- with Node.js 22 and 24 and on Windows with Node.js 24.
19
-
20
- ## Unit tests
21
-
22
- `tests/unit/` imports from `src/` and touches neither the filesystem nor other
23
- processes. A test formats or lints a string and checks the result, usually
24
- together with the contracts every formatting change must keep: the output is
25
- stable when formatted again, the parsed meaning is unchanged, and disabling the
26
- rule leaves the source as written.
27
-
28
- | File | Covers |
29
- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
30
- | `engine.test.ts` | Edit application, formatting phases, safety checks, configuration, plugins |
31
- | `rules.test.ts` | Each built-in style and problem rule, per dialect |
32
- | `wrap.test.ts` | Prose wrapping, including property-based tests and a linear-time check |
33
- | `callout-wrap.test.ts` | Wrapping inside Obsidian callouts |
34
- | `links.test.ts` | Link and fragment resolution for every dialect, including generated anchors and unreadable paths |
35
- | `structure.test.ts` | Document structure rules |
36
- | `math.test.ts` | Where dollar math begins and ends in each dialect, compared with what GitHub, Forgejo, and Gitea rendered (`math-renderers.ts`) |
37
-
38
- A defect in how a rule reads or rewrites Markdown belongs here, as the smallest
39
- synthetic document that shows it.
40
-
41
- ## Integration tests
42
-
43
- `tests/integration/` runs `dist/cli/main.js` as a child process in temporary
44
- workspaces, and runs the files under `examples/` and `benchmarks/` as they are.
45
- These tests catch what unit tests cannot: file discovery, configuration loading,
46
- exit codes, output streams, line endings and file names on disk, and
47
- documentation that no longer matches the tool.
48
-
49
- | File | Covers |
50
- | -------------------- | ------------------------------------------------------------------------------------------------------------------- |
51
- | `cli.test.ts` | Commands, flags, exit codes, discovery, ignore rules, the assumed dialect, and write safeguards |
52
- | `workflows.test.ts` | Whole tasks: mixed-dialect workspaces, CRLF files, non-ASCII paths, JSON reports, plugin loading |
53
- | `examples.test.ts` | Every example: configurations load, `before/` formats into `after/`, scripts print what is shown |
54
- | `docs.test.ts` | Documentation against the code: rule and preset tables, configuration snippets, the examples page, code block width |
55
- | `benchmarks.test.ts` | The benchmark suite runs, and its synthetic documents format cleanly |
56
-
57
- `support.ts` holds the shared helpers: `fixture()` writes a temporary workspace
58
- that is removed after the test, `copyOf()` copies a folder of the repository
59
- somewhere a test may write, and `run()` starts the CLI. `restrict()` takes a
60
- path's permissions away until the test ends. Tests that need an unreadable path
61
- are skipped on Windows and for the root user, where permissions cannot be taken
62
- away; `links.test.ts` covers the library's part everywhere, by telling the
63
- workspace which paths are unreadable.
64
-
65
- A defect in how the tool behaves as a program belongs here: which files it
66
- selects, what it prints, what it writes, and how it exits.
67
-
68
- ## Installed package check
69
-
70
- `npm run test:package` packs the package, installs the tarball into a temporary
71
- project, and then runs the installed `mdtools` command, imports the library,
72
- runs a shipped example, and compiles a TypeScript consumer against the published
73
- types. It can need access to the npm registry, so it is separate from
74
- `npm test`.
75
-
76
- ## Known defects
77
-
78
- A test marked `it.fails` reproduces a confirmed defect that is not fixed yet. It
79
- passes while the defect exists and fails once the defect is gone, which is the
80
- signal to remove the marker. Each one has a comment describing the defect and
81
- naming its issue. There are currently none.
82
-
83
- ## Speed
84
-
85
- The benchmark is not a test and never fails on a slow result, because shared CI
86
- machines vary too much for a time limit on ordinary input to be reliable.
87
- `benchmarks.test.ts` only checks that it still runs. See
88
- [benchmarks](benchmarks.md) for the measurements and how to read them.
89
-
90
- A few unit tests do guard against one kind of slowness: an algorithm whose cost
91
- grows faster than its input. They give an unusual input, such as thousands of
92
- unclosed tags, a generous time limit, or compare the time for two input sizes.
93
- Add such a test with the fix when a defect of that kind is found.