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.
- package/CHANGELOG.md +577 -0
- package/CODE_OF_CONDUCT.md +30 -0
- package/CONTRIBUTING.md +189 -16
- package/README.md +100 -154
- package/SECURITY.md +15 -13
- package/config.schema.json +91 -0
- package/dist/cli/diff.d.ts +10 -0
- package/dist/cli/diff.js +247 -0
- package/dist/cli/diff.js.map +1 -0
- package/dist/cli/main.js +270 -150
- package/dist/cli/main.js.map +1 -1
- package/dist/config/load.js +67 -6
- package/dist/config/load.js.map +1 -1
- package/dist/config/problems.d.ts +7 -0
- package/dist/config/problems.js +208 -0
- package/dist/config/problems.js.map +1 -0
- package/dist/config/resolve.d.ts +42 -109
- package/dist/config/resolve.js +193 -52
- package/dist/config/resolve.js.map +1 -1
- package/dist/core/directives.d.ts +7 -0
- package/dist/core/directives.js +25 -13
- package/dist/core/directives.js.map +1 -1
- package/dist/core/engine.d.ts +42 -4
- package/dist/core/engine.js +518 -79
- package/dist/core/engine.js.map +1 -1
- package/dist/core/frozen.d.ts +6 -0
- package/dist/core/frozen.js +15 -0
- package/dist/core/frozen.js.map +1 -0
- package/dist/core/scope.d.ts +30 -0
- package/dist/core/scope.js +122 -0
- package/dist/core/scope.js.map +1 -0
- package/dist/core/types.d.ts +202 -23
- package/dist/core/types.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +3 -0
- package/dist/node.js +4 -0
- package/dist/node.js.map +1 -0
- package/dist/rules/blocks.d.ts +34 -0
- package/dist/rules/blocks.js +550 -0
- package/dist/rules/blocks.js.map +1 -0
- package/dist/rules/content.d.ts +2 -0
- package/dist/rules/content.js +85 -0
- package/dist/rules/content.js.map +1 -0
- package/dist/rules/dialects.js +10 -6
- package/dist/rules/dialects.js.map +1 -1
- package/dist/rules/links.js +302 -6
- package/dist/rules/links.js.map +1 -1
- package/dist/rules/lists.d.ts +2 -0
- package/dist/rules/lists.js +924 -0
- package/dist/rules/lists.js.map +1 -0
- package/dist/rules/structure.js +127 -1
- package/dist/rules/structure.js.map +1 -1
- package/dist/rules/style.d.ts +8 -2
- package/dist/rules/style.js +1137 -165
- package/dist/rules/style.js.map +1 -1
- package/dist/syntax/block-identifier.d.ts +18 -0
- package/dist/syntax/block-identifier.js +24 -0
- package/dist/syntax/block-identifier.js.map +1 -0
- package/dist/syntax/obsidian.d.ts +29 -11
- package/dist/syntax/obsidian.js +9 -10
- package/dist/syntax/obsidian.js.map +1 -1
- package/dist/syntax/parse.d.ts +87 -3
- package/dist/syntax/parse.js +247 -19
- package/dist/syntax/parse.js.map +1 -1
- package/dist/workspace/access.d.ts +12 -3
- package/dist/workspace/access.js +33 -5
- package/dist/workspace/access.js.map +1 -1
- package/dist/workspace/discovery.d.ts +85 -0
- package/dist/workspace/discovery.js +155 -0
- package/dist/workspace/discovery.js.map +1 -0
- package/dist/workspace/encoding.d.ts +24 -0
- package/dist/workspace/encoding.js +113 -0
- package/dist/workspace/encoding.js.map +1 -0
- package/dist/workspace/files.d.ts +92 -6
- package/dist/workspace/files.js +715 -59
- package/dist/workspace/files.js.map +1 -1
- package/dist/workspace/git.d.ts +54 -0
- package/dist/workspace/git.js +198 -0
- package/dist/workspace/git.js.map +1 -0
- package/dist/workspace/index.d.ts +58 -3
- package/dist/workspace/index.js +136 -37
- package/dist/workspace/index.js.map +1 -1
- package/dist/workspace/selection.d.ts +2 -2
- package/dist/workspace/selection.js +3 -3
- package/dist/workspace/selection.js.map +1 -1
- package/dist/workspace/slug.js +8 -1
- package/dist/workspace/slug.js.map +1 -1
- package/dist/workspace/vault.js +3 -1
- package/dist/workspace/vault.js.map +1 -1
- package/docs/api.md +239 -0
- package/docs/benchmarks.md +140 -200
- package/docs/changelog.md +1 -0
- package/docs/cli.md +281 -89
- package/docs/configuration.md +193 -480
- package/docs/design.md +163 -284
- package/docs/dialects.md +169 -0
- package/docs/examples.md +151 -109
- package/docs/index.md +21 -37
- package/docs/integrations.md +144 -0
- package/docs/obsidian.md +91 -115
- package/docs/plugins.md +147 -212
- package/docs/quick-start.md +68 -74
- package/docs/rules.md +1237 -0
- package/docs/versions.md +56 -0
- package/examples/README.md +17 -14
- package/examples/automation/summarize-report.mjs +5 -2
- package/examples/library/lint-folder.mjs +5 -4
- package/examples/library/lint-workspace.mjs +32 -0
- package/examples/plugin/notes/release-checklist.md +2 -2
- package/examples/plugin/rules.mjs +17 -23
- package/examples/workspaces/obsidian-vault/after/mdtools.config.jsonc +2 -2
- package/examples/workspaces/obsidian-vault/before/mdtools.config.jsonc +2 -2
- package/examples/workspaces/repository-docs/after/README.md +2 -2
- package/examples/workspaces/repository-docs/after/mdtools.config.jsonc +0 -2
- package/examples/workspaces/repository-docs/before/README.md +2 -2
- package/examples/workspaces/repository-docs/before/docs/guide.md +7 -7
- package/examples/workspaces/repository-docs/before/docs/reference.md +3 -1
- package/examples/workspaces/repository-docs/before/mdtools.config.jsonc +0 -2
- package/package.json +38 -12
- package/docs/contributing.md +0 -218
- package/docs/releases/0.1.0-beta.1.md +0 -39
- package/docs/releases/0.1.0-beta.2.md +0 -83
- package/docs/releases/0.1.0-beta.3.md +0 -61
- package/docs/releases/0.1.0-beta.4.md +0 -50
- package/docs/releases/0.1.0-rc.1.md +0 -99
- package/docs/releases/0.2.0-rc.1.md +0 -141
- package/docs/releases/0.2.0-rc.2.md +0 -225
- package/docs/releases.md +0 -144
- package/docs/testing.md +0 -93
package/docs/examples.md
CHANGED
|
@@ -2,20 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
The repository's
|
|
4
4
|
[`examples/`](https://github.com/viell-dev/slop-markdown-tools/tree/main/examples)
|
|
5
|
-
|
|
6
|
-
`node_modules/mdrefine/examples/`. The
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
root. With an installed package, use `npx --no-install mdtools` in place of
|
|
5
|
+
directory holds working examples, and the package ships the same files under
|
|
6
|
+
`node_modules/mdrefine/examples/`. The tests compare every file and output on
|
|
7
|
+
this page with the tool.
|
|
8
|
+
|
|
9
|
+
The commands run from the root of a [built
|
|
10
|
+
checkout](https://github.com/viell-dev/slop-markdown-tools/blob/main/CONTRIBUTING.md#set-up).
|
|
11
|
+
With the installed package, use `npx mdtools` in place of
|
|
13
12
|
`node dist/cli/main.js`.
|
|
14
13
|
|
|
15
14
|
## Start from a configuration
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
Copy one of four starting configurations to the root of your documents as
|
|
17
|
+
`mdtools.config.jsonc`:
|
|
19
18
|
|
|
20
19
|
- [`examples/github.jsonc`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/github.jsonc)
|
|
21
20
|
for repositories rendered by GitHub.
|
|
@@ -24,17 +23,16 @@ to the root of your documents as `mdtools.config.jsonc`:
|
|
|
24
23
|
- [`examples/gitea.jsonc`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/gitea.jsonc)
|
|
25
24
|
for Gitea instances.
|
|
26
25
|
- [`examples/obsidian.jsonc`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/obsidian.jsonc)
|
|
27
|
-
for Obsidian vaults, with links written as vault-
|
|
26
|
+
for Obsidian vaults, with links written as vault-relative paths.
|
|
28
27
|
|
|
29
|
-
Each wraps prose at 80 columns and chooses a link style
|
|
30
|
-
[
|
|
28
|
+
Each wraps prose at 80 columns and chooses a link style; see
|
|
29
|
+
[configuration](configuration.md).
|
|
31
30
|
|
|
32
31
|
## Format a repository's documentation
|
|
33
32
|
|
|
34
33
|
`examples/workspaces/repository-docs/` holds a README and two guides twice:
|
|
35
34
|
`before/` as someone might write them, and `after/` exactly as `format --write`
|
|
36
|
-
leaves them.
|
|
37
|
-
that no preset turns on:
|
|
35
|
+
leaves them. The configuration adds a rule that no preset enables:
|
|
38
36
|
|
|
39
37
|
[`examples/workspaces/repository-docs/before/mdtools.config.jsonc`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/workspaces/repository-docs/before/mdtools.config.jsonc):
|
|
40
38
|
|
|
@@ -43,8 +41,6 @@ that no preset turns on:
|
|
|
43
41
|
// Documentation for a repository hosted on GitHub.
|
|
44
42
|
"extends": ["recommended", "github"],
|
|
45
43
|
"rules": {
|
|
46
|
-
// Not part of a preset: turn underlined headings into "#" headings.
|
|
47
|
-
"style/heading": "warn",
|
|
48
44
|
// Write local links as ./relative paths, which editors can follow too.
|
|
49
45
|
"links/path": ["warn", { "style": "relative", "leadingDot": true }],
|
|
50
46
|
},
|
|
@@ -55,7 +51,7 @@ The README before formatting:
|
|
|
55
51
|
|
|
56
52
|
[`examples/workspaces/repository-docs/before/README.md`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/workspaces/repository-docs/before/README.md):
|
|
57
53
|
|
|
58
|
-
|
|
54
|
+
```md
|
|
59
55
|
# Weather Station
|
|
60
56
|
|
|
61
57
|
Weather Station collects *temperature*, *humidity*, and *pressure* readings from a sensor board and publishes them as a small web page that updates every minute.
|
|
@@ -75,12 +71,12 @@ Follow the [setup guide](docs/guide.md) first, then read the [sensor reference](
|
|
|
75
71
|
| Humidity | % | Yes |
|
|
76
72
|
| Pressure | hPa | Since 1.2 |
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
* [X] Publish readings every minute
|
|
75
|
+
* [ ] Keep a week of history
|
|
76
|
+
```
|
|
81
77
|
|
|
82
|
-
Preview the changes with `--diff`. To
|
|
83
|
-
|
|
78
|
+
Preview the changes with `--diff`. To try `--write`, copy `before/` elsewhere
|
|
79
|
+
first.
|
|
84
80
|
|
|
85
81
|
```sh
|
|
86
82
|
node dist/cli/main.js format --root examples/workspaces/repository-docs/before --diff
|
|
@@ -90,7 +86,7 @@ The same README afterwards:
|
|
|
90
86
|
|
|
91
87
|
[`examples/workspaces/repository-docs/after/README.md`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/workspaces/repository-docs/after/README.md):
|
|
92
88
|
|
|
93
|
-
|
|
89
|
+
```md
|
|
94
90
|
# Weather Station
|
|
95
91
|
|
|
96
92
|
Weather Station collects _temperature_, _humidity_, and _pressure_ readings from
|
|
@@ -101,8 +97,8 @@ a sensor board and publishes them as a small web page that updates every minute.
|
|
|
101
97
|
|
|
102
98
|
## Usage
|
|
103
99
|
|
|
104
|
-
Follow the [setup guide](./docs/guide.md) first, then read the
|
|
105
|
-
|
|
100
|
+
Follow the [setup guide](./docs/guide.md) first, then read the [sensor
|
|
101
|
+
reference](./docs/reference.md#pressure) to interpret the readings. The
|
|
106
102
|
[calibration notes](docs/calibration.md) explain how to correct a drifting
|
|
107
103
|
sensor.
|
|
108
104
|
|
|
@@ -116,7 +112,7 @@ sensor.
|
|
|
116
112
|
|
|
117
113
|
- [x] Publish readings every minute
|
|
118
114
|
- [ ] Keep a week of history
|
|
119
|
-
|
|
115
|
+
```
|
|
120
116
|
|
|
121
117
|
Each change comes from one rule of the configuration:
|
|
122
118
|
|
|
@@ -124,41 +120,48 @@ Each change comes from one rule of the configuration:
|
|
|
124
120
|
keep their lines.
|
|
125
121
|
- `style/emphasis` and `style/strong` chose `_` and `**`.
|
|
126
122
|
- `github/alert-marker` and `github/task-marker` normalized `[!note]` and `[X]`.
|
|
123
|
+
- `style/list-marker` wrote the task list with `-`.
|
|
127
124
|
- `style/table` aligned the table.
|
|
128
125
|
- `links/path` put `./` in front of the links it could resolve.
|
|
129
126
|
- In `docs/guide.md`, `style/heading` turned an underlined heading into a `#`
|
|
130
|
-
heading,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
127
|
+
heading, `style/ordered-list` wrote `1)` as `1.`, `style/list-indent` left one
|
|
128
|
+
space after each number and moved the code block in the second step with the
|
|
129
|
+
step's text, and `style/code-fence` wrote the block's `~~~` fence with
|
|
130
|
+
backticks.
|
|
131
|
+
- In `docs/reference.md`, `style/heading` removed the closing `##` of a heading,
|
|
132
|
+
`style/blank-lines` removed two repeated blank lines, and
|
|
133
|
+
`style/final-newline` added the missing final newline.
|
|
134
|
+
|
|
135
|
+
The link to `docs/calibration.md`, a file that does not exist, did not change.
|
|
136
|
+
Formatting never guesses a target, so `lint` still reports it and exits with
|
|
137
|
+
code `1`:
|
|
135
138
|
|
|
136
139
|
```sh
|
|
137
140
|
node dist/cli/main.js lint --root examples/workspaces/repository-docs/after
|
|
138
141
|
```
|
|
139
142
|
|
|
140
143
|
```text
|
|
141
|
-
README.md:13:1: error links/valid: Missing local target: docs/calibration.md.
|
|
144
|
+
examples/workspaces/repository-docs/after/README.md:13:1: error links/valid: Missing local target: docs/calibration.md.
|
|
142
145
|
3 file(s) linted; 1 error(s), 0 warning(s).
|
|
143
146
|
```
|
|
144
147
|
|
|
145
148
|
## Format an Obsidian vault
|
|
146
149
|
|
|
147
150
|
`examples/workspaces/obsidian-vault/` is a small vault, again as `before/` and
|
|
148
|
-
`after/`. The configuration sits at the vault root, next to `.obsidian/`,
|
|
149
|
-
`app.json` sets `"strictLineBreaks": true
|
|
150
|
-
|
|
151
|
+
`after/`. The configuration sits at the vault's root, next to `.obsidian/`,
|
|
152
|
+
whose `app.json` sets `"strictLineBreaks": true`, which [wrapping
|
|
153
|
+
needs](obsidian.md#enable-wrapping).
|
|
151
154
|
|
|
152
155
|
[`examples/workspaces/obsidian-vault/before/mdtools.config.jsonc`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/workspaces/obsidian-vault/before/mdtools.config.jsonc):
|
|
153
156
|
|
|
154
157
|
```jsonc
|
|
155
158
|
{
|
|
156
|
-
// An Obsidian vault; this file sits at the vault root, next to .obsidian/.
|
|
159
|
+
// An Obsidian vault; this file sits at the vault's root, next to .obsidian/.
|
|
157
160
|
"extends": ["recommended", "obsidian"],
|
|
158
161
|
// Templates contain placeholders, not prose. They stay valid link targets.
|
|
159
162
|
"ignore": ["Templates/**"],
|
|
160
163
|
"rules": {
|
|
161
|
-
// Spell Markdown links as vault-
|
|
164
|
+
// Spell Markdown links as vault-relative paths in angle brackets.
|
|
162
165
|
"links/path": ["warn", { "style": "root", "brackets": "angle" }],
|
|
163
166
|
},
|
|
164
167
|
}
|
|
@@ -168,7 +171,7 @@ The vault's home note before formatting:
|
|
|
168
171
|
|
|
169
172
|
[`examples/workspaces/obsidian-vault/before/Home.md`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/workspaces/obsidian-vault/before/Home.md):
|
|
170
173
|
|
|
171
|
-
|
|
174
|
+
```md
|
|
172
175
|
# Home
|
|
173
176
|
|
|
174
177
|
This vault tracks the kitchen garden. Start with [[Tomatoes]] or jump straight to the [[Watering schedule#Summer|summer watering plan]].
|
|
@@ -182,13 +185,13 @@ This vault tracks the kitchen garden. Start with [[Tomatoes]] or jump straight t
|
|
|
182
185
|
- [ ] Order *more* seed trays
|
|
183
186
|
|
|
184
187
|
![[Tomatoes#^harvest]]
|
|
185
|
-
|
|
188
|
+
```
|
|
186
189
|
|
|
187
190
|
And afterwards:
|
|
188
191
|
|
|
189
192
|
[`examples/workspaces/obsidian-vault/after/Home.md`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/workspaces/obsidian-vault/after/Home.md):
|
|
190
193
|
|
|
191
|
-
|
|
194
|
+
```md
|
|
192
195
|
# Home
|
|
193
196
|
|
|
194
197
|
This vault tracks the kitchen garden. Start with [[Tomatoes]] or jump straight
|
|
@@ -205,30 +208,28 @@ to the [[Garden/Watering schedule#Summer|summer watering plan]].
|
|
|
205
208
|
- [ ] Order _more_ seed trays
|
|
206
209
|
|
|
207
210
|
![[Garden/Tomatoes#^harvest]]
|
|
208
|
-
|
|
211
|
+
```
|
|
209
212
|
|
|
210
213
|
What to notice:
|
|
211
214
|
|
|
212
215
|
- The callout type is lowercase, its title stays on its line, and its body is
|
|
213
216
|
wrapped inside the quote.
|
|
214
|
-
- `[[Tomatoes]]` is unchanged, because
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
- The Markdown link to the template
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
- `[[Tomatoes]]` is unchanged, because its target is its visible text. The
|
|
218
|
+
labeled wikilink and the embed do not show their target, so both now carry the
|
|
219
|
+
vault-relative path.
|
|
220
|
+
- The Markdown link to the template is vault-relative, in angle brackets. The
|
|
221
|
+
template itself is ignored: never linted or formatted, but still a link
|
|
222
|
+
target.
|
|
220
223
|
- In `Garden/Tomatoes.md`, the paragraph ending in `^harvest` is not reflowed,
|
|
221
224
|
because a block identifier belongs to its paragraph's last line.
|
|
222
|
-
- `Garden/Watering schedule.md` links to a note
|
|
223
|
-
|
|
224
|
-
formatting.
|
|
225
|
+
- `Garden/Watering schedule.md` links to a note `Compost` that does not exist,
|
|
226
|
+
which `lint` reports before and after formatting.
|
|
225
227
|
|
|
226
228
|
## Write a plugin
|
|
227
229
|
|
|
228
|
-
`examples/plugin/` adds two
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
[Plugins and library API](plugins.md) describes the contract.
|
|
230
|
+
`examples/plugin/` adds two rules. A problem rule reports placeholder words. A
|
|
231
|
+
style rule writes one space between a heading's `#` marks and its text, and
|
|
232
|
+
leaves underlined headings alone. [Plugins](plugins.md) describes the contract.
|
|
232
233
|
|
|
233
234
|
[`examples/plugin/rules.mjs`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/plugin/rules.mjs):
|
|
234
235
|
|
|
@@ -250,7 +251,7 @@ export default {
|
|
|
250
251
|
name: "house",
|
|
251
252
|
presets: {
|
|
252
253
|
recommended: {
|
|
253
|
-
rules: { "house/no-placeholder": "error", "house/
|
|
254
|
+
rules: { "house/no-placeholder": "error", "house/heading-space": "warn" },
|
|
254
255
|
},
|
|
255
256
|
},
|
|
256
257
|
rules: {
|
|
@@ -292,36 +293,30 @@ export default {
|
|
|
292
293
|
return findings;
|
|
293
294
|
},
|
|
294
295
|
},
|
|
295
|
-
"
|
|
296
|
-
description: "Write
|
|
296
|
+
"heading-space": {
|
|
297
|
+
description: "Write one space between a heading's # marks and its text.",
|
|
297
298
|
kind: "style",
|
|
298
299
|
phase: "block",
|
|
299
300
|
check({ document }) {
|
|
300
301
|
const findings = [];
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
// "---" would close it as front matter, so no break is rewritten there.
|
|
304
|
-
const opensFrontMatter =
|
|
305
|
-
blocks[0]?.type === "thematicBreak" && document.source.startsWith("---");
|
|
306
|
-
for (const [index, node] of blocks.entries()) {
|
|
307
|
-
if (node.type !== "thematicBreak") continue;
|
|
302
|
+
visit(document.tree, (node) => {
|
|
303
|
+
if (node.type !== "heading" || !node.children.length) return;
|
|
308
304
|
const start = node.position.start.offset;
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
//
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
previous.position.end.line < node.position.start.line - 1;
|
|
305
|
+
const text = node.children[0].position.start.offset;
|
|
306
|
+
const marks = document.source.slice(start, text);
|
|
307
|
+
const wanted = `${"#".repeat(node.depth)} `;
|
|
308
|
+
// Only a "#" heading starts with its marks: an underlined heading
|
|
309
|
+
// starts with its text, and so the check below leaves it alone. The
|
|
310
|
+
// parser drops the blank space before a heading's text, so changing
|
|
311
|
+
// it cannot change what the heading says.
|
|
312
|
+
if (!/^#+[ \t]+$/.test(marks) || marks === wanted) return;
|
|
318
313
|
findings.push({
|
|
319
314
|
start,
|
|
320
|
-
end,
|
|
321
|
-
message: "Write
|
|
322
|
-
|
|
315
|
+
end: text,
|
|
316
|
+
message: "Write one space after the heading's # marks.",
|
|
317
|
+
edit: { start, end: text, text: wanted },
|
|
323
318
|
});
|
|
324
|
-
}
|
|
319
|
+
});
|
|
325
320
|
return findings;
|
|
326
321
|
},
|
|
327
322
|
},
|
|
@@ -329,8 +324,8 @@ export default {
|
|
|
329
324
|
};
|
|
330
325
|
```
|
|
331
326
|
|
|
332
|
-
The configuration loads the plugin, enables its preset, and
|
|
333
|
-
|
|
327
|
+
The configuration loads the plugin, enables its preset, and sets one rule's
|
|
328
|
+
options:
|
|
334
329
|
|
|
335
330
|
[`examples/plugin/mdtools.config.jsonc`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/plugin/mdtools.config.jsonc):
|
|
336
331
|
|
|
@@ -350,32 +345,31 @@ A note that triggers both rules:
|
|
|
350
345
|
|
|
351
346
|
[`examples/plugin/notes/release-checklist.md`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/plugin/notes/release-checklist.md):
|
|
352
347
|
|
|
353
|
-
|
|
348
|
+
```md
|
|
354
349
|
# Release checklist
|
|
355
350
|
|
|
356
351
|
Draft the announcement. TODO: add the download link.
|
|
357
352
|
|
|
358
353
|
Searching the notes with `grep TODO` is not reported: code is not prose.
|
|
359
354
|
|
|
360
|
-
|
|
355
|
+
## Before publishing
|
|
361
356
|
|
|
362
|
-
Ask for a review
|
|
363
|
-
|
|
357
|
+
Ask for a review.
|
|
358
|
+
```
|
|
364
359
|
|
|
365
|
-
Linting reports both,
|
|
360
|
+
Linting reports both, but not the `TODO` inside the code span:
|
|
366
361
|
|
|
367
362
|
```sh
|
|
368
363
|
node dist/cli/main.js lint --root examples/plugin
|
|
369
364
|
```
|
|
370
365
|
|
|
371
366
|
```text
|
|
372
|
-
notes/release-checklist.md:3:25: error house/no-placeholder: Replace the placeholder "TODO" before publishing.
|
|
373
|
-
notes/release-checklist.md:7:1: warn house/
|
|
367
|
+
examples/plugin/notes/release-checklist.md:3:25: error house/no-placeholder: Replace the placeholder "TODO" before publishing.
|
|
368
|
+
examples/plugin/notes/release-checklist.md:7:1: warn house/heading-space: Write one space after the heading's # marks.
|
|
374
369
|
1 file(s) linted; 1 error(s), 1 warning(s).
|
|
375
370
|
```
|
|
376
371
|
|
|
377
|
-
Formatting applies the style rule's edit and leaves the placeholder
|
|
378
|
-
person:
|
|
372
|
+
Formatting applies the style rule's edit and leaves the placeholder to a person:
|
|
379
373
|
|
|
380
374
|
```sh
|
|
381
375
|
node dist/cli/main.js format --root examples/plugin --diff
|
|
@@ -383,24 +377,24 @@ node dist/cli/main.js format --root examples/plugin --diff
|
|
|
383
377
|
|
|
384
378
|
```text
|
|
385
379
|
===================================================================
|
|
386
|
-
--- a/notes/release-checklist.md
|
|
387
|
-
+++ b/notes/release-checklist.md
|
|
380
|
+
--- a/examples/plugin/notes/release-checklist.md
|
|
381
|
+
+++ b/examples/plugin/notes/release-checklist.md
|
|
388
382
|
@@ -3,7 +3,7 @@
|
|
389
383
|
Draft the announcement. TODO: add the download link.
|
|
390
384
|
|
|
391
385
|
Searching the notes with `grep TODO` is not reported: code is not prose.
|
|
392
386
|
|
|
393
|
-
|
|
394
|
-
|
|
387
|
+
-## Before publishing
|
|
388
|
+
+## Before publishing
|
|
395
389
|
|
|
396
|
-
Ask for a review
|
|
397
|
-
notes/release-checklist.md:3:25: error house/no-placeholder: Replace the placeholder "TODO" before publishing.
|
|
390
|
+
Ask for a review.
|
|
391
|
+
examples/plugin/notes/release-checklist.md:3:25: error house/no-placeholder: Replace the placeholder "TODO" before publishing.
|
|
398
392
|
1 file(s) processed; 1 would change.
|
|
399
393
|
```
|
|
400
394
|
|
|
401
395
|
## Call the library
|
|
402
396
|
|
|
403
|
-
The library takes
|
|
397
|
+
The [library](api.md) takes and returns strings; it never reads or writes files.
|
|
404
398
|
The scripts import `mdrefine` by name, which works in a checkout and wherever
|
|
405
399
|
the package is installed.
|
|
406
400
|
|
|
@@ -441,7 +435,7 @@ no final newline.
|
|
|
441
435
|
changed: true; remaining diagnostics: 0
|
|
442
436
|
```
|
|
443
437
|
|
|
444
|
-
To check links between documents, the
|
|
438
|
+
To check links between documents, the script reads the files and passes them to
|
|
445
439
|
`createWorkspace()`:
|
|
446
440
|
|
|
447
441
|
[`examples/library/lint-folder.mjs`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/library/lint-folder.mjs):
|
|
@@ -452,7 +446,8 @@ To check links between documents, the host reads the files and passes them to
|
|
|
452
446
|
// The library never reads or writes files. The host reads them and hands them
|
|
453
447
|
// to createWorkspace(), which is what lets rules check links between documents.
|
|
454
448
|
// This script reads everything below the folder; a real host would skip folders
|
|
455
|
-
// such as .git and node_modules, as the CLI does.
|
|
449
|
+
// such as .git and node_modules, as the CLI does. lint-workspace.mjs leaves that
|
|
450
|
+
// to discoverWorkspace() from "mdrefine/node".
|
|
456
451
|
//
|
|
457
452
|
// node examples/library/lint-folder.mjs [folder]
|
|
458
453
|
import { readdir, readFile } from "node:fs/promises";
|
|
@@ -466,14 +461,14 @@ const folder = path.resolve(
|
|
|
466
461
|
const config = { extends: ["recommended", "github"] };
|
|
467
462
|
|
|
468
463
|
// Workspace keys are forward-slash paths relative to the folder. A Markdown
|
|
469
|
-
// file
|
|
470
|
-
// still resolve.
|
|
464
|
+
// file, named .md or .markdown as the CLI finds them, maps to its text; any
|
|
465
|
+
// other file maps to null, so that links to it still resolve.
|
|
471
466
|
const files = {};
|
|
472
467
|
for (const entry of await readdir(folder, { recursive: true, withFileTypes: true })) {
|
|
473
468
|
if (!entry.isFile()) continue;
|
|
474
469
|
const absolute = path.join(entry.parentPath, entry.name);
|
|
475
470
|
const name = path.relative(folder, absolute).split(path.sep).join("/");
|
|
476
|
-
files[name] = /\.md$/i.test(name) ? await readFile(absolute, "utf8") : null;
|
|
471
|
+
files[name] = /\.(?:md|markdown)$/i.test(name) ? await readFile(absolute, "utf8") : null;
|
|
477
472
|
}
|
|
478
473
|
const workspace = createWorkspace(files, { dialect: "github" });
|
|
479
474
|
|
|
@@ -504,10 +499,60 @@ README.md:13:1 error links/valid: Missing local target: docs/calibration.md.
|
|
|
504
499
|
1 error(s)
|
|
505
500
|
```
|
|
506
501
|
|
|
502
|
+
`mdrefine/node` finds and selects the files as the CLI does, and prepares each
|
|
503
|
+
document's options:
|
|
504
|
+
|
|
505
|
+
[`examples/library/lint-workspace.mjs`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/library/lint-workspace.mjs):
|
|
506
|
+
|
|
507
|
+
```js
|
|
508
|
+
// Lint a workspace on disk through the library, choosing files as the CLI does.
|
|
509
|
+
//
|
|
510
|
+
// discoverWorkspace() from "mdrefine/node" finds the files, honors .gitignore
|
|
511
|
+
// files and the configuration's ignore patterns, leaves out nested
|
|
512
|
+
// repositories and what it may not read, and recognizes Obsidian vaults.
|
|
513
|
+
// options() then gives each document what the CLI passes to lint() and
|
|
514
|
+
// format(). Configuration files are not read: pass the configuration.
|
|
515
|
+
//
|
|
516
|
+
// node examples/library/lint-workspace.mjs [folder]
|
|
517
|
+
import path from "node:path";
|
|
518
|
+
import { fileURLToPath } from "node:url";
|
|
519
|
+
import { lint } from "mdrefine";
|
|
520
|
+
import { discoverWorkspace } from "mdrefine/node";
|
|
521
|
+
|
|
522
|
+
const root = path.resolve(
|
|
523
|
+
process.argv[2] ?? fileURLToPath(new URL("../workspaces/repository-docs/after", import.meta.url)),
|
|
524
|
+
);
|
|
525
|
+
const config = { extends: ["recommended", "github"] };
|
|
526
|
+
|
|
527
|
+
const discovery = await discoverWorkspace({ root, config });
|
|
528
|
+
for (const item of discovery.skipped) console.log(`skipped: ${item.message}`);
|
|
529
|
+
let errors = 0;
|
|
530
|
+
for (const name of discovery.selected) {
|
|
531
|
+
for (const item of lint(discovery.read(name), discovery.options(name))) {
|
|
532
|
+
if (item.severity === "error") errors += 1;
|
|
533
|
+
console.log(
|
|
534
|
+
`${name}:${item.line}:${item.column} ${item.severity} ${item.rule}: ${item.message}`,
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
console.log(`${errors} error(s) in ${discovery.selected.length} document(s)`);
|
|
539
|
+
process.exitCode = errors > 0 ? 1 : 0;
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
```sh
|
|
543
|
+
node examples/library/lint-workspace.mjs
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
```text
|
|
547
|
+
README.md:13:1 error links/valid: Missing local target: docs/calibration.md.
|
|
548
|
+
1 error(s) in 3 document(s)
|
|
549
|
+
```
|
|
550
|
+
|
|
507
551
|
## Automate checks
|
|
508
552
|
|
|
509
|
-
A workflow for a repository that lists `mdrefine` in its
|
|
510
|
-
|
|
553
|
+
A GitHub Actions workflow for a repository that lists `mdrefine` in its
|
|
554
|
+
`devDependencies`; [integrations](integrations.md#continuous-integration) covers
|
|
555
|
+
Forgejo:
|
|
511
556
|
|
|
512
557
|
[`examples/automation/github-actions.yml`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/automation/github-actions.yml):
|
|
513
558
|
|
|
@@ -537,9 +582,9 @@ jobs:
|
|
|
537
582
|
- run: npx --no-install mdtools format --check
|
|
538
583
|
```
|
|
539
584
|
|
|
540
|
-
|
|
585
|
+
The script
|
|
541
586
|
[`summarize-report.mjs`](https://github.com/viell-dev/slop-markdown-tools/blob/main/examples/automation/summarize-report.mjs)
|
|
542
|
-
reads
|
|
587
|
+
reads a `--json` report and counts diagnostics per rule:
|
|
543
588
|
|
|
544
589
|
```sh
|
|
545
590
|
node dist/cli/main.js lint --root examples/plugin --json | node examples/automation/summarize-report.mjs
|
|
@@ -548,8 +593,5 @@ node dist/cli/main.js lint --root examples/plugin --json | node examples/automat
|
|
|
548
593
|
```text
|
|
549
594
|
lint: 1 file(s), 2 diagnostic(s)
|
|
550
595
|
1 error house/no-placeholder in 1 file(s)
|
|
551
|
-
1 warn house/
|
|
596
|
+
1 warn house/heading-space in 1 file(s)
|
|
552
597
|
```
|
|
553
|
-
|
|
554
|
-
[CLI workflows](cli.md) covers file selection, exit codes, and stdin;
|
|
555
|
-
[configuration and rules](configuration.md) lists every rule and option.
|
package/docs/index.md
CHANGED
|
@@ -1,52 +1,36 @@
|
|
|
1
1
|
---
|
|
2
2
|
layout: home
|
|
3
3
|
hero:
|
|
4
|
-
name:
|
|
5
|
-
text:
|
|
6
|
-
tagline:
|
|
4
|
+
name: mdrefine
|
|
5
|
+
text: Lint and format Markdown
|
|
6
|
+
tagline: One configuration for checks and formatting, for documents rendered by GitHub, Forgejo, Gitea, Obsidian, or any CommonMark renderer.
|
|
7
7
|
actions:
|
|
8
8
|
- theme: brand
|
|
9
|
-
text:
|
|
9
|
+
text: Get started
|
|
10
10
|
link: /quick-start
|
|
11
11
|
- theme: alt
|
|
12
|
-
text:
|
|
13
|
-
link: /
|
|
12
|
+
text: Rules
|
|
13
|
+
link: /rules
|
|
14
14
|
features:
|
|
15
15
|
- title: Check, preview, then write
|
|
16
|
-
details: Lint without changing files,
|
|
17
|
-
- title:
|
|
18
|
-
details:
|
|
19
|
-
- title:
|
|
20
|
-
details:
|
|
16
|
+
details: Lint without changing files, read the diff, and write when ready. A JSON report and exit codes serve CI, scripts, and agents.
|
|
17
|
+
- title: Changes only what its rules target
|
|
18
|
+
details: Formatting edits the source in place, keeps everything else byte for byte, and refuses an edit that would change what a document means.
|
|
19
|
+
- title: Knows where it renders
|
|
20
|
+
details: Tables, math, wikilinks, callouts, and heading anchors are read as GitHub, Forgejo, Gitea, or Obsidian read them, and local links are checked the same way.
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
mdrefine is meant to replace a general-purpose linter and formatter, such as
|
|
24
|
+
markdownlint and Prettier, for Markdown documents.
|
|
25
|
+
[Integrations](integrations.md#coming-from-prettier-or-markdownlint) shows which
|
|
26
|
+
of their checks have a rule here so far.
|
|
26
27
|
|
|
27
28
|
```sh
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
npx mdtools lint
|
|
30
|
+
npx mdtools format --diff
|
|
31
|
+
npx mdtools format --write
|
|
32
|
+
npx mdtools format --check
|
|
31
33
|
```
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
for the limits of those checks.
|
|
36
|
-
|
|
37
|
-
## Start with your documents
|
|
38
|
-
|
|
39
|
-
- **A repository or writing folder:** follow the [quick start](quick-start.md),
|
|
40
|
-
then choose [configuration and rules](configuration.md).
|
|
41
|
-
- **An Obsidian vault:** use the [vault guide](obsidian.md) for wikilinks,
|
|
42
|
-
callouts, block references, and safe prose wrapping.
|
|
43
|
-
- **A custom workflow:** use [CLI workflows](cli.md) or extend the
|
|
44
|
-
[library and plugin API](plugins.md).
|
|
45
|
-
- **A look before installing:** the [examples](examples.md) show documents
|
|
46
|
-
before and after formatting, a plugin, and library scripts.
|
|
47
|
-
|
|
48
|
-
This is an early prerelease, written, tested, documented, and maintained by AI
|
|
49
|
-
agents rather than human maintainers. The repository owner assigns agents to
|
|
50
|
-
tasks and follows the project through issues and PRs, not code. Issues and pull
|
|
51
|
-
requests from people and agents are welcome. Read
|
|
52
|
-
[how to contribute](contributing.md) before reporting a defect.
|
|
35
|
+
[Get started](quick-start.md), browse the [rules](rules.md), or see
|
|
36
|
+
[examples](examples.md) of documents before and after formatting.
|