mdrefine 0.2.0-rc.2 → 0.2.0-rc.3

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 (127) hide show
  1. package/CHANGELOG.md +509 -0
  2. package/CODE_OF_CONDUCT.md +30 -0
  3. package/CONTRIBUTING.md +188 -16
  4. package/README.md +100 -154
  5. package/SECURITY.md +15 -13
  6. package/config.schema.json +91 -0
  7. package/dist/cli/main.js +261 -148
  8. package/dist/cli/main.js.map +1 -1
  9. package/dist/config/load.js +67 -6
  10. package/dist/config/load.js.map +1 -1
  11. package/dist/config/problems.d.ts +7 -0
  12. package/dist/config/problems.js +208 -0
  13. package/dist/config/problems.js.map +1 -0
  14. package/dist/config/resolve.d.ts +42 -109
  15. package/dist/config/resolve.js +193 -52
  16. package/dist/config/resolve.js.map +1 -1
  17. package/dist/core/directives.d.ts +7 -0
  18. package/dist/core/directives.js +25 -13
  19. package/dist/core/directives.js.map +1 -1
  20. package/dist/core/engine.d.ts +42 -4
  21. package/dist/core/engine.js +518 -79
  22. package/dist/core/engine.js.map +1 -1
  23. package/dist/core/frozen.d.ts +6 -0
  24. package/dist/core/frozen.js +15 -0
  25. package/dist/core/frozen.js.map +1 -0
  26. package/dist/core/scope.d.ts +30 -0
  27. package/dist/core/scope.js +122 -0
  28. package/dist/core/scope.js.map +1 -0
  29. package/dist/core/types.d.ts +202 -23
  30. package/dist/core/types.js.map +1 -1
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.js.map +1 -1
  33. package/dist/node.d.ts +3 -0
  34. package/dist/node.js +4 -0
  35. package/dist/node.js.map +1 -0
  36. package/dist/rules/blocks.d.ts +34 -0
  37. package/dist/rules/blocks.js +538 -0
  38. package/dist/rules/blocks.js.map +1 -0
  39. package/dist/rules/content.d.ts +2 -0
  40. package/dist/rules/content.js +85 -0
  41. package/dist/rules/content.js.map +1 -0
  42. package/dist/rules/dialects.js +10 -6
  43. package/dist/rules/dialects.js.map +1 -1
  44. package/dist/rules/links.js +302 -6
  45. package/dist/rules/links.js.map +1 -1
  46. package/dist/rules/lists.d.ts +2 -0
  47. package/dist/rules/lists.js +924 -0
  48. package/dist/rules/lists.js.map +1 -0
  49. package/dist/rules/structure.js +127 -1
  50. package/dist/rules/structure.js.map +1 -1
  51. package/dist/rules/style.d.ts +8 -2
  52. package/dist/rules/style.js +1118 -165
  53. package/dist/rules/style.js.map +1 -1
  54. package/dist/syntax/block-identifier.d.ts +18 -0
  55. package/dist/syntax/block-identifier.js +24 -0
  56. package/dist/syntax/block-identifier.js.map +1 -0
  57. package/dist/syntax/obsidian.d.ts +29 -11
  58. package/dist/syntax/obsidian.js +9 -10
  59. package/dist/syntax/obsidian.js.map +1 -1
  60. package/dist/syntax/parse.d.ts +74 -3
  61. package/dist/syntax/parse.js +227 -19
  62. package/dist/syntax/parse.js.map +1 -1
  63. package/dist/workspace/access.d.ts +12 -3
  64. package/dist/workspace/access.js +33 -5
  65. package/dist/workspace/access.js.map +1 -1
  66. package/dist/workspace/discovery.d.ts +80 -0
  67. package/dist/workspace/discovery.js +143 -0
  68. package/dist/workspace/discovery.js.map +1 -0
  69. package/dist/workspace/encoding.d.ts +24 -0
  70. package/dist/workspace/encoding.js +113 -0
  71. package/dist/workspace/encoding.js.map +1 -0
  72. package/dist/workspace/files.d.ts +76 -6
  73. package/dist/workspace/files.js +639 -59
  74. package/dist/workspace/files.js.map +1 -1
  75. package/dist/workspace/git.d.ts +54 -0
  76. package/dist/workspace/git.js +198 -0
  77. package/dist/workspace/git.js.map +1 -0
  78. package/dist/workspace/index.d.ts +58 -3
  79. package/dist/workspace/index.js +136 -37
  80. package/dist/workspace/index.js.map +1 -1
  81. package/dist/workspace/selection.d.ts +2 -2
  82. package/dist/workspace/selection.js +3 -3
  83. package/dist/workspace/selection.js.map +1 -1
  84. package/dist/workspace/slug.js +8 -1
  85. package/dist/workspace/slug.js.map +1 -1
  86. package/dist/workspace/vault.js +3 -1
  87. package/dist/workspace/vault.js.map +1 -1
  88. package/docs/api.md +237 -0
  89. package/docs/benchmarks.md +139 -199
  90. package/docs/changelog.md +1 -0
  91. package/docs/cli.md +271 -89
  92. package/docs/configuration.md +193 -480
  93. package/docs/design.md +158 -284
  94. package/docs/dialects.md +169 -0
  95. package/docs/examples.md +151 -109
  96. package/docs/index.md +21 -37
  97. package/docs/integrations.md +138 -0
  98. package/docs/obsidian.md +91 -115
  99. package/docs/plugins.md +147 -212
  100. package/docs/quick-start.md +68 -74
  101. package/docs/rules.md +1230 -0
  102. package/docs/versions.md +56 -0
  103. package/examples/README.md +17 -14
  104. package/examples/automation/summarize-report.mjs +5 -2
  105. package/examples/library/lint-folder.mjs +5 -4
  106. package/examples/library/lint-workspace.mjs +32 -0
  107. package/examples/plugin/notes/release-checklist.md +2 -2
  108. package/examples/plugin/rules.mjs +17 -23
  109. package/examples/workspaces/obsidian-vault/after/mdtools.config.jsonc +2 -2
  110. package/examples/workspaces/obsidian-vault/before/mdtools.config.jsonc +2 -2
  111. package/examples/workspaces/repository-docs/after/README.md +2 -2
  112. package/examples/workspaces/repository-docs/after/mdtools.config.jsonc +0 -2
  113. package/examples/workspaces/repository-docs/before/README.md +2 -2
  114. package/examples/workspaces/repository-docs/before/docs/guide.md +7 -7
  115. package/examples/workspaces/repository-docs/before/docs/reference.md +3 -1
  116. package/examples/workspaces/repository-docs/before/mdtools.config.jsonc +0 -2
  117. package/package.json +37 -11
  118. package/docs/contributing.md +0 -218
  119. package/docs/releases/0.1.0-beta.1.md +0 -39
  120. package/docs/releases/0.1.0-beta.2.md +0 -83
  121. package/docs/releases/0.1.0-beta.3.md +0 -61
  122. package/docs/releases/0.1.0-beta.4.md +0 -50
  123. package/docs/releases/0.1.0-rc.1.md +0 -99
  124. package/docs/releases/0.2.0-rc.1.md +0 -141
  125. package/docs/releases/0.2.0-rc.2.md +0 -225
  126. package/docs/releases.md +0 -144
  127. package/docs/testing.md +0 -93
package/CHANGELOG.md ADDED
@@ -0,0 +1,509 @@
1
+ # Changelog
2
+
3
+ Notable changes to mdrefine, newest first. The format follows [Keep a
4
+ Changelog](https://keepachangelog.com/en/1.1.0/), and version numbers follow the
5
+ [versioning
6
+ policy](https://viell-dev.github.io/slop-markdown-tools/versions.html). Each
7
+ release's section is also its [GitHub
8
+ release](https://github.com/viell-dev/slop-markdown-tools/releases)'s notes; the
9
+ prereleases' notes there are longer than their entries here.
10
+
11
+ ## 0.2.0-rc.3 - 2026-10-18
12
+
13
+ ### Upgrading from a prerelease
14
+
15
+ From `0.2.0-rc.2`:
16
+
17
+ - `format --write` refuses a read-only file on every platform, where Linux and
18
+ macOS used to replace it: the file gets an `engine/unwritable-file` error and
19
+ stays unchanged. Make the file writable to format it.
20
+ - One document that cannot be read or written, or that a rule was refused or
21
+ failed on, no longer keeps `format --write` from writing the others. Every
22
+ document that formatted is written, that one with the edits that were kept;
23
+ each problem is reported for its own file, and the exit code is still `2`.
24
+ Before, such a document kept every file from being written, and a file that
25
+ failed while the batch was written stopped the run. Pass `--exclude` to leave
26
+ a file alone.
27
+ - In the JSON report, `written` lists the files that were written instead of
28
+ being `true` or `false`. A script that tested it as a boolean must test its
29
+ length, because an empty list counts as true in JavaScript.
30
+ - A document that starts with a byte order mark gets its findings and edits at
31
+ the right positions; before, it could be refused or get findings in the wrong
32
+ places. In the library, `parse` now returns `document.source` without the
33
+ mark, which the tree's positions already skipped.
34
+ - `mdtools-disable-next-line` and line numbers also count a carriage return
35
+ alone as a line ending; before, such a directive could apply to the wrong
36
+ line.
37
+ - A file locked by another program on Windows (`EBUSY`) is handled like one that
38
+ may not be read, instead of stopping every command.
39
+ - A document that is not UTF-8 text gets an `engine/unreadable-file` error, and
40
+ stdin that is not stops the command with exit code `2`. Before, such text was
41
+ decoded with U+FFFD in place of what was not UTF-8, and `format --write` wrote
42
+ those characters into the file. Save such files as UTF-8.
43
+ - `format --write` writes each file into the existing file instead of replacing
44
+ it with a new one, so the file keeps its permissions, owner and group,
45
+ attributes, creation time, and hard links. Before, a replaced file lost what
46
+ Node.js cannot copy: the other names of a hard link kept the old content, and
47
+ on Windows the file's own permissions were dropped, which could let more users
48
+ read it. A crash or power failure during the write can now leave a file
49
+ incomplete; see [what writing
50
+ keeps](https://viell-dev.github.io/slop-markdown-tools/cli.html#what-writing-keeps).
51
+ - When a rule's edits would change a document's meaning, `format` keeps the
52
+ other rules' edits, so `--diff` and the library's output show them, and
53
+ reports that rule with `engine/unsafe-format` at the line where the meaning
54
+ would first differ. Before, the whole document was left unchanged. Edits of
55
+ two rules that overlap are applied in turn instead of refusing the document.
56
+ - A mistake on the command line, such as an unknown option or command or a
57
+ missing option value, exits with code `2` instead of `1`, the code for
58
+ findings, and so does `mdtools` without a command, which prints the help on
59
+ stderr.
60
+ - The text output and the diff name files from the current directory instead of
61
+ the workspace root. The JSON report keeps paths from the root and adds `root`.
62
+ - `config explain` names the configuration file `config` instead of `file`, adds
63
+ the document's `path`, and refuses a document outside the workspace. `config`
64
+ no longer accepts `--exclude`, `--json`, `--stdin-filepath`, and
65
+ `--max-warnings`, which did nothing there.
66
+ - A rule that throws or returns invalid findings is skipped for that document
67
+ with an `engine/rule-error` error, in `lint` as well, and the exit code is
68
+ `2`. Before, `lint` stopped at the first such rule, and `format` reported it
69
+ as `engine/unsafe-format`. A plugin rule with an invalid definition, such as
70
+ `phase: "Inline"`, stops the command with exit code `2` where it used to be
71
+ ignored, and a rule or preset named like a built-in property of every object,
72
+ such as `toString`, is reported as unknown.
73
+ - `recommended` warns about six more problems, listed under Added. A check that
74
+ runs `lint --max-warnings 0` fails on them until the documents are fixed or
75
+ the rules are turned off.
76
+ - `recommended` formats more, so `format --check` and `lint` report documents
77
+ that it used to accept until `format --write` runs once. It removes trailing
78
+ spaces, except hard line breaks, and repeated blank lines; writes code fences
79
+ with backticks and thematic breaks as `---`; turns underlined headings into
80
+ `#` headings and removes closing `#` sequences; and aligns tables. To keep a
81
+ form, turn its rule off or set its option, such as
82
+ `"style/heading": ["warn", { "closing": "keep" }]`.
83
+ - `.gitignore` files decide as in Git: a deeper file can include again what a
84
+ higher one excludes, and patterns match letter case exactly unless the
85
+ repository's `core.ignorecase` is on, as Git sets it on Windows and macOS.
86
+ Files that were left out before can be linted now, and the reverse.
87
+ - Git's other ignore rules apply too: `.gitignore` files above the workspace
88
+ root, `.git/info/exclude`, and the global excludes file, while a file that Git
89
+ tracks is never ignored. With `--root` on a folder of a repository, or with a
90
+ global excludes file, files that were linted before can be left out now, and a
91
+ tracked file that a pattern matches is linted.
92
+ - `.markdown` files are documents, and a file named on the command line is read
93
+ as Markdown whatever its name. A hook that passes every changed file should
94
+ pass only the Markdown ones.
95
+ - An input that does not exist and contains `*`, `?`, `[`, or `{` is a pattern,
96
+ and is an error only when it matches no document.
97
+ - `.npm-cache` is an ordinary directory, linted like any other unless
98
+ `.gitignore` or `ignore` leaves it out.
99
+ - `style/wrap` wraps more: across line breaks in links, emphasis, and code
100
+ spans, inside the text of links and emphasis, in the bodies of GitHub,
101
+ Forgejo, and Gitea alerts, and before words such as `--config` or
102
+ `**strong**`. A check that runs `format --check` fails on documents formatted
103
+ by an earlier version until `format --write` runs once.
104
+ - In the library, `resolveConfig` takes one options object,
105
+ `{ path, config, plugins, defaultDialect }`, as `lint` and `format` do, so
106
+ their options serve as they are. A call with the four separate arguments of
107
+ the prereleases throws an error that says so.
108
+ - `presets`, `builtInRules`, `dialects`, `dialectAliases`, and `configSchema`
109
+ are frozen, and a change to them throws a `TypeError`; change a copy instead.
110
+ - In the library's types, `WikiLink`, `ObsidianComment`, and `ObsidianHighlight`
111
+ replace `ObsidianLiteral`, `Rule.schema` is a `JsonSchema` instead of Ajv's
112
+ schema type, and the lists and records in `Config` are read-only: replace a
113
+ list or the `rules` of a configuration instead of changing it in place.
114
+ - `format` throws an error that the workspace throws, such as a loader's `EIO`,
115
+ as `lint` does, instead of reporting it as `engine/unsafe-format`.
116
+ - A plugin named `engine` is rejected.
117
+ - `recommended` formats lists: `*` and `+` bullets become `-`, `1)` becomes
118
+ `1.`, numbers are made consistent, and each item gets one space after its
119
+ marker and no indentation before it. `format --check` fails on lists written
120
+ otherwise until they are formatted or the list rules are turned off.
121
+ - `style/wrap` no longer joins the lines of a paragraph that has a line starting
122
+ with `:::`, `{%`, or `{{`, but lines that an earlier version joined stay
123
+ joined: split them again where a site generator reads them by line.
124
+ - A document whose front matter would end inside a code block, an HTML block, or
125
+ display math can get `engine/unsafe-format` errors, and exit code `2`, from
126
+ `format`, where the rules used to change it.
127
+
128
+ From `0.2.0-rc.1` or earlier, also:
129
+
130
+ - When nothing names a dialect, documents are read as GitHub Markdown, or as
131
+ Obsidian notes inside a vault, where they used to be read as CommonMark. Name
132
+ `"dialect": "commonmark"` to keep the old reading. The library's `lint`,
133
+ `format`, `resolveConfig`, and `createWorkspace` assume `github` as well.
134
+ - `$…$` is math only under the conditions of each dialect's renderer; before,
135
+ any text between two `$` signs was. Text that was left alone because of that
136
+ is now wrapped and restyled like other prose.
137
+ - A directory that may not be read is skipped with a warning, and a selected
138
+ document that may not be read gets an `engine/unreadable-file` error, where
139
+ both used to stop the command with exit code `2` and no report. An
140
+ `.obsidian/app.json` that cannot be read or is not valid JSON gives a warning,
141
+ and the vault is not wrapped.
142
+ - In a vault below the workspace root, Obsidian links resolve from the vault's
143
+ root and reach only its files. A workspace root inside a vault no longer
144
+ counts as the whole vault, so links that the rest of the vault could affect
145
+ are not rewritten.
146
+ - A plugin package is resolved as an `import` from the configuration file, with
147
+ the conditions given to Node.js, so a package with both an `import` and a
148
+ `require` entry loads through `import`.
149
+ - In the library, a source loader given to `createWorkspace` can be called more
150
+ than once for the same file and must return the same text each time, and one
151
+ that throws `EACCES` or `EPERM` makes the file unreadable instead of stopping
152
+ the run.
153
+ - The `lint` summary counts errors and warnings, and messages about paths,
154
+ configuration files, and plugins are worded differently. Exit codes and the
155
+ JSON report keep their meaning.
156
+
157
+ From every prerelease:
158
+
159
+ - The command line, the configuration, the JSON report, and the library now
160
+ follow the [versioning
161
+ policy](https://viell-dev.github.io/slop-markdown-tools/versions.html). npm's
162
+ `latest` tag names the newest stable release; release candidates no longer
163
+ move it.
164
+
165
+ ### Added
166
+
167
+ - `style/list-marker`, `style/ordered-list`, and `style/list-indent`, in
168
+ `recommended`, write bullets as `-` and numbers as `1.` with consistent
169
+ numbering and one space after each marker, and move each item's lines with its
170
+ text. Their options cover markdownlint's MD004, MD007, MD029, and MD030
171
+ ([#275](https://github.com/viell-dev/slop-markdown-tools/pull/275)).
172
+ - `--quiet` reports errors only, and `rules` lists the rules of the
173
+ configuration's plugins too, also as JSON with `--json`
174
+ ([#260](https://github.com/viell-dev/slop-markdown-tools/pull/260)).
175
+ - The CLI finds `mdtools.config.js` and `mdtools.config.cjs`, `extends` accepts
176
+ a single preset name, and a rule's setting can be its severity alone in a
177
+ list, as in `["warn"]`. The package ships the configuration's JSON Schema as
178
+ `config.schema.json`, which the documentation site serves as well, for editors
179
+ to complete and check configuration files
180
+ ([#261](https://github.com/viell-dev/slop-markdown-tools/pull/261)).
181
+ - The library loads with `require()`, exports `mdrefine/package.json`, and has a
182
+ doc comment for every export; the package lists `keywords`
183
+ ([#261](https://github.com/viell-dev/slop-markdown-tools/pull/261)).
184
+ - Nine problem rules: `links/undefined-reference`, `links/unused-definition`,
185
+ `links/empty`, `structure/heading-increment`, `content/image-alt`, and
186
+ `content/table-columns` in `recommended`, and the optional
187
+ `content/code-language`, `structure/single-title`, and
188
+ `structure/duplicate-heading`
189
+ ([#237](https://github.com/viell-dev/slop-markdown-tools/pull/237)).
190
+ - `style/block-spacing` separates headings and lists from the blocks around them
191
+ with a blank line
192
+ ([#190](https://github.com/viell-dev/slop-markdown-tools/pull/190)).
193
+ - Four style rules in `recommended`: `style/code-fence`, `style/thematic-break`,
194
+ `style/blank-lines`, and `style/trailing-space`, with markdownlint's choices
195
+ as options. `style/heading` also removes closing `#` sequences and can write
196
+ underlined headings (options `closing` and `style`), `style/table` can write
197
+ compact tables (option `style`), and both join `recommended`
198
+ ([#267](https://github.com/viell-dev/slop-markdown-tools/pull/267)).
199
+ - `lint` and `format` accept `ranges` to work on parts of a document, and
200
+ `format` returns their `scope`
201
+ ([#188](https://github.com/viell-dev/slop-markdown-tools/pull/188),
202
+ [#195](https://github.com/viell-dev/slop-markdown-tools/pull/195)).
203
+ - `mdrefine/node` exports `discoverWorkspace()`, the CLI's discovery of files,
204
+ with the example `examples/library/lint-workspace.mjs`
205
+ ([#189](https://github.com/viell-dev/slop-markdown-tools/pull/189)).
206
+ - Glob patterns as inputs, such as `mdtools lint "docs/**/*.md"`, expanded by
207
+ the CLI itself on every system
208
+ ([#239](https://github.com/viell-dev/slop-markdown-tools/pull/239)).
209
+
210
+ ### Changed
211
+
212
+ - A mistake on the command line exits with code `2`, as in ESLint and Prettier
213
+ ([#260](https://github.com/viell-dev/slop-markdown-tools/pull/260)).
214
+ - The text output names files from the current directory, and the JSON report
215
+ gives the workspace `root`
216
+ ([#260](https://github.com/viell-dev/slop-markdown-tools/pull/260)).
217
+ - `format --check` names the files that would change
218
+ ([#260](https://github.com/viell-dev/slop-markdown-tools/pull/260)).
219
+ - The help describes every command and lists only the options that each one
220
+ reads, an unknown dialect gets the list of dialects, `lint --fix` points to
221
+ `format --write`, `config explain` reports `config` and `path` and refuses
222
+ documents outside the workspace, and the `obsidian/strict-line-breaks` message
223
+ speaks to both command-line and library users
224
+ ([#260](https://github.com/viell-dev/slop-markdown-tools/pull/260)).
225
+ - Configuration and rule option errors name the setting as it is written, in
226
+ plain words, and list the allowed values, as in
227
+ `"extends[1]" must be a preset name, not 5`; a JSON syntax error gives its
228
+ line and column
229
+ ([#261](https://github.com/viell-dev/slop-markdown-tools/pull/261)).
230
+ - `resolveConfig` takes an options object, the exported tables are frozen and
231
+ typed read-only, and the types of Obsidian nodes and rule schemas are their
232
+ own ([#261](https://github.com/viell-dev/slop-markdown-tools/pull/261)).
233
+ - `format --write` refuses read-only files on every platform, and reports a file
234
+ that fails with `engine/unwritable-file`
235
+ ([#177](https://github.com/viell-dev/slop-markdown-tools/pull/177)).
236
+ - A file locked by another program on Windows counts as one that may not be
237
+ read, in the CLI and in `createWorkspace` loaders
238
+ ([#177](https://github.com/viell-dev/slop-markdown-tools/pull/177)).
239
+ - Documents and stdin that are not UTF-8 text are refused instead of being
240
+ damaged, and `createWorkspace` treats a loader error with the code
241
+ `ERR_ENCODING_INVALID_ENCODED_DATA` as an unreadable target
242
+ ([#234](https://github.com/viell-dev/slop-markdown-tools/pull/234)).
243
+ - `format --write` writes into the existing file instead of replacing it, so
244
+ that the file keeps its permissions, attributes, owner, creation time, and
245
+ hard links, and writes the original content back when a write fails part way
246
+ ([#234](https://github.com/viell-dev/slop-markdown-tools/pull/234),
247
+ [#255](https://github.com/viell-dev/slop-markdown-tools/pull/255)).
248
+ - `format --write` writes every document that formatted, and reports a document
249
+ that could not be read, formatted as configured, or written for its own file;
250
+ the JSON report's `written` lists the files written
251
+ ([#255](https://github.com/viell-dev/slop-markdown-tools/pull/255)).
252
+ - The documentation is restructured, with new pages for the rules, dialects,
253
+ integrations, the library API, versions, and this changelog, and the release
254
+ notes come from this file
255
+ ([#238](https://github.com/viell-dev/slop-markdown-tools/pull/238)).
256
+ - When one rule's edits would change a document's meaning, `format` leaves out
257
+ only that rule's edits and names the rule and the line, and it applies
258
+ overlapping edits in turn
259
+ ([#241](https://github.com/viell-dev/slop-markdown-tools/pull/241)).
260
+ - Plugin rule option schemas are compiled once instead of for every document
261
+ ([#241](https://github.com/viell-dev/slop-markdown-tools/pull/241)).
262
+ - Many repeated headings, and many emphases on one line, no longer take time
263
+ that grows with the square of their number on Forgejo and Gitea, and `ignore`
264
+ and `overrides` patterns are compiled once instead of for every path
265
+ ([#273](https://github.com/viell-dev/slop-markdown-tools/pull/273)).
266
+ - `.markdown` files are documents and link targets, and a file named on the
267
+ command line is read as Markdown whatever its name
268
+ ([#239](https://github.com/viell-dev/slop-markdown-tools/pull/239)).
269
+ - CI tests Node.js 22.12.0, the lowest supported version, where it tested the
270
+ newest Node.js 22, and also tests Node.js 26
271
+ ([#257](https://github.com/viell-dev/slop-markdown-tools/pull/257)).
272
+ - The documentation site describes the newest stable release instead of the
273
+ unreleased state of `main`
274
+ ([#257](https://github.com/viell-dev/slop-markdown-tools/pull/257)).
275
+ - `style/wrap` reflows a paragraph with a line break inside a link's text, an
276
+ image description, emphasis, strong text, strikethrough, or a code span, and
277
+ can break lines inside the text of links and emphasis
278
+ ([#262](https://github.com/viell-dev/slop-markdown-tools/pull/262)).
279
+ - `style/wrap` wraps the body of a GitHub, Forgejo, or Gitea alert below the
280
+ line with its marker, as it does for Obsidian callouts
281
+ ([#262](https://github.com/viell-dev/slop-markdown-tools/pull/262)).
282
+ - `style/wrap` reflows a paragraph whose code span goes on in a line that starts
283
+ with spaces or tabs, and joins the span without them, as `style/inline-code`
284
+ does ([#288](https://github.com/viell-dev/slop-markdown-tools/pull/288)).
285
+ - `style/wrap` leaves a paragraph as written when one of its lines starts with
286
+ `:::`, `{%`, or `{{`, such as a Docusaurus admonition or a Liquid tag, keeps a
287
+ word that starts with them from starting a line, and keeps a template tag that
288
+ one line holds whole. Site generators read these by line
289
+ ([#298](https://github.com/viell-dev/slop-markdown-tools/pull/298)).
290
+ - The plugin example's style rule writes one space after a heading's `#` marks,
291
+ because `style/thematic-break` now does what it did
292
+ ([#267](https://github.com/viell-dev/slop-markdown-tools/pull/267)).
293
+
294
+ ### Fixed
295
+
296
+ - `style/wrap`, the other rules that leave the line of an alert's or callout's
297
+ marker alone, and the safety check recognize a marker written with an escape
298
+ or a character reference, such as `\[!NOTE]` or `[!TIP]`, which GitHub
299
+ renders as an alert. Before, `style/wrap` joined the body onto such a marker,
300
+ and GitHub showed an ordinary quote
301
+ ([#298](https://github.com/viell-dev/slop-markdown-tools/pull/298)).
302
+ - A document whose front matter would end at a `---` or `+++` inside a code
303
+ block, an HTML block, or display math that a line of the front matter opens is
304
+ read with that block, and formatting keeps its meaning both with and without
305
+ the front matter. Before, rules could change the block's content, such as a
306
+ `___` in code into `---`, which GitHub shows
307
+ ([#298](https://github.com/viell-dev/slop-markdown-tools/pull/298)).
308
+ - `style/wrap` wraps a paragraph that starts with a linked image, such as a
309
+ badge, unless it opens a block quote. Before, it was left as written, as if it
310
+ started with a callout's marker
311
+ ([#298](https://github.com/viell-dev/slop-markdown-tools/pull/298)).
312
+ - A plugin rule's option schema of `false` refuses options, and an asynchronous
313
+ schema (`$async`) is refused when the rule set is built instead of crashing
314
+ Node.js after the run
315
+ ([#297](https://github.com/viell-dev/slop-markdown-tools/pull/297)).
316
+ - A heading whose code span is written across lines gets the anchor that GitHub
317
+ gives it, so a correct link to it is no longer reported missing, and the
318
+ library's `textContent` reads such a code span as renderers show it
319
+ ([#293](https://github.com/viell-dev/slop-markdown-tools/pull/293)).
320
+ - `--dialect` works with an `.mjs` configuration that exports a frozen object
321
+ ([#260](https://github.com/viell-dev/slop-markdown-tools/pull/260)).
322
+ - `--stdin-filepath` accepts a document inside a root that is reached through a
323
+ link or a Windows junction
324
+ ([#260](https://github.com/viell-dev/slop-markdown-tools/pull/260)).
325
+ - The configuration and command-line pages say that configuration patterns match
326
+ letter case on every system, while `.gitignore` files and input patterns
327
+ ignore it on Windows and macOS
328
+ ([#261](https://github.com/viell-dev/slop-markdown-tools/pull/261)).
329
+ - `format` stops on an error of the workspace, as `lint` does, instead of
330
+ reporting it as `engine/unsafe-format`, and a plugin named `engine`, whose
331
+ findings would pass for the engine's own, is rejected
332
+ ([#261](https://github.com/viell-dev/slop-markdown-tools/pull/261)).
333
+ - `parse` reads a document in the dialect that an alias such as `codeberg`
334
+ stands for, so Forgejo's rules apply to it, and the type declarations no
335
+ longer need `@types/mdast` from another package, which a strict installation
336
+ such as pnpm's does not provide
337
+ ([#261](https://github.com/viell-dev/slop-markdown-tools/pull/261)).
338
+ - Documents and JSON configuration files that start with a byte order mark are
339
+ read correctly
340
+ ([#174](https://github.com/viell-dev/slop-markdown-tools/pull/174)).
341
+ - `style/heading` keeps link reference definitions directly above an underlined
342
+ heading, which it used to replace with the heading, so that the document was
343
+ refused ([#267](https://github.com/viell-dev/slop-markdown-tools/pull/267)).
344
+ - `style/final-newline` adds no line ending, and `style/block-spacing` no blank
345
+ line, where it would become part of an unclosed HTML or Obsidian comment, and
346
+ `style/final-newline` none where it would add a line to a code block without
347
+ its closing fence; such documents used to be refused
348
+ ([#267](https://github.com/viell-dev/slop-markdown-tools/pull/267)).
349
+ - `style/wrap` leaves paragraphs as written instead of refusing the document
350
+ when their first word is a bare block marker
351
+ ([#196](https://github.com/viell-dev/slop-markdown-tools/pull/196)), when an
352
+ Obsidian paragraph holds `==`, `[[`, or `]]` outside its highlights and links,
353
+ or when the first line is lazy
354
+ ([#200](https://github.com/viell-dev/slop-markdown-tools/pull/200)).
355
+ - `style/wrap` lets words that only start like a block marker, such as
356
+ `--config`, `#tag`, or `-5`, begin a line, and keeps a table delimiter row
357
+ from beginning one
358
+ ([#262](https://github.com/viell-dev/slop-markdown-tools/pull/262)).
359
+ - `style/wrap` keeps a paragraph's first line from becoming a link reference
360
+ definition, a thematic break, or display math instead of refusing the document
361
+ ([#262](https://github.com/viell-dev/slop-markdown-tools/pull/262)).
362
+ - `style/wrap` counts a tab in a list item's prefix up to the next tab stop
363
+ instead of as no width
364
+ ([#262](https://github.com/viell-dev/slop-markdown-tools/pull/262)).
365
+ - A carriage return alone ends a line for suppression directives, diagnostic
366
+ positions, callout titles, and `style/wrap`
367
+ ([#196](https://github.com/viell-dev/slop-markdown-tools/pull/196),
368
+ [#200](https://github.com/viell-dev/slop-markdown-tools/pull/200)).
369
+ - A rule that throws or returns invalid findings is reported as
370
+ `engine/rule-error` for its document, and invalid plugin rules and names such
371
+ as `toString` are rejected with a clear message
372
+ ([#241](https://github.com/viell-dev/slop-markdown-tools/pull/241)).
373
+ - `.gitignore` files are applied as Git applies them, with negations in deeper
374
+ files and letter case per platform
375
+ ([#239](https://github.com/viell-dev/slop-markdown-tools/pull/239)).
376
+ - Git's ignore rules apply from the repository's top level, also above the
377
+ workspace root, together with `.git/info/exclude` and the global excludes
378
+ file. Inside a nested repository only its own rules apply, and none applies to
379
+ a file that Git tracks
380
+ ([#273](https://github.com/viell-dev/slop-markdown-tools/pull/273)).
381
+ - Git's ignore rules match letter case as each repository's `core.ignorecase`
382
+ says, and each repository, also a nested one, uses the global excludes file
383
+ that its own settings name
384
+ ([#287](https://github.com/viell-dev/slop-markdown-tools/pull/287)).
385
+ - A file or directory named on the command line that is ignored gets a warning
386
+ that says why, instead of being skipped without a word
387
+ ([#239](https://github.com/viell-dev/slop-markdown-tools/pull/239)).
388
+ - A link into `dist`, `coverage`, `node_modules`, or another directory that is
389
+ not processed, or through a symbolic link or junction, is checked on disk
390
+ instead of being reported missing; one that leads outside the workspace root
391
+ cannot be checked
392
+ ([#259](https://github.com/viell-dev/slop-markdown-tools/pull/259)).
393
+ - An Obsidian block identifier counts only at the end of a block and holds
394
+ letters, digits, and hyphens, in every rule that reads one
395
+ ([#259](https://github.com/viell-dev/slop-markdown-tools/pull/259)).
396
+ - A vault's `.obsidian/app.json` that starts with a byte order mark is read
397
+ ([#259](https://github.com/viell-dev/slop-markdown-tools/pull/259)).
398
+ - `links/notation` decodes percent escapes when it makes a wikilink
399
+ ([#259](https://github.com/viell-dev/slop-markdown-tools/pull/259)).
400
+ - A link to a file that is not Markdown accepts any fragment, such as an image's
401
+ `#gh-dark-mode-only` or a PDF's `#page=2`
402
+ ([#259](https://github.com/viell-dev/slop-markdown-tools/pull/259)).
403
+ - An Obsidian wikilink never resolves to a folder
404
+ ([#259](https://github.com/viell-dev/slop-markdown-tools/pull/259)).
405
+ - Obsidian links to a heading below another, `[[Note#Setup#Mobile]]`, are
406
+ resolved ([#259](https://github.com/viell-dev/slop-markdown-tools/pull/259)).
407
+ - An Obsidian heading link matches the heading's source text, with its
408
+ backticks, as well as its visible text
409
+ ([#259](https://github.com/viell-dev/slop-markdown-tools/pull/259)).
410
+ - `style/emphasis` and `style/strong` leave the text of a collapsed or shortcut
411
+ reference, such as `[*Title*][]`, as written, because that text is also the
412
+ label that matches the definition, and likewise text in brackets that the new
413
+ markers would make match one. Before, all of the rule's edits in the document
414
+ were refused
415
+ ([#274](https://github.com/viell-dev/slop-markdown-tools/pull/274)).
416
+ - `style/emphasis`, `style/strong`, `style/inline-code`, and
417
+ `style/block-spacing` no longer propose edits that change the parse in rare
418
+ places, where their edits were refused: crossed or shared markers, as in
419
+ `*a _b* c_` or `*****a***`, markers next to dollar math or across the line of
420
+ a callout's or alert's marker, code spans whose joined line would form an
421
+ Obsidian highlight or wikilink, change that line, or pair with earlier
422
+ backticks, a table below one that ends in a list item or block quote, and a
423
+ list in a quote that ends in an empty footnote definition
424
+ ([#274](https://github.com/viell-dev/slop-markdown-tools/pull/274)).
425
+ - `style/inline-code` leaves out the spaces and tabs that start a code span's
426
+ next line when it joins the span, as CommonMark and GitHub do; before,
427
+ `npm run` continued by an indented `build` became `npm run build`, which
428
+ changed what GitHub shows. The safety check compares code spans the same way
429
+ ([#274](https://github.com/viell-dev/slop-markdown-tools/pull/274)).
430
+ - `style/inline-code` and the safety check read a code span as GitHub shows it
431
+ where a line break is at its edge, and on a lazy continuation line, one
432
+ without its block quote's `>` or its list item's indentation, whose spaces and
433
+ tabs GitHub keeps in the span. Before, the rule could change what GitHub
434
+ shows, such as `npm run build` into `npm run build`, and the safety check
435
+ did not notice. Outside the GitHub dialect, a span on such an indented lazy
436
+ line stays split, because commonmark.js leaves those spaces out. `style/wrap`
437
+ now also reflows a paragraph whose code span has a line break at its edge
438
+ ([#291](https://github.com/viell-dev/slop-markdown-tools/pull/291)).
439
+ - `style/wrap` keeps a dollar from the edge of a line where it could begin or
440
+ end math there: in Obsidian a word that ends in `$` stays with the word after
441
+ it, and on GitHub and in Obsidian a word that starts with `$` stays with the
442
+ word before it. Before, such a paragraph was refused in Obsidian
443
+ ([#274](https://github.com/viell-dev/slop-markdown-tools/pull/274)).
444
+ - `style/wrap` leaves a paragraph as written when its second line is a table
445
+ delimiter row, in every dialect with tables. Directly below a table that ends
446
+ in a list item or block quote, the parser reads another table as such a
447
+ paragraph, and joining its lines removed a table that GitHub shows
448
+ ([#274](https://github.com/viell-dev/slop-markdown-tools/pull/274)).
449
+ - `style/wrap` keeps a run of `=` or `-` that starts the body of an alert or
450
+ callout together with the next word. Alone on a line, it would underline the
451
+ marker's line as a heading, and the paragraph was refused
452
+ ([#274](https://github.com/viell-dev/slop-markdown-tools/pull/274)).
453
+ - The type declaration of `defaultDialect` describes vaults anywhere in a
454
+ workspace ([#184](https://github.com/viell-dev/slop-markdown-tools/pull/184)),
455
+ and the CLI guide explains stdin in PowerShell
456
+ ([#182](https://github.com/viell-dev/slop-markdown-tools/pull/182)).
457
+
458
+ ## 0.2.0-rc.2 - 2026-10-06
459
+
460
+ When nothing names a dialect, GitHub Markdown is assumed, or the Obsidian
461
+ dialect inside a vault. Vaults are recognized anywhere in a workspace, and their
462
+ links resolve within them. Directories and files that may not be read no longer
463
+ stop a run. `$` math follows each renderer. Plugin packages resolve like an
464
+ `import`. Messages are clearer, link checks need about half the memory, and the
465
+ package ships examples. [Release
466
+ notes](https://github.com/viell-dev/slop-markdown-tools/releases/tag/0.2.0-rc.2).
467
+
468
+ ## 0.2.0-rc.1 - 2026-10-03
469
+
470
+ New `forgejo` and `gitea` dialects and presets, with `codeberg` as another name
471
+ for `forgejo`. Fragments are checked against the anchors that each renderer
472
+ generates, Forgejo and Gitea heading attributes are preserved, and
473
+ `forgejo/heading-id` reports ids that break rendering. [Release
474
+ notes](https://github.com/viell-dev/slop-markdown-tools/releases/tag/0.2.0-rc.1).
475
+
476
+ ## 0.1.0-rc.1 - 2026-09-21
477
+
478
+ Five built-in rules no longer propose edits that made formatting refuse ordinary
479
+ documents. Obsidian links match without regard to case, new line breaks follow a
480
+ document's first line ending, and applying many edits takes linear time.
481
+ [Release
482
+ notes](https://github.com/viell-dev/slop-markdown-tools/releases/tag/0.1.0-rc.1).
483
+
484
+ ## 0.1.0-beta.4 - 2026-09-18
485
+
486
+ `style/wrap` wraps an Obsidian callout's body directly below its title, and
487
+ reports a long title with `reportUnbreakable`. [Release
488
+ notes](https://github.com/viell-dev/slop-markdown-tools/releases/tag/0.1.0-beta.4).
489
+
490
+ ## 0.1.0-beta.3 - 2026-09-18
491
+
492
+ `style/wrap`'s report options tell breakable prose from unbreakable atoms, and
493
+ formatting is more than twice as fast. [Release
494
+ notes](https://github.com/viell-dev/slop-markdown-tools/releases/tag/0.1.0-beta.3).
495
+
496
+ ## 0.1.0-beta.2 - 2026-09-18
497
+
498
+ New `style/inline-code` and `structure/initial-heading` rules, the `measure`,
499
+ `reportUnreflowed`, and `reportUnbreakable` options of `style/wrap`, the
500
+ `resolve` settings, and `--exclude`. Link resolution fixes, and workspaces with
501
+ source loaders. [Release
502
+ notes](https://github.com/viell-dev/slop-markdown-tools/releases/tag/0.1.0-beta.2).
503
+
504
+ ## 0.1.0-beta.1 - 2026-09-18
505
+
506
+ The first public release: `lint` and `format` for CommonMark, GitHub Markdown,
507
+ and Obsidian, with presets, overrides, suppression comments, plugins, and link
508
+ checks. [Release
509
+ notes](https://github.com/viell-dev/slop-markdown-tools/releases/tag/0.1.0-beta.1).
@@ -0,0 +1,30 @@
1
+ # Code of conduct
2
+
3
+ People and agents take part in this project through its issues, pull requests,
4
+ and other spaces on GitHub. Everyone who does is expected to:
5
+
6
+ - be respectful, assume good faith, and criticize ideas rather than people;
7
+ - keep to the topic, and keep reports minimal and reproducible;
8
+ - leave out private content, such as other people's documents or personal
9
+ details;
10
+ - not harass, insult, threaten, or demean anyone, and not post sexual content or
11
+ spam.
12
+
13
+ An agent's operator is responsible for what the agent posts. Run agents so that
14
+ they follow this code and the [contribution guide](CONTRIBUTING.md); a stream of
15
+ unreviewed, generated submissions counts as spam.
16
+
17
+ These standards follow the [Contributor
18
+ Covenant](https://www.contributor-covenant.org/) in short form.
19
+
20
+ ## Enforcement
21
+
22
+ The repository's maintainers, who are agents assigned by its owner and the owner
23
+ themselves, may edit or hide comments, lock conversations, and close issues or
24
+ pull requests that break this code, saying why where it helps. The owner can
25
+ block an account. Nobody watches the repository around the clock, so a response
26
+ can take time.
27
+
28
+ To report a violation, use GitHub's "Report content" option on the comment,
29
+ issue, or pull request. It reaches GitHub's staff, who act on abuse across
30
+ GitHub. Do not open a public issue about another person.