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
package/docs/rules.md ADDED
@@ -0,0 +1,1237 @@
1
+ # Rules
2
+
3
+ A rule is either a **style** rule or a **problem** rule. A style rule checks how
4
+ something is written and proposes an edit, which `format` applies and `lint`
5
+ reports. A problem rule reports a defect that has no single correct repair, and
6
+ never edits. `format` applies an edit only when the document still means the
7
+ same afterwards; see [how it works](design.md#safety-model).
8
+
9
+ Enable and configure rules under `rules` in the
10
+ [configuration](configuration.md#rules-and-severity). `npx mdtools rules` lists
11
+ the built-in rules and those of the configuration's [plugins](plugins.md).
12
+
13
+ 🎨 marks a style rule, whose findings `format` fixes, and 🔍 a problem rule,
14
+ which is reported only. ✅ is yes and ❌ no. Each rule's section names its
15
+ presets, dialects, and options.
16
+
17
+ | Rule | Kind | `recommended` | Dialect preset | Options |
18
+ | ----------------------------- | :--: | :-----------: | :------------: | :-----: |
19
+ | `content/code-language` | 🔍 | ❌ | ❌ | ❌ |
20
+ | `content/image-alt` | 🔍 | ✅ | ❌ | ❌ |
21
+ | `content/table-columns` | 🔍 | ✅ | ❌ | ❌ |
22
+ | `forgejo/heading-id` | 🔍 | ❌ | ✅ (error) | ❌ |
23
+ | `github/alert-marker` | 🎨 | ❌ | ✅ | ❌ |
24
+ | `github/task-marker` | 🎨 | ❌ | ✅ | ❌ |
25
+ | `links/empty` | 🔍 | ✅ | ❌ | ❌ |
26
+ | `links/notation` | 🎨 | ❌ | ❌ | ✅ |
27
+ | `links/path` | 🎨 | ❌ | ❌ | ✅ |
28
+ | `links/undefined-reference` | 🔍 | ✅ | ❌ | ❌ |
29
+ | `links/unused-definition` | 🔍 | ✅ | ❌ | ❌ |
30
+ | `links/valid` | 🔍 | ✅ (error) | ❌ | ❌ |
31
+ | `obsidian/block-reference` | 🔍 | ❌ | ✅ (error) | ❌ |
32
+ | `obsidian/callout-marker` | 🎨 | ❌ | ✅ | ❌ |
33
+ | `obsidian/strict-line-breaks` | 🔍 | ❌ | ✅ | ❌ |
34
+ | `structure/duplicate-heading` | 🔍 | ❌ | ❌ | ❌ |
35
+ | `structure/heading-increment` | 🔍 | ✅ | ❌ | ❌ |
36
+ | `structure/initial-heading` | 🔍 | ❌ | ❌ | ❌ |
37
+ | `structure/single-title` | 🔍 | ❌ | ❌ | ❌ |
38
+ | `style/blank-lines` | 🎨 | ✅ | ❌ | ✅ |
39
+ | `style/block-spacing` | 🎨 | ❌ | ❌ | ❌ |
40
+ | `style/code-fence` | 🎨 | ✅ | ❌ | ✅ |
41
+ | `style/emphasis` | 🎨 | ✅ | ❌ | ✅ |
42
+ | `style/final-newline` | 🎨 | ✅ | ❌ | ❌ |
43
+ | `style/heading` | 🎨 | ✅ | ❌ | ✅ |
44
+ | `style/inline-code` | 🎨 | ❌ | ❌ | ❌ |
45
+ | `style/list-indent` | 🎨 | ✅ | ❌ | ✅ |
46
+ | `style/list-marker` | 🎨 | ✅ | ❌ | ✅ |
47
+ | `style/ordered-list` | 🎨 | ✅ | ❌ | ✅ |
48
+ | `style/strong` | 🎨 | ✅ | ❌ | ✅ |
49
+ | `style/table` | 🎨 | ✅ | ✅ | ✅ |
50
+ | `style/thematic-break` | 🎨 | ✅ | ❌ | ✅ |
51
+ | `style/trailing-space` | 🎨 | ✅ | ❌ | ✅ |
52
+ | `style/wrap` | 🎨 | ✅ | ❌ | ✅ |
53
+
54
+ A preset enables its rules as warnings, unless the rule's section says error.
55
+ The `codeberg` preset is the `forgejo` preset under another name. In a dialect
56
+ that a rule's section does not name, the rule finds nothing.
57
+
58
+ ## `content/code-language`
59
+
60
+ **Problem rule**, reported only. Presets: none. Dialects: all. Options: none.
61
+
62
+ Reports a fenced code block that does not name its language after the opening
63
+ fence. GitHub, Forgejo, Gitea, and Obsidian highlight code by the language its
64
+ fence names; name `text` for plain text. Indented code blocks have no place for
65
+ a language and are not reported.
66
+
67
+ Reported:
68
+
69
+ ````markdown
70
+ ```
71
+ npm test
72
+ ```
73
+ ````
74
+
75
+ Not reported:
76
+
77
+ ````markdown
78
+ ```sh
79
+ npm test
80
+ ```
81
+ ````
82
+
83
+ ## `content/image-alt`
84
+
85
+ **Problem rule**, reported only. Presets: `recommended`. Dialects: all. Options:
86
+ none.
87
+
88
+ Reports an image without alternative text, the text between the brackets of
89
+ `![text](chart.png)`. Screen readers read it in place of the image, and browsers
90
+ show it when the image does not load. Text that is only blank space counts as
91
+ none. In the Obsidian dialect, a size after `|`, as in `![|100](chart.png)`, is
92
+ not text, and embeds such as `![[chart.png]]` are not reported, because they
93
+ have no place for text. HTML `<img>` elements are not checked.
94
+
95
+ Reported:
96
+
97
+ ```markdown
98
+ ![](sales-by-month.png)
99
+ ```
100
+
101
+ Not reported:
102
+
103
+ ```markdown
104
+ ![Sales by month, rising from March](sales-by-month.png)
105
+ ```
106
+
107
+ ## `content/table-columns`
108
+
109
+ **Problem rule**, reported only. Presets: `recommended`. Dialects: all but
110
+ CommonMark. Options: none.
111
+
112
+ Reports a table row with more or fewer cells than the header row. As the GFM
113
+ specification requires, renderers drop the extra cells of a longer row without a
114
+ trace and fill a shorter row with empty cells, so the table does not show what
115
+ its source says. A `|` separates cells inside code and wikilinks too, unless it
116
+ is escaped as `\|`.
117
+
118
+ Reported, because the last row has three cells:
119
+
120
+ ```markdown
121
+ | Name | Size |
122
+ | ---- | ---- |
123
+ | a | 1 |
124
+ | b | 2 | 3 |
125
+ ```
126
+
127
+ Not reported:
128
+
129
+ ```markdown
130
+ | Name | Size |
131
+ | ------- | ---- |
132
+ | a | 1 |
133
+ | `b\|c` | 2 |
134
+ ```
135
+
136
+ ## `forgejo/heading-id`
137
+
138
+ **Problem rule**, reported only. Presets: `forgejo`, `gitea` (error). Dialects:
139
+ Forgejo, Gitea. Options: none.
140
+
141
+ Reports a heading attribute block whose `id` is not text, such as `{id=5}`,
142
+ `{id=true}`, or a list. Forgejo, and Gitea before 1.26, render nothing at all
143
+ for a document that contains one; Gitea 1.26 and later render the heading
144
+ without an anchor. Quote the value (`{id="5"}`) or write `{#5}`.
145
+ [Dialects](dialects.md#forgejo-and-gitea) describes attribute blocks.
146
+
147
+ Reported:
148
+
149
+ ```markdown
150
+ ## Install {id=5}
151
+ ```
152
+
153
+ Not reported:
154
+
155
+ ```markdown
156
+ ## Install {id="5"}
157
+ ```
158
+
159
+ ## `github/alert-marker`
160
+
161
+ **Style rule**, fixed by `format`. Presets: `github`, `forgejo`, `gitea`.
162
+ Dialects: GitHub, Forgejo, Gitea. Options: none.
163
+
164
+ Writes the type of a GitHub alert in capitals. The renderers accept any case for
165
+ the five types `NOTE`, `TIP`, `IMPORTANT`, `WARNING`, and `CAUTION`, and their
166
+ documentation spells them in capitals. Other types are not alerts there and are
167
+ left as written, and so is a marker written with an escape or a character
168
+ reference, such as `\[!note]`.
169
+
170
+ Before:
171
+
172
+ ```markdown
173
+ > [!note]
174
+ > Read this first.
175
+ ```
176
+
177
+ After:
178
+
179
+ ```markdown
180
+ > [!NOTE]
181
+ > Read this first.
182
+ ```
183
+
184
+ ## `github/task-marker`
185
+
186
+ **Style rule**, fixed by `format`. Presets: `github`, `forgejo`, `gitea`,
187
+ `obsidian`. Dialects: all but CommonMark. Options: none.
188
+
189
+ Writes the mark of a completed task as a lowercase `x`.
190
+
191
+ Before:
192
+
193
+ ```markdown
194
+ - [X] Write the guide
195
+ ```
196
+
197
+ After:
198
+
199
+ ```markdown
200
+ - [x] Write the guide
201
+ ```
202
+
203
+ ## `links/empty`
204
+
205
+ **Problem rule**, reported only. Presets: `recommended`. Dialects: all. Options:
206
+ none.
207
+
208
+ Reports a link or image whose destination is empty, as in `[guide]()`, or only
209
+ `#`, which leads to the top of the page. Both are usually placeholders that were
210
+ never filled in. A reference definition with such a destination is reported
211
+ once, at the definition, rather than at each reference to it. Obsidian wikilinks
212
+ are not checked.
213
+
214
+ Reported:
215
+
216
+ ```markdown
217
+ See the [setup guide](#) and the [changelog]().
218
+ ```
219
+
220
+ Not reported:
221
+
222
+ ```markdown
223
+ See the [setup guide](#setup).
224
+ ```
225
+
226
+ ## `links/notation`
227
+
228
+ **Style rule**, fixed by `format`. Presets: none. Dialects: Obsidian. Options:
229
+ `style`, required.
230
+
231
+ Converts Obsidian links between Markdown and wikilink notation. The `style`
232
+ option is required; without it the rule does nothing.
233
+
234
+ - `"markdown"` turns a wikilink with its own label, `[[target|label]]`, into
235
+ `[label](<target>)`.
236
+ - `"wiki"` turns a Markdown link whose label is plain text into
237
+ `[[target|label]]`.
238
+
239
+ Only links whose target exists are converted. Titles, labels with formatting,
240
+ wikilinks without a label, and embeds are left as written: a wikilink without a
241
+ label shows its target as text, and a note embed is not the same thing as a
242
+ Markdown image. A new wikilink decodes percent escapes, because Obsidian takes
243
+ its text as the note's name: `[x](My%20Note.md)` becomes `[[My Note.md|x]]`. A
244
+ destination that does not decode, or whose name would hold `|`, `[`, `]`, `#`,
245
+ or `^`, stays as written.
246
+
247
+ With `"style": "markdown"`, before:
248
+
249
+ ```markdown
250
+ See [[Garden/Plan|the plan]].
251
+ ```
252
+
253
+ After:
254
+
255
+ ```markdown
256
+ See [the plan](<Garden/Plan>).
257
+ ```
258
+
259
+ With `links/path` also on, a link that both change gets its notation first and
260
+ its path in the next pass, the same result as running them one after the other.
261
+
262
+ ## `links/path`
263
+
264
+ **Style rule**, fixed by `format`. Presets: none. Dialects: all; some options
265
+ Obsidian only. Options: `style`, `brackets`, `extension`, `leadingDot`.
266
+
267
+ Rewrites the destination of a local link to the configured spelling. A link is
268
+ rewritten only when its target exists and its fragment, if any, is found, and
269
+ only when the new destination leads to the same file and fragment.
270
+
271
+ | Option | Values | Default |
272
+ | ------------ | -------------------------------------------------- | ------------ |
273
+ | `style` | `"preserve"`, `"relative"`, `"root"`, `"shortest"` | `"preserve"` |
274
+ | `brackets` | `"preserve"`, `"angle"`, `"bare"` | `"preserve"` |
275
+ | `extension` | `"preserve"`, `"include"`, `"omit"` | `"preserve"` |
276
+ | `leadingDot` | `true` or `false` | `false` |
277
+
278
+ - `style`: `relative` counts the path from the linking document. `root` writes
279
+ it vault-relative, that is from the vault's root directory, without a leading
280
+ slash. `shortest` writes only the note's name when that name finds the same
281
+ note, and otherwise the vault-relative path. `root` and `shortest` apply in
282
+ the Obsidian dialect only.
283
+ - `brackets`: `angle` writes the destination in `<…>`; `bare` writes it without,
284
+ with spaces percent-encoded.
285
+ - `extension`: whether the path to a Markdown file ends in `.md`. `omit` applies
286
+ in the Obsidian dialect only.
287
+ - `leadingDot`: with `relative`, start a path with `./` when it does not start
288
+ with `.`.
289
+
290
+ A relative path also gets `./` when it would otherwise name a different file at
291
+ the vault's root. A destination that already has the configured spelling keeps
292
+ its percent-encoding; a new path encodes `%` and `#`, so that it names the same
293
+ file. Absolute filesystem paths are never written. These are left as written: a
294
+ wikilink without a label, whose target is also its visible text; reference
295
+ definitions, which are checked but not rewritten; autolinks; and links whose
296
+ target is uncertain because a directory could not be read or the workspace root
297
+ is only part of a vault (see [Obsidian
298
+ vaults](obsidian.md#a-workspace-root-inside-a-vault)).
299
+
300
+ With `{ "style": "relative", "leadingDot": true }` in `README.md`, before:
301
+
302
+ ```markdown
303
+ See the [guide](docs/guide.md#setup).
304
+ ```
305
+
306
+ After:
307
+
308
+ ```markdown
309
+ See the [guide](./docs/guide.md#setup).
310
+ ```
311
+
312
+ ## `links/undefined-reference`
313
+
314
+ **Problem rule**, reported only. Presets: `recommended`. Dialects: all;
315
+ footnotes all but CommonMark. Options: none.
316
+
317
+ Reports a reference whose label has no definition in the document: a full
318
+ reference `[text][label]`, a collapsed reference `[label][]`, and, in every
319
+ dialect but CommonMark, a footnote reference `[^label]`. The renderer shows such
320
+ a reference as plain text, brackets and all. Labels match as the renderer
321
+ matches them, without regard to case or to how much blank space separates words.
322
+
323
+ A shortcut reference, `[label]` alone, is not reported, because brackets in
324
+ prose are usually just brackets. Neither are brackets directly after a letter,
325
+ digit, `_`, or `)`, as in `matrix[i][j]`, which are indexes rather than
326
+ references, nor brackets in code, math, HTML, or links, nor escaped ones (`\[`).
327
+ A run of brackets such as `[a][b][c]` is reported once, at its start.
328
+
329
+ Reported, when neither a definition `[setup]: …` nor a footnote `[^1]: …`
330
+ exists:
331
+
332
+ ```markdown
333
+ See the [installation guide][setup] and [setup][].[^1]
334
+ ```
335
+
336
+ Not reported:
337
+
338
+ ```markdown
339
+ See the [installation guide][Setup] and press [Enter].
340
+
341
+ [setup]: install.md
342
+ ```
343
+
344
+ ## `links/unused-definition`
345
+
346
+ **Problem rule**, reported only. Presets: `recommended`. Dialects: all. Options:
347
+ none.
348
+
349
+ Reports a reference definition or footnote that no reference in the document
350
+ uses. A definition that only a shortcut reference `[label]` uses counts as used.
351
+ A second definition of the same label is reported too, because the renderers use
352
+ the first. GitHub leaves footnotes that nothing references off the page.
353
+
354
+ Reported, at `[old-setup]`:
355
+
356
+ ```markdown
357
+ See the [guide][setup].
358
+
359
+ [setup]: install.md
360
+ [old-setup]: old/install.md
361
+ ```
362
+
363
+ Not reported:
364
+
365
+ ```markdown
366
+ See the [guide][setup] and the [changelog].
367
+
368
+ [setup]: install.md
369
+ [changelog]: CHANGELOG.md
370
+ ```
371
+
372
+ ## `links/valid`
373
+
374
+ **Problem rule**, reported only. Presets: `recommended` (error). Dialects: all.
375
+ Options: none.
376
+
377
+ Reports a local link, image, wikilink, embed, or reference definition whose
378
+ target does not exist, and a fragment (`#heading`, `#^block`) that its target
379
+ does not have. The anchors that a fragment can reach depend on the dialect; see
380
+ [heading anchors](dialects.md#heading-anchors). Only a Markdown file's fragments
381
+ are checked: an image, a PDF, or a source file accepts any, such as
382
+ `#gh-dark-mode-only`, `#page=2`, or `#L10-L20`. A target that is missing or
383
+ ambiguous is reported, never guessed. A link into a directory that the CLI does
384
+ not visit, such as `dist`, or through a symbolic link is checked on disk; see
385
+ [ignored files](configuration.md#ignored-files-and-link-targets).
386
+
387
+ | Message | Meaning |
388
+ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
389
+ | `Missing local target: …` | No file matches. |
390
+ | `Ambiguous local target: …` | Several files match, such as two notes whose names differ only by case. |
391
+ | `Missing fragment in …` | The target exists but has no such heading, block, or anchor. |
392
+ | `Local target is a directory: …` | Obsidian Markdown links only; other dialects accept a link to a directory, which a site can serve. |
393
+ | `Local target is outside the vault: …` | Obsidian only: the path leaves the note's vault, where Obsidian cannot follow it. |
394
+ | `Local target could not be checked: …` | A directory that may hold it could not be read, the root is only part of a vault, or a link leaves the root. |
395
+ | `Fragment could not be checked: …` | The target exists but could not be read. |
396
+
397
+ URLs with a scheme, such as `https:`, are never fetched or checked. Outside the
398
+ Obsidian dialect, a destination that starts with `/` or contains `?` depends on
399
+ the website, and is not checked either.
400
+
401
+ In the Obsidian dialect, links resolve as in Obsidian: a path that starts with
402
+ `./` or `../` counts from the note; otherwise an exact path from the vault's
403
+ root comes first, then an exact path from the note, then a note found by its
404
+ name or by the end of its path. Several matches at the first level that finds
405
+ any are ambiguous. A wikilink never resolves to a directory, so the search goes
406
+ on to a note of that name. Note names and headings match without regard to case;
407
+ block identifiers match exactly. A heading matches by the text it shows or as
408
+ its source writes it, such as ``#`move` `` for ``### `move` ``, and
409
+ `#Setup#Mobile` names a heading below another one.
410
+
411
+ Reported when `docs/guide.md` does not exist, or has no heading named "Setup":
412
+
413
+ ```markdown
414
+ See the [guide](docs/guide.md#setup).
415
+ ```
416
+
417
+ ## `obsidian/block-reference`
418
+
419
+ **Problem rule**, reported only. Presets: `obsidian` (error). Dialects:
420
+ Obsidian. Options: none.
421
+
422
+ Reports a block identifier that a note uses more than once: `^` and Latin
423
+ letters, digits, and hyphens at the end of a paragraph or heading, or alone on
424
+ the line after a list or quote, as Obsidian defines it. A link to `#^id` can
425
+ reach only one of them.
426
+
427
+ Reported, on the second paragraph:
428
+
429
+ ```markdown
430
+ First idea. ^idea
431
+
432
+ Second idea. ^idea
433
+ ```
434
+
435
+ ## `obsidian/callout-marker`
436
+
437
+ **Style rule**, fixed by `format`. Presets: `obsidian`. Dialects: Obsidian.
438
+ Options: none.
439
+
440
+ Writes the type of an Obsidian callout in lowercase, custom types included. The
441
+ title and the body are left as written, and so is a marker written with an
442
+ escape or a character reference, such as `\[!TIP]`.
443
+
444
+ Before:
445
+
446
+ ```markdown
447
+ > [!TIP] Reading the notes
448
+ ```
449
+
450
+ After:
451
+
452
+ ```markdown
453
+ > [!tip] Reading the notes
454
+ ```
455
+
456
+ ## `obsidian/strict-line-breaks`
457
+
458
+ **Problem rule**, reported only. Presets: `obsidian`. Dialects: Obsidian.
459
+ Options: none.
460
+
461
+ Reports, once per note, that `style/wrap` leaves the note as written because the
462
+ vault's "Strict line breaks" setting is not known to be on. Without that
463
+ setting, Obsidian's Reading view shows every line break in a paragraph, so
464
+ joining or breaking lines would change what the note looks like. The setting is
465
+ `"strictLineBreaks": true` in the vault's `.obsidian/app.json`; the tool reads
466
+ it and never changes it. The finding is at line 1, and its message begins
467
+ `Obsidian's "Strict line breaks" setting is not known to be on`. See [Obsidian
468
+ vaults](obsidian.md#enable-wrapping).
469
+
470
+ ## `structure/duplicate-heading`
471
+
472
+ **Problem rule**, reported only. Presets: none. Dialects: all. Options: none.
473
+
474
+ Reports a heading with the same text as an earlier heading under the same parent
475
+ heading. Two "Setup" sections side by side make a table of contents ambiguous,
476
+ and a link to `#setup` reaches only the first. The same heading under different
477
+ parents, as in a guide with a section per platform, is not reported. Headings
478
+ are compared by their text as the reader sees it: formatting does not count,
479
+ case does. As for `structure/heading-increment`, the headings of a block quote
480
+ or a footnote are checked among themselves.
481
+
482
+ Reported:
483
+
484
+ ```markdown
485
+ # Install
486
+
487
+ ## Setup
488
+
489
+ ## Setup
490
+ ```
491
+
492
+ Not reported:
493
+
494
+ ```markdown
495
+ # Linux
496
+
497
+ ## Setup
498
+
499
+ # Windows
500
+
501
+ ## Setup
502
+ ```
503
+
504
+ ## `structure/heading-increment`
505
+
506
+ **Problem rule**, reported only. Presets: `recommended`. Dialects: all. Options:
507
+ none.
508
+
509
+ Reports a heading more than one level deeper than the heading before it, such as
510
+ a level-3 heading directly after a level-1 heading. Readers who move through a
511
+ document by its headings, with a screen reader or a table of contents, rely on
512
+ the levels to show how sections nest. The first heading may have any level.
513
+
514
+ The headings of a block quote, which is also how callouts and alerts are
515
+ written, and of a footnote are checked among themselves: a callout can start
516
+ with a level-3 heading under any heading, and its headings do not count for the
517
+ document's.
518
+
519
+ Reported:
520
+
521
+ ```markdown
522
+ # Install
523
+
524
+ ### Requirements
525
+ ```
526
+
527
+ Not reported:
528
+
529
+ ```markdown
530
+ # Install
531
+
532
+ ## Requirements
533
+
534
+ > [!NOTE]
535
+ >
536
+ > ### Older versions
537
+ ```
538
+
539
+ ## `structure/initial-heading`
540
+
541
+ **Problem rule**, reported only. Presets: none. Dialects: all. Options: none.
542
+
543
+ Requires the first block of a document, after optional YAML or TOML front
544
+ matter, to be a level-1 heading. Underlined (`===`) headings count as well as
545
+ `#` headings; [`style/heading`](#styleheading) turns them into `#` headings. An
546
+ empty document is reported. Comments and other content before the title are not
547
+ skipped. Use [overrides](configuration.md#overrides) to exempt generated
548
+ documents.
549
+
550
+ Reported:
551
+
552
+ ```markdown
553
+ Some text before the title.
554
+
555
+ # Title
556
+ ```
557
+
558
+ Not reported:
559
+
560
+ ```markdown
561
+ ---
562
+ title: Notes
563
+ ---
564
+
565
+ # Notes
566
+ ```
567
+
568
+ ## `structure/single-title`
569
+
570
+ **Problem rule**, reported only. Presets: none. Dialects: all. Options: none.
571
+
572
+ Reports a second level-1 heading in a document. A document has one title, and
573
+ further level-1 headings usually belong one level down. A `title` key in YAML or
574
+ TOML front matter counts as the title; every level-1 heading is then reported.
575
+ As for `structure/heading-increment`, the headings of a block quote or a
576
+ footnote are checked among themselves.
577
+
578
+ Reported:
579
+
580
+ ```markdown
581
+ # Install
582
+
583
+ # Configure
584
+ ```
585
+
586
+ Not reported:
587
+
588
+ ```markdown
589
+ ---
590
+ title: Install
591
+ ---
592
+
593
+ ## Requirements
594
+ ```
595
+
596
+ ## `style/blank-lines`
597
+
598
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
599
+ Options: `maximum`.
600
+
601
+ Collapses blank lines in a row to at most `maximum` of them, and removes blank
602
+ lines at the start and at the end of a document. The option `maximum` is an
603
+ integer of at least 1; the default is 1. The line break that ends the last line
604
+ stays; [`style/final-newline`](#stylefinal-newline) adds it where it is missing.
605
+ Inside a block quote, a line of only `>` markers is a blank line, and repeated
606
+ ones are removed the same way.
607
+
608
+ Before, with three blank lines between the blocks and two at the end:
609
+
610
+ ```markdown
611
+ # Setup
612
+
613
+
614
+
615
+ Install the package.
616
+
617
+
618
+ ```
619
+
620
+ After:
621
+
622
+ ```markdown
623
+ # Setup
624
+
625
+ Install the package.
626
+ ```
627
+
628
+ These blank lines are left as written, because they are content there or their
629
+ number changes what the document means:
630
+
631
+ - Inside code blocks, HTML blocks, math blocks, front matter, and Obsidian
632
+ comments, also in one that runs to the end of the document without its closing
633
+ fence or marker.
634
+ - At the start of a document, when the line below them is `---` or `+++`, which
635
+ would then open front matter.
636
+ - Next to a blank line with other block quote markers or indentation, such as
637
+ `>` next to an empty line, which belong to different block quotes.
638
+ - In a block quote, below the last block of a list, list item, or footnote that
639
+ the parser counts them toward: there it reads a list as loose when two or more
640
+ follow and as tight when one does.
641
+
642
+ ## `style/block-spacing`
643
+
644
+ **Style rule**, fixed by `format`. Presets: none. Dialects: all. Options: none.
645
+
646
+ Separates every heading and every list from the blocks before and after it with
647
+ a blank line, in the document and in block quotes at any depth. It adds one
648
+ blank line where there is none and keeps the blank lines that are already there.
649
+ Inside a block quote, the new line holds the quote's `>` markers.
650
+
651
+ Before:
652
+
653
+ ```markdown
654
+ # Setup
655
+ Install the package.
656
+ - Run the command.
657
+ ```
658
+
659
+ After:
660
+
661
+ ```markdown
662
+ # Setup
663
+
664
+ Install the package.
665
+
666
+ - Run the command.
667
+ ```
668
+
669
+ Nothing is added at the start or the end of a document, and these places are
670
+ left as written, because a blank line there would change what the document means
671
+ or what a comment applies to:
672
+
673
+ - Blocks inside a list item or a footnote definition. A blank line between the
674
+ blocks of a list item makes the list loose, which changes how it renders.
675
+ - Front matter and the block below it.
676
+ - A list that ends inside an HTML comment or another HTML block without its end
677
+ marker, which would take the blank line in.
678
+ - A heading or list directly below an HTML comment or below a
679
+ `mdtools-disable-next-line` directive, which apply to the line below them.
680
+ - The line that opens a callout or alert, such as `> [!NOTE]`, and the block
681
+ directly below it.
682
+ - In the Obsidian dialect, a block identifier on a line of its own (`^id`)
683
+ directly below a heading or list, which Obsidian may attach to the block
684
+ above.
685
+ - Directly below text or a link reference definition: a list or quote whose
686
+ first line continues with another list marker, as in `- 2. Step` or `- -`, and
687
+ a heading underlined with `===` or `---`. The parser can read such a line
688
+ differently there than below a blank line.
689
+ - Directly below a table that ends in a list item or block quote: text whose
690
+ second line is a table delimiter row. The parser reads a table there as text,
691
+ where GitHub reads a table, and a blank line would make it a table for the
692
+ parser too.
693
+ - In a block quote, below a list whose last item ends in an empty footnote
694
+ definition, such as `> - [^1]:`. The parser would count the new line of `>` as
695
+ part of the item and read the list as loose.
696
+
697
+ ## `style/code-fence`
698
+
699
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
700
+ Options: `marker`.
701
+
702
+ Writes the fences of a fenced code block with one marker, and as long as its
703
+ content allows: three characters, or one more than the longest line inside that
704
+ holds only the marker, which would otherwise close the block. The option
705
+ `marker` is ``"```"`` (the default), `"~~~"`, or `"consistent"`, which takes the
706
+ marker of the document's first fence. The info string and the content are left
707
+ as written.
708
+
709
+ Before:
710
+
711
+ ```markdown
712
+ ~~~sh
713
+ npm test
714
+ ~~~
715
+ ```
716
+
717
+ After:
718
+
719
+ ````markdown
720
+ ```sh
721
+ npm test
722
+ ```
723
+ ````
724
+
725
+ Indented code blocks have no fence and are left as written. So is a `~~~` fence
726
+ whose info string contains a backtick, because a backtick fence cannot have one.
727
+
728
+ ## `style/emphasis`
729
+
730
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
731
+ Options: `marker`.
732
+
733
+ Writes emphasis with one marker. The option `marker` is `"_"` (the default) or
734
+ `"*"`. With `_`, emphasis inside a word keeps `*`, because `_` cannot mark
735
+ emphasis there.
736
+
737
+ Before:
738
+
739
+ ```markdown
740
+ Use *emphasis* sparingly, as in un*believ*able.
741
+ ```
742
+
743
+ After:
744
+
745
+ ```markdown
746
+ Use _emphasis_ sparingly, as in un*believ*able.
747
+ ```
748
+
749
+ Markers are left as written where new ones could change how the text parses, and
750
+ so are the exceptions of [Forgejo and Gitea](dialects.md#forgejo-and-gitea):
751
+
752
+ - A new marker that would touch another `*` or `_`, or be separated from one
753
+ only by `~`.
754
+ - Text with a `*` or `_` that did not pair, as in `*a _b* c_`, or with a run of
755
+ markers that two emphases share, as in `*****a***`. There markers change only
756
+ where the rule can tell that every pair stays the same.
757
+ - The text of a collapsed or shortcut reference, such as `[*Title*][]` or
758
+ `[*Title*]`, which is also its label, and text in brackets that would match a
759
+ definition's label with the new markers.
760
+ - A marker right after a `$` on GitHub, Forgejo, and Gitea, where a `_` after
761
+ the dollar decides whether dollar math ends there.
762
+ - Emphasis that begins on the line of an alert's or a callout's marker and ends
763
+ below it.
764
+
765
+ ## `style/final-newline`
766
+
767
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
768
+ Options: none.
769
+
770
+ Ends a document that is not empty with a line break, using the document's own
771
+ line ending. A file whose last line has no line break is changed; an empty file
772
+ is not. Nothing is added where the line break would become part of the last
773
+ block: an HTML comment or another HTML block without its end marker, an Obsidian
774
+ comment without its closing `%%`, or a code or math block without its closing
775
+ fence whose last line is blank space.
776
+
777
+ ## `style/heading`
778
+
779
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
780
+ Options: `style`, `closing`.
781
+
782
+ Writes headings in one style and without closing `#` sequences. By default it
783
+ turns a heading underlined with `===` or `---` into a `#` heading of the same
784
+ level, and removes the closing sequence of a `#` heading with the blank space
785
+ around it.
786
+
787
+ | Option | Values | Default |
788
+ | --------- | ----------------------------------- | ---------- |
789
+ | `style` | `"atx"`, `"setext"`, `"consistent"` | `"atx"` |
790
+ | `closing` | `"remove"`, `"keep"` | `"remove"` |
791
+
792
+ - `style`: `atx` writes `#` headings. `setext` underlines headings of levels 1
793
+ and 2 and keeps `#` for deeper levels, which cannot be underlined.
794
+ `consistent` follows the document's first heading: `setext` when it is
795
+ underlined, otherwise `atx`.
796
+ - `closing`: `keep` leaves the closing sequences of `#` headings as written.
797
+
798
+ Before:
799
+
800
+ ```markdown
801
+ Installation
802
+ ------------
803
+
804
+ ## Usage ##
805
+ ```
806
+
807
+ After:
808
+
809
+ ```markdown
810
+ ## Installation
811
+
812
+ ## Usage
813
+ ```
814
+
815
+ A trailing run of `#` in the text of an underlined heading is escaped, so that
816
+ it is not taken for a closing sequence. Underlined headings of more than one
817
+ line, and those inside lists or block quotes, are left as written. On Forgejo
818
+ and Gitea, a closing sequence after an attribute block such as `{#id}` stays,
819
+ because Gitea before 1.26 reads the block only when the sequence follows it.
820
+
821
+ With `setext`, a `#` heading is underlined only where its text can stand on a
822
+ line of its own as the same heading: at the start of a line of the document, not
823
+ in a list or block quote, below a blank line or at the start of the document,
824
+ because directly below text its line would continue the paragraph. It keeps its
825
+ `#` when its text starts like another block, such as a list item, block quote,
826
+ thematic break, fence, HTML, or link reference definition, when it contains `|`,
827
+ which `---` below it could make a table, or when it ends with a backslash, and
828
+ on Forgejo and Gitea when it contains `{`. Below a first line of `---` that no
829
+ line closes, a level-2 underline has at least four `-`, because `---` would
830
+ close it as front matter.
831
+
832
+ ## `style/inline-code`
833
+
834
+ **Style rule**, fixed by `format`. Presets: none. Dialects: all. Options: none.
835
+
836
+ Joins a code span that is written across lines onto one line. A line break
837
+ inside a code span renders as a space, so the content stays the same, and the
838
+ spaces and tabs that start the next line are left out, as CommonMark and GitHub
839
+ leave them out. On a lazy continuation line, one without its block quote's `>`
840
+ or its list item's indentation, GitHub keeps them in the span, and so does the
841
+ joined span; commonmark.js leaves them out, so outside the GitHub dialect such a
842
+ span stays split. Some editors, such as Obsidian's Live Preview, show a split
843
+ code span differently from the rendered page. `style/wrap` joins such a code
844
+ span only in a paragraph that it wraps, and this rule also elsewhere, such as in
845
+ a paragraph with a hard line break. The exceptions of [Forgejo and
846
+ Gitea](dialects.md#forgejo-and-gitea) apply, and a span stays split where the
847
+ joined line would read differently:
848
+
849
+ - In Obsidian, where an `==` or `[[` left as text on the joined lines could open
850
+ a highlight or wikilink.
851
+ - Where joining would move text onto the line of an alert's or a callout's
852
+ marker, which holds an Obsidian callout's title.
853
+ - Where the joined span needs a different number of backticks than it has, and
854
+ an earlier run of that many in the same paragraph would pair with them.
855
+
856
+ Before:
857
+
858
+ ```markdown
859
+ Run `npm run
860
+ build` before the tests.
861
+ ```
862
+
863
+ After:
864
+
865
+ ```markdown
866
+ Run `npm run build` before the tests.
867
+ ```
868
+
869
+ ## `style/list-indent`
870
+
871
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
872
+ Options: spaces after markers, `nestedIndent`.
873
+
874
+ Puts the configured spaces, one by default, between a list marker and the item's
875
+ text, and starts each item where its container's text starts: at the start of
876
+ the line, after a block quote's `>`, or under the text of the list item that
877
+ holds it. The item's other lines move by as many columns as its text, so its
878
+ paragraphs, code blocks, and nested lists stay inside it as they were.
879
+
880
+ | Option | Values | Default |
881
+ | ------------------------ | ---------------------- | --------------------- |
882
+ | `bulletSpaces` | An integer from 1 to 4 | `1` |
883
+ | `orderedSpaces` | An integer from 1 to 4 | `1` |
884
+ | `bulletSpacesMultiline` | An integer from 1 to 4 | `bulletSpaces` |
885
+ | `orderedSpacesMultiline` | An integer from 1 to 4 | `orderedSpaces` |
886
+ | `nestedIndent` | An integer from 1 to 8 | Under the item's text |
887
+
888
+ - `bulletSpaces` and `orderedSpaces`: the spaces after the marker of a bullet
889
+ item and of a numbered one. As in markdownlint's MD030, the `Multiline`
890
+ options take their place in a list where an item has more than one line or
891
+ blank lines separate the items.
892
+ - `nestedIndent`: the columns from an item's marker to the marker of a list
893
+ nested in it, like markdownlint's MD007 `indent`. A nested marker can stand
894
+ from its item's text to three columns further, and the rule keeps it there:
895
+ `4` puts it two columns in under `- item` and one under `1. item`. A nested
896
+ list that starts on its item's line, as in `- - item`, stays there, and one
897
+ that follows another list stays out of that list's last item.
898
+
899
+ With the defaults, before:
900
+
901
+ ```markdown
902
+ - Unpack the board.
903
+
904
+ Keep the box for returns.
905
+ 1. Connect the sensor.
906
+ - Use the short cable.
907
+ ```
908
+
909
+ After:
910
+
911
+ ```markdown
912
+ - Unpack the board.
913
+
914
+ Keep the box for returns.
915
+ 1. Connect the sensor.
916
+ - Use the short cable.
917
+ ```
918
+
919
+ These are left as written:
920
+
921
+ - An item that starts with indented code, five or more spaces after the marker;
922
+ the code depends on that spacing.
923
+ - A list where moving an item would move another line into it. Here `Text`
924
+ follows the list, and below `- Item` it would be the item's second paragraph:
925
+
926
+ ```markdown
927
+ - Item
928
+
929
+ Text
930
+ ```
931
+
932
+ The same goes for a line that continues the item's paragraph without the
933
+ item's indentation, where that line would start a list, a code span, or
934
+ another block once inside the item.
935
+ - A list with a tab in an item's indentation, such as one that Obsidian indented
936
+ with tabs.
937
+
938
+ ## `style/list-marker`
939
+
940
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
941
+ Options: `marker`.
942
+
943
+ Writes every bullet list with one marker.
944
+
945
+ | Option | Values | Default |
946
+ | -------- | --------------------------------------------------- | ------- |
947
+ | `marker` | `"-"`, `"*"`, `"+"`, `"consistent"`, or `"sublist"` | `"-"` |
948
+
949
+ - `consistent`: the marker of the document's first bullet list, as in
950
+ markdownlint's MD004.
951
+ - `sublist`: each level of nesting keeps the marker of its first list, unless
952
+ the level above has that marker, in which case it gets the next one, as with
953
+ MD004's `sublist`. A level counts the bullet lists that a list is nested in.
954
+
955
+ A bullet list that directly follows another one is a separate list only because
956
+ its marker differs, so it gets the next marker in the order `-`, `*`, `+`, and
957
+ the list after that the first one again. A list whose new marker would make a
958
+ line read as a thematic break, as `+ - -` would with `-`, keeps its markers, and
959
+ so do the lists next to it.
960
+
961
+ Before:
962
+
963
+ ```markdown
964
+ * Milk
965
+ * Bread
966
+
967
+ + Plates
968
+ ```
969
+
970
+ After:
971
+
972
+ ```markdown
973
+ - Milk
974
+ - Bread
975
+
976
+ * Plates
977
+ ```
978
+
979
+ ## `style/ordered-list`
980
+
981
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
982
+ Options: `delimiter`, `numbering`.
983
+
984
+ Writes the numbers of ordered lists with one delimiter and numbers the items
985
+ consistently.
986
+
987
+ | Option | Values | Default |
988
+ | ----------- | ---------------------------------- | -------- |
989
+ | `delimiter` | `"."`, `")"`, or `"consistent"` | `"."` |
990
+ | `numbering` | `"auto"`, `"ordered"`, or `"same"` | `"auto"` |
991
+
992
+ - `delimiter`: `consistent` is the delimiter of the document's first ordered
993
+ list. As with bullet markers, an ordered list that directly follows another
994
+ one keeps a different delimiter.
995
+ - `numbering`: `ordered` counts up from the first number, and `same` repeats it
996
+ in every item. `auto` repeats it when the first two items have the same
997
+ number, as in `1.`, `1.`, `1.`, and counts up otherwise. These are
998
+ markdownlint's MD029 `one_or_ordered`, `ordered`, and, for lists that start at
999
+ 1 or 0, `one` and `zero`.
1000
+
1001
+ The first number never changes, because the rendered list starts at it. When a
1002
+ number gets wider or narrower, as from `9.` to `10.`, the item's other lines
1003
+ move with its text. A list keeps its numbers where that would move a line into
1004
+ or out of an item, as for [`style/list-indent`](#stylelist-indent), and where
1005
+ the numbers are written with leading zeros, as in `01.`, or would need more than
1006
+ nine digits.
1007
+
1008
+ Before:
1009
+
1010
+ ```markdown
1011
+ 1) Unpack the board.
1012
+ 2) Connect the sensor.
1013
+ 2) Power it on.
1014
+ ```
1015
+
1016
+ After:
1017
+
1018
+ ```markdown
1019
+ 1. Unpack the board.
1020
+ 2. Connect the sensor.
1021
+ 3. Power it on.
1022
+ ```
1023
+
1024
+ ## `style/strong`
1025
+
1026
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
1027
+ Options: `marker`.
1028
+
1029
+ Writes strong emphasis with one marker. The option `marker` is `"*"` (the
1030
+ default) or `"_"`. The exceptions of `style/emphasis` apply.
1031
+
1032
+ Before:
1033
+
1034
+ ```markdown
1035
+ A __bold__ claim.
1036
+ ```
1037
+
1038
+ After:
1039
+
1040
+ ```markdown
1041
+ A **bold** claim.
1042
+ ```
1043
+
1044
+ ## `style/table`
1045
+
1046
+ **Style rule**, fixed by `format`. Presets: `recommended`, `github`, `forgejo`,
1047
+ `gitea`, `obsidian`. Dialects: all but CommonMark. Options: `style`.
1048
+
1049
+ Aligns a table: every cell of a column is padded to the column's width, measured
1050
+ in display columns, and the delimiter row keeps each column's alignment. The
1051
+ option `style` is `"aligned"` (the default) or `"compact"`, which writes one
1052
+ space on each side of a cell's text and delimiters of three characters, such as
1053
+ `| :-- | --: |`. The text of each cell is left as written, and so is the number
1054
+ of cells in each row. A table inside a list or block quote, and one with a row
1055
+ that has more cells than its header, are left as written.
1056
+
1057
+ Before:
1058
+
1059
+ ```markdown
1060
+ | Sensor | Unit |
1061
+ |:--|--:|
1062
+ | Temperature | °C |
1063
+ ```
1064
+
1065
+ After:
1066
+
1067
+ ```markdown
1068
+ | Sensor | Unit |
1069
+ | :---------- | ---: |
1070
+ | Temperature | °C |
1071
+ ```
1072
+
1073
+ ## `style/thematic-break`
1074
+
1075
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
1076
+ Options: `marker`.
1077
+
1078
+ Writes thematic breaks with one marker. The option `marker` is `"---"` (the
1079
+ default), `"***"`, `"___"`, or `"consistent"`, which takes the character of the
1080
+ document's first break. Blank space before and after the break stays.
1081
+
1082
+ Before:
1083
+
1084
+ ```markdown
1085
+ Text.
1086
+
1087
+ * * *
1088
+ ```
1089
+
1090
+ After:
1091
+
1092
+ ```markdown
1093
+ Text.
1094
+
1095
+ ---
1096
+ ```
1097
+
1098
+ A break is left as written where the new marker would change what the document
1099
+ means:
1100
+
1101
+ - With `---`, directly below a paragraph or a link reference definition, which
1102
+ `---` would underline as a heading.
1103
+ - On the line of a list item whose marker is the new marker's character, as in
1104
+ `- ***` with `---`: `- ---` is one thematic break, not a list item.
1105
+ - At the start of a document, with `---`, which would open front matter if a
1106
+ later line of `---` closed it, and a `---` that site generators read as the
1107
+ start of front matter.
1108
+ - With `---`, at the start of a line below a first line of `---` that no line
1109
+ closes, which `---` would close as front matter.
1110
+
1111
+ ## `style/trailing-space`
1112
+
1113
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
1114
+ Options: `hardBreak`.
1115
+
1116
+ Removes spaces and tabs at the end of lines. A hard line break written as two or
1117
+ more spaces keeps them. The option `hardBreak` is `"keep"` (the default) or
1118
+ `"backslash"`, which writes such a break as a backslash, so that it is visible
1119
+ in the source.
1120
+
1121
+ With `{ "hardBreak": "backslash" }`, before, with two spaces after `one`:
1122
+
1123
+ ```markdown
1124
+ Line one
1125
+ line two
1126
+ ```
1127
+
1128
+ After:
1129
+
1130
+ ```markdown
1131
+ Line one\
1132
+ line two
1133
+ ```
1134
+
1135
+ Blank space is left as written where it is content: in code blocks, except on
1136
+ their fence lines, and in HTML, math, front matter, Obsidian comments, code
1137
+ spans, and link titles and labels that span lines. With `"backslash"`, a break
1138
+ stays as spaces where a backslash would change what the line says: after another
1139
+ backslash, after a literal autolink such as `www.example.com`, which would take
1140
+ the backslash into its address, on the title line of an alert or callout, in a
1141
+ paragraph that starts like a link reference definition (`[label]:`), and on
1142
+ Forgejo and Gitea inside `\(...\)` math.
1143
+
1144
+ ## `style/wrap`
1145
+
1146
+ **Style rule**, fixed by `format`. Presets: `recommended`. Dialects: all.
1147
+ Options: `width`, `measure`, `reportUnreflowed`, `reportUnbreakable`.
1148
+
1149
+ Reflows each paragraph so that its lines fill the width without exceeding it. A
1150
+ line break inside a paragraph renders as a space, so the rendered text stays the
1151
+ same, and short lines keep diffs small. Lines are broken at spaces in the text,
1152
+ also in the text of a link, emphasis, strong text, or strikethrough. A code
1153
+ span, an image, math, a link's destination, a template tag on one line such as
1154
+ `{% data x %}` or `{{ title }}`, and a word longer than the line stay whole and
1155
+ can overflow; a code span or an image description written across lines is joined
1156
+ onto one, without the spaces and tabs that start its next line, as renderers
1157
+ read it. In Obsidian, the text of a link stays whole and is joined onto one line
1158
+ too, because Live Preview shows a link whose text spans lines as its Markdown
1159
+ source. List markers, block quote markers, and indentation count toward the
1160
+ width, a tab up to the next multiple of four columns.
1161
+
1162
+ A word that would start a block at the start of a line, such as a list marker,
1163
+ `#`, `>`, a run of `-` or `=`, or a table delimiter row such as `|---|`, stays
1164
+ on the line before it, and so does a word that starts with `:::`, `{%`, or `{{`.
1165
+ A word that only starts like one, such as `--config`, `#tag`, or `-5`, can start
1166
+ a line. The first line keeps more than one word when its first word alone would
1167
+ open a block, such as `***` or `$$`, or, in the body below the line of an
1168
+ alert's or callout's marker, would underline that line as a heading, such as
1169
+ `==` or `--`. It also keeps a paragraph that starts like a link reference
1170
+ definition (`[Note]: see …`) from becoming one. On GitHub and in Obsidian, a
1171
+ word that starts with `$` stays on the line before it when a `$` comes earlier
1172
+ in the paragraph, and in Obsidian a word that ends in `$`, such as a lone `$`,
1173
+ stays on the line after it when a `$` comes later: at the edge of a line, a
1174
+ dollar can begin or end math that it cannot begin or end next to a space.
1175
+
1176
+ | Option | Values | Default |
1177
+ | ------------------- | ----------------------------- | ----------- |
1178
+ | `width` | An integer from 20 to 500 | `80` |
1179
+ | `measure` | `"columns"` or `"codepoints"` | `"columns"` |
1180
+ | `reportUnreflowed` | `true` or `false` | `false` |
1181
+ | `reportUnbreakable` | `true` or `false` | `false` |
1182
+
1183
+ - `measure`: `columns` counts display columns, so a wide character such as `漢`
1184
+ counts two. `codepoints` counts Unicode code points: a character outside the
1185
+ Basic Multilingual Plane counts once, and a combining mark counts by itself.
1186
+ - `reportUnreflowed`: report a paragraph that is too wide but left as written,
1187
+ with the reason.
1188
+ - `reportUnbreakable`: report a line that stays too wide because of something
1189
+ that cannot be split, also in paragraphs left as written. The line of an
1190
+ alert's or a callout's marker counts as one such piece, even when it contains
1191
+ spaces.
1192
+
1193
+ The two report options propose no edits and use the rule's severity. To make
1194
+ them fail a check, set the rule to `error` or pass `--max-warnings 0`;
1195
+ `format --check` checks only for edits.
1196
+
1197
+ A paragraph is left as written when joining or breaking its lines could change
1198
+ what it means, that is, when it:
1199
+
1200
+ - has a hard line break, inline HTML, or a block identifier (`^id`) at its end;
1201
+ - has a line break that is content, inside math, inline HTML, an Obsidian
1202
+ comment, or a link's destination or title;
1203
+ - has lines whose container markers the tool cannot reproduce;
1204
+ - opens a block quote with an alert or callout marker such as `[!NOTE]` in the
1205
+ CommonMark dialect; in the other dialects only the line with the marker, and
1206
+ an Obsidian callout's title on it, stays as it is, and the body is wrapped. A
1207
+ paragraph elsewhere that starts with a linked image, `[![…](…)](…)`, is
1208
+ wrapped;
1209
+ - starts with a bare `-`, `+`, `*`, `1.`, `1)`, `#`, or `>` followed by more
1210
+ words, which joining would turn into a block;
1211
+ - starts directly below a link reference definition without that definition's
1212
+ container markers;
1213
+ - has a table delimiter row such as `| - |` as its second line, in the dialects
1214
+ with tables: such a paragraph is usually a table that the parser reads as text
1215
+ (see [the safety model](design.md#safety-model));
1216
+ - has a line that starts with `:::`, `{%`, or `{{`, which [site
1217
+ generators](dialects.md#what-each-dialect-reads) read by line;
1218
+ - holds, in the Obsidian dialect, `==`, `[[`, or `]]` outside its highlights and
1219
+ wikilinks, because joining lines could create one.
1220
+
1221
+ In the Obsidian dialect, the rule wraps only with the vault's [strict line
1222
+ breaks](obsidian.md#enable-wrapping). [Forgejo and
1223
+ Gitea](dialects.md#forgejo-and-gitea) add their own cases.
1224
+
1225
+ With `{ "width": 40 }`, before:
1226
+
1227
+ ```markdown
1228
+ Wrapping keeps lines short, so that a change to one sentence shows up as a small diff.
1229
+ ```
1230
+
1231
+ After:
1232
+
1233
+ ```markdown
1234
+ Wrapping keeps lines short, so that a
1235
+ change to one sentence shows up as a
1236
+ small diff.
1237
+ ```