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/configuration.md
CHANGED
|
@@ -1,238 +1,192 @@
|
|
|
1
|
-
# Configuration
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
One configuration controls both `lint` and `format`. Without a configuration
|
|
4
|
+
file, the `recommended` preset applies and the dialect is
|
|
5
|
+
[assumed](dialects.md#the-assumed-dialect).
|
|
6
|
+
|
|
7
|
+
## Configuration files
|
|
8
|
+
|
|
9
|
+
The file is named `mdtools.config.jsonc`, `mdtools.config.json`,
|
|
10
|
+
`mdtools.config.mjs`, `mdtools.config.js`, or `mdtools.config.cjs`. The CLI
|
|
11
|
+
looks for it in the directory given with `--root`, or else the current
|
|
12
|
+
directory, and then in each directory above, up to the first one that is a Git
|
|
13
|
+
repository (holds `.git`) or an Obsidian vault (holds `.obsidian`), or the
|
|
14
|
+
filesystem root. Two configuration files in one directory are an error.
|
|
15
|
+
`--config` names a file explicitly. The directory of the configuration file is
|
|
16
|
+
the workspace root unless `--root` names another; without a configuration file,
|
|
17
|
+
it is the repository or vault where the search stopped, or else the current
|
|
18
|
+
directory. Configuration files do not cascade: a file in a subdirectory is not
|
|
19
|
+
merged with one above it.
|
|
20
|
+
|
|
21
|
+
JSONC allows comments and trailing commas. A JSON or JSONC file may start with a
|
|
22
|
+
byte order mark, and a syntax error in one is reported with its line and column.
|
|
23
|
+
A JavaScript file exports the configuration as its default export, or as
|
|
24
|
+
`module.exports` in CommonJS; Node.js reads an `.mjs` file as an ES module, a
|
|
25
|
+
`.cjs` file as CommonJS, and a `.js` file as the nearest `package.json` declares
|
|
26
|
+
with `type`, or by its syntax when none does. JavaScript configuration and
|
|
27
|
+
plugins run with your permissions, so load only code you trust. Unknown keys,
|
|
28
|
+
rule IDs, and preset names are errors, and so are rule options that the rule
|
|
29
|
+
does not accept; the message names the setting, as in
|
|
30
|
+
`"extends[1]" must be a preset name, not 5`.
|
|
2
31
|
|
|
3
|
-
|
|
32
|
+
```jsonc
|
|
33
|
+
{
|
|
34
|
+
"extends": ["recommended", "github"],
|
|
35
|
+
"ignore": ["generated/**"],
|
|
36
|
+
"rules": { "style/wrap": ["warn", { "width": 100 }] },
|
|
37
|
+
"overrides": [
|
|
38
|
+
{ "files": ["vault/**/*.md"], "rules": { "style/emphasis": "off" } },
|
|
39
|
+
],
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
| Key | Value | Purpose |
|
|
44
|
+
| ----------- | ---------------------------------------------- | -------------------------------------------------------------------- |
|
|
45
|
+
| `$schema` | A string | Ignored by the tool; gives an editor the [JSON Schema](#json-schema) |
|
|
46
|
+
| `extends` | A preset name or a list of them | [Presets](#presets) to start from |
|
|
47
|
+
| `dialect` | A [dialect](dialects.md) name | The renderer whose syntax documents are read in |
|
|
48
|
+
| `rules` | Rule IDs and settings | [Rules and severity](#rules-and-severity) |
|
|
49
|
+
| `overrides` | Objects with `files`, and `dialect` or `rules` | [Settings for some files](#overrides) |
|
|
50
|
+
| `ignore` | Path patterns | [Documents not to process](#ignored-files-and-link-targets) |
|
|
51
|
+
| `resolve` | `{ "gitIgnored": …, "nestedRepositories": … }` | [More link targets](#ignored-files-and-link-targets) |
|
|
52
|
+
| `plugins` | Files or package names | [Plugins](#plugins) to load |
|
|
53
|
+
|
|
54
|
+
### JSON Schema
|
|
4
55
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
configuration directory is the workspace root unless `--root` overrides it.
|
|
56
|
+
The configuration's JSON Schema lets an editor that reads JSON Schemas, such as
|
|
57
|
+
Visual Studio Code, complete and check the settings. The package ships it as
|
|
58
|
+
`config.schema.json`, matching the installed version; name it with `$schema`,
|
|
59
|
+
relative to the configuration file:
|
|
10
60
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
61
|
+
```jsonc
|
|
62
|
+
{
|
|
63
|
+
"$schema": "./node_modules/mdrefine/config.schema.json",
|
|
64
|
+
"extends": ["recommended", "github"],
|
|
65
|
+
}
|
|
66
|
+
```
|
|
15
67
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
68
|
+
The documentation site serves the schema of the version it documents at
|
|
69
|
+
`https://viell-dev.github.io/slop-markdown-tools/config.schema.json`, an address
|
|
70
|
+
that stays the same. In a JavaScript configuration file, a type annotation in a
|
|
71
|
+
comment gives an editor the same help:
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
/** @type {import("mdrefine").Config} */
|
|
75
|
+
export default { extends: ["recommended", "github"] };
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The schema describes the form of each setting. Rule IDs, preset names, and rule
|
|
79
|
+
options are checked when the tool runs, against the rules and presets of the
|
|
80
|
+
loaded plugins. The library exports the same schema as
|
|
81
|
+
[`configSchema`](api.md#other-exports).
|
|
82
|
+
|
|
83
|
+
## Presets
|
|
21
84
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
85
|
+
A **preset** is a named set of rule settings. The **dialect** is a separate
|
|
86
|
+
setting: it names the renderer whose syntax documents are read in, such as
|
|
87
|
+
GitHub's or Obsidian's, and so decides what counts as a table, a link, or a line
|
|
88
|
+
break. Each preset except `recommended` also sets a dialect. The
|
|
89
|
+
[rules](rules.md) page shows which presets enable each rule.
|
|
90
|
+
|
|
91
|
+
Presets are starting points with opinionated defaults, not a fixed style. Every
|
|
92
|
+
rule can be turned off or given another severity, and a rule whose choice
|
|
93
|
+
documents reasonably differ on, such as the emphasis marker or the wrapping
|
|
94
|
+
width, takes options for it; the [rules](rules.md) list them with their
|
|
95
|
+
defaults.
|
|
96
|
+
|
|
97
|
+
| Preset | Sets the dialect | For |
|
|
98
|
+
| ------------- | ---------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
99
|
+
| `recommended` | No | Any document: wrapping at 80 columns, markers, blank space, tables, valid links, problems that show on the page |
|
|
100
|
+
| `github` | `github` | Documents rendered by GitHub |
|
|
101
|
+
| `forgejo` | `forgejo` | Documents rendered by Forgejo, such as on Codeberg |
|
|
102
|
+
| `codeberg` | `forgejo` | The `forgejo` preset under another name |
|
|
103
|
+
| `gitea` | `gitea` | Documents rendered by Gitea |
|
|
104
|
+
| `obsidian` | `obsidian` | An Obsidian vault |
|
|
105
|
+
|
|
106
|
+
Without `extends`, the configuration starts from `recommended`. `extends` names
|
|
107
|
+
one preset or lists several, and replaces that default, so name both, as in
|
|
108
|
+
`["recommended", "github"]`; `"extends": "github"` starts from `github` alone,
|
|
109
|
+
and `"extends": []` enables no rules. Presets apply in the order listed, then
|
|
110
|
+
the configuration's own settings, then each matching override in order. A later
|
|
111
|
+
setting for a rule replaces an earlier one as a whole, options included. A
|
|
112
|
+
plugin's presets are named with the plugin's name as a prefix, such as
|
|
113
|
+
`sample/recommended`, and presets may extend other presets; a cycle is an error.
|
|
114
|
+
|
|
115
|
+
## Rules and severity
|
|
116
|
+
|
|
117
|
+
A rule's setting is its severity, `"off"`, `"warn"`, or `"error"`, or a list of
|
|
118
|
+
the severity and the rule's options, as in `["warn", { "width": 100 }]`; a list
|
|
119
|
+
of the severity alone, `["warn"]`, keeps the rule's default options. The [rules
|
|
120
|
+
reference](rules.md) lists every rule and its options.
|
|
121
|
+
|
|
122
|
+
`format` applies the edits of every enabled style rule, whether its severity is
|
|
123
|
+
`warn` or `error`. Problem rules only report. Errors make `lint` and `format`
|
|
124
|
+
exit with code `1`; warnings do so only beyond `--max-warnings`.
|
|
125
|
+
|
|
126
|
+
## Dialect
|
|
127
|
+
|
|
128
|
+
`dialect` sets the dialect of every document, and an override can set another
|
|
129
|
+
for some of them. `codeberg` is accepted as another name for `forgejo`.
|
|
130
|
+
`--dialect` on the command line replaces the dialect of the configuration and
|
|
131
|
+
its presets, though not one set by a matching override. When neither the
|
|
132
|
+
configuration, its presets and overrides, nor `--dialect` names one, the dialect
|
|
133
|
+
is [assumed](dialects.md#the-assumed-dialect).
|
|
134
|
+
|
|
135
|
+
## Overrides
|
|
136
|
+
|
|
137
|
+
Each entry of `overrides` applies its `dialect` and `rules` to the documents
|
|
138
|
+
that match one of its `files` patterns:
|
|
25
139
|
|
|
26
140
|
```jsonc
|
|
27
141
|
{
|
|
28
142
|
"extends": ["recommended", "github"],
|
|
29
|
-
"ignore": ["generated/**"],
|
|
30
143
|
"overrides": [
|
|
31
144
|
{
|
|
32
|
-
"files": ["
|
|
33
|
-
"
|
|
34
|
-
"rules": { "style/emphasis": "off" },
|
|
145
|
+
"files": ["CHANGELOG.md", "generated/**"],
|
|
146
|
+
"rules": { "style/wrap": "off" },
|
|
35
147
|
},
|
|
36
148
|
],
|
|
37
149
|
}
|
|
38
150
|
```
|
|
39
151
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
with
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
[Obsidian vaults](obsidian.md#vaults-that-are-not-the-workspace-root).
|
|
47
|
-
|
|
48
|
-
## Dialects
|
|
49
|
-
|
|
50
|
-
`dialect` selects the renderer whose rules apply: `commonmark`, `github`,
|
|
51
|
-
`forgejo`, `gitea`, or `obsidian`. `codeberg` is an alias for `forgejo`, because
|
|
52
|
-
Codeberg runs Forgejo's renderer; aliases are accepted wherever a dialect is
|
|
53
|
-
named and resolve to the canonical name in `config explain` and plugin
|
|
54
|
-
documents.
|
|
55
|
-
|
|
56
|
-
When nothing names a dialect, the tool assumes one. That is the case without a
|
|
57
|
-
configuration file, and with a configuration in which no `dialect` setting,
|
|
58
|
-
preset, or matching override names one, unless `--dialect` is passed. A named
|
|
59
|
-
dialect always takes precedence. Version 0.2.0-rc.1 and earlier assumed
|
|
60
|
-
`commonmark` everywhere.
|
|
61
|
-
|
|
62
|
-
- For a document inside an Obsidian vault, the assumed dialect is `obsidian`.
|
|
63
|
-
Obsidian shows a single line break as a line break unless the vault's "Strict
|
|
64
|
-
line breaks" setting is on, so no other dialect can reflow a note safely. A
|
|
65
|
-
vault is a folder that contains a `.obsidian` folder, and a document belongs
|
|
66
|
-
to the nearest vault at or above its own folder. That can be the workspace
|
|
67
|
-
root, a folder below it, or a folder above it when a folder of a vault is used
|
|
68
|
-
as the root. The search upward ends at a repository, a folder that contains
|
|
69
|
-
`.git`: documents of a repository checked out inside a vault are not read as
|
|
70
|
-
the vault's notes, just as the tool leaves a repository inside a workspace
|
|
71
|
-
alone.
|
|
72
|
-
- For every other document, it is `github`. GitHub's syntax is the common base
|
|
73
|
-
of the Forgejo, Gitea, and Obsidian dialects, so tables and footnotes are
|
|
74
|
-
recognized instead of being reflowed as ordinary paragraphs.
|
|
75
|
-
|
|
76
|
-
Only the dialect is assumed: the rules of the `github` and `obsidian` presets,
|
|
77
|
-
such as table alignment, still need the preset. For documents that are plain
|
|
78
|
-
CommonMark, name the dialect with `"dialect": "commonmark"` or
|
|
79
|
-
`--dialect commonmark`.
|
|
80
|
-
|
|
81
|
-
Text between dollar signs is read as math under the conditions of the dialect's
|
|
82
|
-
renderer, so that sums of money are not taken for a formula. Math is never
|
|
83
|
-
restyled, and no line is broken inside it.
|
|
84
|
-
|
|
85
|
-
- On GitHub, Forgejo, and Gitea, `$…$` is math only when the opening `$` does
|
|
86
|
-
not follow a letter or digit, and the next `$` is not followed by a letter, a
|
|
87
|
-
digit, or `_`. `Costs $5 and $6` is prose; `From $5 to 10$` is math, as it is
|
|
88
|
-
to all three renderers.
|
|
89
|
-
- GitHub also wants a single `$` to touch its formula: no space after the
|
|
90
|
-
opening one and none before the closing one. `$ x $` is math on Forgejo and
|
|
91
|
-
Gitea and prose on GitHub.
|
|
92
|
-
- In Obsidian, the opening `$` may not be followed by a space, and a `$` closes
|
|
93
|
-
the formula only if no space stands before it and no digit follows it. Letters
|
|
94
|
-
and digits before the opening `$` do not matter there. `Costs $5 and $6` is
|
|
95
|
-
prose, and so is `$ x $`; `a$x$b` holds a formula, which it does on none of
|
|
96
|
-
the other three.
|
|
97
|
-
- Display math, between lines of `$$` or in a `math` code block, is the same in
|
|
98
|
-
every dialect.
|
|
99
|
-
|
|
100
|
-
Where a renderer is stricter than this, the tool stays on the careful side: it
|
|
101
|
-
also protects a formula with emphasis inside, which GitHub does not render, and
|
|
102
|
-
one that runs over a line break, which Forgejo and Gitea do not. Obsidian's two
|
|
103
|
-
views differ in two cases, and the tool follows the one that shows more as a
|
|
104
|
-
formula, Reading view: in `A $5 and $x$` it protects everything from the first
|
|
105
|
-
`$` to the last, where Live Preview shows only `$x$` as the formula, and it
|
|
106
|
-
protects a formula that runs over a line break, which Live Preview does not
|
|
107
|
-
render. GitHub accepts an escaped `\$` as the start of a formula; the tool does
|
|
108
|
-
not. Versions up to `0.2.0-rc.1` read any text between two `$` signs as math in
|
|
109
|
-
every dialect.
|
|
110
|
-
|
|
111
|
-
GitHub and Forgejo share tables, task lists, strikethrough, footnotes, literal
|
|
112
|
-
autolinks, `$` math, and the five `[!NOTE]`-style alert types. Forgejo
|
|
113
|
-
additionally renders definition lists (`Term` followed by a line starting with
|
|
114
|
-
`: `), `\(...\)` and `\[...\]` math, and `[[target|text]]` shortlinks, and
|
|
115
|
-
generates heading anchors differently: every run of characters other than
|
|
116
|
-
letters, numbers, and `_` becomes one hyphen, so `## test.0.1` is `#test-0-1` on
|
|
117
|
-
Forgejo and `#test01` on GitHub. The Forgejo dialect keeps those constructs on
|
|
118
|
-
their original lines, leaves emphasis markers and code spans inside `\(...\)`
|
|
119
|
-
unchanged, and validates fragments against Forgejo anchors. The GitHub rules
|
|
120
|
-
apply to both dialects.
|
|
121
|
-
|
|
122
|
-
Gitea, from which Forgejo was forked, renders the same definition lists and
|
|
123
|
-
shortlinks. It parses `\(...\)` and `\[...\]` math only when an administrator
|
|
124
|
-
enables them with `MATH_CODE_BLOCK_DETECTION`, as was the default before
|
|
125
|
-
Gitea 1.24; a document cannot reveal that setting, so the Gitea dialect keeps
|
|
126
|
-
those constructs on their lines too. Gitea's heading anchors follow GitHub's:
|
|
127
|
-
punctuation is deleted, so `## test.0.1` is `#test01`. Gitea 1.26 and later give
|
|
128
|
-
repeated headings the same anchor; the `-1`, `-2` suffixes of earlier versions
|
|
129
|
-
are still accepted. Gitea 1.26 and later also render `__init__.py` literally
|
|
130
|
-
instead of as emphasis, including in headings, whose anchor is then
|
|
131
|
-
`#__init__py`. Whether underscores delimit emphasis depends on the rest of the
|
|
132
|
-
line, so on a line containing `_.py` the Gitea dialect leaves emphasis markers
|
|
133
|
-
unchanged and keeps link destinations whose rewrite would change their
|
|
134
|
-
underscores. It does not reflow such a paragraph unless all its underscores are
|
|
135
|
-
inside code spans and it contains no `$` or `\(` math. The GitHub rules apply to
|
|
136
|
-
Gitea as well. Gitea renders repository files with soft line breaks by default;
|
|
137
|
-
if an instance adds `new-line-hard-break` to `RENDER_OPTIONS_REPO_FILE`, disable
|
|
138
|
-
`style/wrap`.
|
|
139
|
-
|
|
140
|
-
Forgejo, and Gitea before 1.26, build a heading's anchor from the source of its
|
|
141
|
-
last line as written, before any Markdown in it is read. Link destinations,
|
|
142
|
-
image syntax, emphasis markers, character references, and inline HTML tags are
|
|
143
|
-
part of the anchor, and a heading underlined with `===` or `---` gets the anchor
|
|
144
|
-
of its last text line only. `## Link [text](https://example.com/page) end` is
|
|
145
|
-
`#link-text-https-example-com-page-end` on Forgejo and
|
|
146
|
-
`#link-texthttpsexamplecompage-end` on Gitea 1.25, `## Strong __init__ end` is
|
|
147
|
-
`#strong-__init__-end` on both, and `## A <span>B</span>` is `#a-span-b-span`
|
|
148
|
-
and `#a-spanbspan`. The opening and closing `#` sequences, the blank space
|
|
149
|
-
around the text, block quote and list prefixes, and a trailing attribute block
|
|
150
|
-
are not part of the line. GitHub, and Gitea 1.26 and later, build the anchor
|
|
151
|
-
from the rendered text instead: `#link-text-end`, `#strong-init-end`, and
|
|
152
|
-
`#a-b`, with the text of every line of an underlined heading. GitHub keeps the
|
|
153
|
-
tags that it shows as text, such as `<script>`, in the anchor; Gitea 1.26 and
|
|
154
|
-
later show `<script>`, `<style>`, `<html>`, and `<head>` as text and keep them
|
|
155
|
-
too, drop other tags they do not allow while keeping the text inside, and read a
|
|
156
|
-
hard line break as a line break. The Gitea dialect accepts the anchors of both
|
|
157
|
-
Gitea generations.
|
|
158
|
-
|
|
159
|
-
Forgejo and Gitea read a `{...}` block that ends a heading as attributes instead
|
|
160
|
-
of text. `## Install {#setup}` renders as "Install" with the anchor `#setup` and
|
|
161
|
-
no `#install`; `## Usage {.note}` keeps the generated anchor `#usage`. The
|
|
162
|
-
Forgejo and Gitea dialects validate fragments against those anchors. A block
|
|
163
|
-
holds `#id`, `.class`, and `name=value` items, such as
|
|
164
|
-
`{#setup .note data-level=2}`, and ends the heading's line or, in a heading
|
|
165
|
-
underlined with `===` or `---`, its last text line; after a closing `#` sequence
|
|
166
|
-
it still counts (`## Install ## {#setup}`). A block that is not valid, that is
|
|
167
|
-
followed by more text, or whose `{` is escaped with a backslash stays heading
|
|
168
|
-
text. A custom anchor must be linked exactly as written, including its case, and
|
|
169
|
-
it is never numbered: a later `## Setup` heading is also `#setup`, not
|
|
170
|
-
`#setup-1`. GitHub and Obsidian show the block as text, so the other dialects
|
|
171
|
-
keep it in heading anchors and heading names. An `id` that is not text, such as
|
|
172
|
-
`{id=5}`, `{id=true}`, or a list, has no anchor on Gitea 1.26 and later, and
|
|
173
|
-
Forgejo, and Gitea before 1.26, render nothing for the whole document; the
|
|
174
|
-
Forgejo and Gitea presets report it with `forgejo/heading-id`. Quote the value
|
|
175
|
-
(`{id="5"}`) or use `{#5}` instead.
|
|
176
|
-
|
|
177
|
-
Formatting with the Forgejo or Gitea dialect leaves a block as written:
|
|
178
|
-
`{#bare data-x=__init__}` is a valid block, and `{#bare data-x=**init**}` is
|
|
179
|
-
heading text without the anchor `#bare`. A change can also create a block:
|
|
180
|
-
`## *Mode {.a*}` is emphasis, while `## _Mode {.a_}` is a heading with a class.
|
|
181
|
-
`style/emphasis`, `style/strong`, and `links/path` therefore change nothing from
|
|
182
|
-
the first `{` of a heading's last text line on. `style/inline-code` does not
|
|
183
|
-
join a code span that spans lines of a heading, and `style/heading` escapes a
|
|
184
|
-
`#` run in front of the block (`# Run \## {#id}`), which would otherwise end the
|
|
185
|
-
heading there.
|
|
186
|
-
|
|
187
|
-
Because Forgejo, and Gitea before 1.26, build a heading's anchor from its last
|
|
188
|
-
line as written, `style/emphasis`, `style/strong`, and `links/path` also leave
|
|
189
|
-
that line unchanged on these dialects when the heading has no custom `id`.
|
|
190
|
-
Rewriting `## Emph *star* end` to `_star_` would move its anchor from
|
|
191
|
-
`#emph-star-end` to `#emph-_star_-end` and break every link to it, although the
|
|
192
|
-
heading reads the same. Earlier lines of an underlined heading, headings with an
|
|
193
|
-
`id`, and the rest of the document are formatted as usual.
|
|
152
|
+
Patterns are globs, such as `docs/**/*.md`, matched against paths relative to
|
|
153
|
+
the workspace root, with forward slashes. A pattern matches files whose names
|
|
154
|
+
start with a dot, too. Patterns match letter case exactly on every system, so
|
|
155
|
+
that a configuration selects the same files in CI on Linux as on Windows or
|
|
156
|
+
macOS, where patterns on the command line and, in most repositories,
|
|
157
|
+
`.gitignore` files [ignore case](cli.md#which-files-are-processed).
|
|
194
158
|
|
|
195
|
-
##
|
|
159
|
+
## Ignored files and link targets
|
|
160
|
+
|
|
161
|
+
`ignore` lists path patterns, written like those of overrides, for documents
|
|
162
|
+
that are never linted or formatted. They remain link targets, so links to them
|
|
163
|
+
are still checked.
|
|
164
|
+
|
|
165
|
+
The CLI also leaves out what Git ignores, decided [as Git decides
|
|
166
|
+
it](cli.md#which-files-are-processed), nested Git repositories, symbolic links,
|
|
167
|
+
and the directories `.git`, `.obsidian`, `node_modules`, `dist`, and `coverage`.
|
|
168
|
+
`resolve` makes two of these available as link targets, without ever selecting
|
|
169
|
+
them for linting or formatting:
|
|
170
|
+
|
|
171
|
+
```jsonc
|
|
172
|
+
{
|
|
173
|
+
"resolve": { "gitIgnored": true, "nestedRepositories": true },
|
|
174
|
+
}
|
|
175
|
+
```
|
|
196
176
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
An omitted `extends` selects `recommended`. Explicit `extends` replaces that
|
|
207
|
-
default, so use `["recommended", "obsidian"]` for both. `extends: []` enables
|
|
208
|
-
nothing. Severity is `off`, `warn`, or `error`; supply options as
|
|
209
|
-
`["warn", { ... }]`. Both `warn` and `error` style rules format when enabled.
|
|
210
|
-
Problem rules report findings and never become formatting edits.
|
|
211
|
-
|
|
212
|
-
## Built-in rules
|
|
213
|
-
|
|
214
|
-
| Rule | Kind | Options |
|
|
215
|
-
| ----------------------------- | ------- | ---------------------------------------------------------------------- |
|
|
216
|
-
| `style/wrap` | Style | `width`, `measure`, `reportUnreflowed`, `reportUnbreakable`; see below |
|
|
217
|
-
| `style/inline-code` | Style | None; joins multiline code spans, opt-in |
|
|
218
|
-
| `style/emphasis` | Style | `marker`: `_` (default) or `*` |
|
|
219
|
-
| `style/strong` | Style | `marker`: `*` (default) or `_` |
|
|
220
|
-
| `style/final-newline` | Style | None; adds a missing final newline |
|
|
221
|
-
| `style/table` | Style | None; aligns top-level GFM tables |
|
|
222
|
-
| `style/heading` | Style | None; converts eligible Setext headings to ATX |
|
|
223
|
-
| `links/valid` | Problem | None; local files and heading/block fragments |
|
|
224
|
-
| `links/path` | Style | `style`, `brackets`, `extension`, `leadingDot`; see below |
|
|
225
|
-
| `links/notation` | Style | `style`: `markdown` or `wiki`; Obsidian only |
|
|
226
|
-
| `github/task-marker` | Style | None; `[X]` becomes `[x]` |
|
|
227
|
-
| `github/alert-marker` | Style | None; known alert types become uppercase on GitHub, Forgejo, and Gitea |
|
|
228
|
-
| `forgejo/heading-id` | Problem | None; heading ids that are not text, which break rendering on Forgejo |
|
|
229
|
-
| `obsidian/callout-marker` | Style | None; Obsidian callout types become lowercase |
|
|
230
|
-
| `obsidian/block-reference` | Problem | None; duplicate trailing `^block-id` markers |
|
|
231
|
-
| `obsidian/strict-line-breaks` | Problem | None; report unverified/incompatible reflow settings |
|
|
177
|
+
Both default to `false`. The Markdown files of such a target are read only when
|
|
178
|
+
a link's fragment needs checking.
|
|
179
|
+
|
|
180
|
+
The directories that the CLI does not visit, and the targets of symbolic links
|
|
181
|
+
and junctions, are still link targets: a link that names a path in or through
|
|
182
|
+
them is checked on disk. A path whose real location lies outside the workspace
|
|
183
|
+
root is not read and is reported as not checkable. A Git-ignored directory stays
|
|
184
|
+
out unless `resolve.gitIgnored` asks for it, whatever its name, and an Obsidian
|
|
185
|
+
search by note name does not look in these directories.
|
|
232
186
|
|
|
233
187
|
## Plugins
|
|
234
188
|
|
|
235
|
-
`plugins` lists
|
|
189
|
+
`plugins` lists plugins to load, as strings:
|
|
236
190
|
|
|
237
191
|
```jsonc
|
|
238
192
|
{
|
|
@@ -243,136 +197,17 @@ Problem rules report findings and never become formatting edits.
|
|
|
243
197
|
```
|
|
244
198
|
|
|
245
199
|
An entry that starts with `.` or is an absolute path names a file, relative to
|
|
246
|
-
the configuration file's directory. Any other entry names
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
command-line option for them.
|
|
252
|
-
|
|
253
|
-
A plugin is code. It runs with the caller's permissions when the configuration
|
|
254
|
-
is loaded, so name only plugins you trust. A plugin that cannot be found or
|
|
255
|
-
loaded stops the command with exit code `2` and a message that names the entry
|
|
256
|
-
and the configuration file.
|
|
257
|
-
|
|
258
|
-
[Rule plugins](plugins.md#rule-plugins) describes how a package is looked up in
|
|
259
|
-
detail, what a plugin can contain, and how to write one.
|
|
260
|
-
|
|
261
|
-
## Document structure
|
|
262
|
-
|
|
263
|
-
Enable `structure/initial-heading` explicitly with severity `warn` or `error`;
|
|
264
|
-
no preset enables it. It accepts no options and reports problems without
|
|
265
|
-
changing content. Use path `overrides` to exempt generated documents or trees
|
|
266
|
-
with different conventions.
|
|
267
|
-
|
|
268
|
-
`structure/initial-heading` skips YAML/TOML front matter and requires a level-1
|
|
269
|
-
heading as the first content block. Both ATX and Setext headings count; use
|
|
270
|
-
`style/heading` separately to require ATX spelling. Empty documents are
|
|
271
|
-
reported. Comments and other content before the title are not skipped.
|
|
272
|
-
|
|
273
|
-
Filename/title matching, metadata placement, and guesses about accidental
|
|
274
|
-
Markdown markers are consumer policies. Implement those checks through
|
|
275
|
-
[rule plugins](plugins.md#rule-plugins), which receive the document source,
|
|
276
|
-
parsed tree, and path. Modified-date updates belong in a consumer wrapper or
|
|
277
|
-
library workflow; formatting rules must preserve document meaning.
|
|
278
|
-
|
|
279
|
-
## Wrapping and inline code
|
|
280
|
-
|
|
281
|
-
`style/wrap` accepts widths from 20 through 500 and defaults to `width: 80` and
|
|
282
|
-
`measure: "columns"` (display columns). Set `measure: "codepoints"` to count
|
|
283
|
-
Unicode scalar values instead; astral characters count once and combining marks
|
|
284
|
-
count separately. Container prefixes count toward the width in either mode.
|
|
285
|
-
|
|
286
|
-
`reportUnreflowed: true` reports breakable over-width lines in paragraphs
|
|
287
|
-
protected by hard breaks, block IDs, inline HTML, callout headers, Forgejo or
|
|
288
|
-
Gitea definition lists, display math, line-spanning inline syntax, or the Gitea
|
|
289
|
-
`_.py` emphasis exception, or unsupported multiline syntax or containers.
|
|
290
|
-
`reportUnbreakable: true` reports overflow from an atom that cannot be split,
|
|
291
|
-
including in protected paragraphs. Whitespace inside a link, code span, or other
|
|
292
|
-
protected inline node is not a wrapping opportunity, nor is whitespace inside a
|
|
293
|
-
Forgejo or Gitea `\(...\)` expression or `[[...]]` shortlink written on one
|
|
294
|
-
line. A protected paragraph with both breakable prose and an over-width atom can
|
|
295
|
-
report both causes; an atom-only overflow does not trigger `reportUnreflowed`.
|
|
296
|
-
Hard-break markers are excluded from protected-line width. An Obsidian callout
|
|
297
|
-
title is one indivisible physical line: an over-width title follows
|
|
298
|
-
`reportUnbreakable`, even when it contains spaces. Body prose is classified
|
|
299
|
-
separately. A block ID does not make its whole paragraph indivisible. Both
|
|
300
|
-
options default to false, propose no edits, and use the rule's severity. Use
|
|
301
|
-
severity `error` or `--max-warnings 0` to make these diagnostics fail a check;
|
|
302
|
-
`--check` does not change rule settings.
|
|
303
|
-
|
|
304
|
-
Enable `style/inline-code` to join multiline code spans before paragraph reflow.
|
|
305
|
-
This opt-in rule handles single and multiple backticks, including list and quote
|
|
306
|
-
containers. It preserves the parsed code value, converting each line ending to
|
|
307
|
-
one space under CommonMark's code-span rules. Other code whitespace remains
|
|
308
|
-
significant. It is useful for Obsidian editors that display split spans
|
|
309
|
-
differently from Reading view.
|
|
310
|
-
|
|
311
|
-
## Link policies
|
|
200
|
+
the configuration file's directory. Any other entry names a package, found from
|
|
201
|
+
the configuration file as Node.js finds an `import`. A plugin adds rules and
|
|
202
|
+
presets, named with the plugin's name as a prefix: above, the file's plugin
|
|
203
|
+
calls itself `local` and the package's plugin `sample`. Only a configuration
|
|
204
|
+
file can name plugins; the CLI has no option for them.
|
|
312
205
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
"rules": {
|
|
317
|
-
"links/path": ["warn", { "style": "root", "brackets": "angle", "extension": "preserve" }],
|
|
318
|
-
},
|
|
319
|
-
}
|
|
320
|
-
```
|
|
206
|
+
A plugin runs with your permissions when the configuration is loaded. A plugin
|
|
207
|
+
that cannot be loaded stops the command with exit code `2`.
|
|
208
|
+
[Plugins](plugins.md) describes how to write one and how a package is found.
|
|
321
209
|
|
|
322
|
-
|
|
323
|
-
means vault-relative, without a leading slash, and is available only for
|
|
324
|
-
Obsidian. `shortest` uses the basename if it resolves uniquely, otherwise the
|
|
325
|
-
vault-relative path. `leadingDot: true` prefixes ordinary relative paths with
|
|
326
|
-
`./`. Filesystem absolute paths are not generated.
|
|
327
|
-
|
|
328
|
-
`brackets` accepts `preserve` (default), `angle`, or `bare`. Spaces in bare
|
|
329
|
-
Markdown destinations are percent-encoded. `extension` accepts `preserve`
|
|
330
|
-
(default), `include`, or `omit`; omission is Obsidian specific. Fragments are
|
|
331
|
-
resolved according to the dialect, separately from percent-decoded filenames. On
|
|
332
|
-
GitHub, Forgejo, and Gitea, a fragment written with the `user-content-` prefix
|
|
333
|
-
that the renderers add to every anchor reaches the same anchor as one without,
|
|
334
|
-
and is validated the same way. Anchors written as HTML, the `id` of any element
|
|
335
|
-
and the `name` of an `<a>`, such as `<a name="install"></a>` before a heading,
|
|
336
|
-
are valid fragments on those three dialects. GitHub matches every fragment
|
|
337
|
-
without regard to case, so `#Sponsors` reaches `## Sponsors` there; Forgejo and
|
|
338
|
-
Gitea match exactly as written. A heading written as HTML
|
|
339
|
-
(`<h2 align="center">Title</h2>`) gets a generated anchor on GitHub, numbered
|
|
340
|
-
together with the Markdown headings, and on Gitea 1.26 and later, where it is
|
|
341
|
-
not numbered and a heading with its own `id` gets none; Forgejo and earlier
|
|
342
|
-
Gitea versions give it no anchor. HTML inside comments, code, and `<script>`,
|
|
343
|
-
`<textarea>`, and the other elements whose content is text is not an anchor.
|
|
344
|
-
Already compliant destinations retain their percent-encoding spelling, including
|
|
345
|
-
literal `?` and `%` in resolving Obsidian paths. Newly generated paths encode
|
|
346
|
-
literal percent signs and hashes to preserve target identity.
|
|
347
|
-
|
|
348
|
-
Path edits require a resolved target and valid fragment. Unaliased ordinary
|
|
349
|
-
wikilinks retain their target spelling because changing it may change the
|
|
350
|
-
visible label. Reference definitions are validated but their source spelling is
|
|
351
|
-
currently preserved.
|
|
352
|
-
|
|
353
|
-
`links/notation` converts simple explicit-label wikilinks to Markdown links and
|
|
354
|
-
plain-text Markdown links to wikilinks. Titles, rich labels, unaliased
|
|
355
|
-
wikilinks, and embeds are preserved. A note embed is not interchangeable with a
|
|
356
|
-
Markdown image. Do not enable notation conversion and path rewriting for the
|
|
357
|
-
same link in one pass: overlapping edits are reported; run those policies in
|
|
358
|
-
separate passes.
|
|
359
|
-
|
|
360
|
-
Network URLs are recognized but never fetched. Website-root paths and
|
|
361
|
-
query-bearing destinations in CommonMark, GitHub, Forgejo, and Gitea are outside
|
|
362
|
-
local resolution. Missing or ambiguous targets are reported, never guessed. A
|
|
363
|
-
target that could not be checked, because it lies in a directory the tool was
|
|
364
|
-
not permitted to read, is reported as such and not as missing; see
|
|
365
|
-
[paths that cannot be read](#paths-that-cannot-be-read). Obsidian resolution
|
|
366
|
-
uses explicit `./` or `../` paths as source-relative; otherwise an exact
|
|
367
|
-
vault-root match precedes an exact source-relative match, followed by unique
|
|
368
|
-
suffix matching. Multiple candidates within the chosen tier remain ambiguous.
|
|
369
|
-
Relative rewrites use `./` when needed to avoid a vault-root collision. Existing
|
|
370
|
-
directories get a distinct diagnostic in Obsidian; they are not rewritten to
|
|
371
|
-
README or index notes. CommonMark, GitHub, Forgejo, and Gitea directory links
|
|
372
|
-
are accepted because a hosting site can serve them. Shortest-name/alias
|
|
373
|
-
resolution is not a complete clone of Obsidian.
|
|
374
|
-
|
|
375
|
-
## Suppressions
|
|
210
|
+
## Suppression comments
|
|
376
211
|
|
|
377
212
|
```markdown
|
|
378
213
|
<!-- mdtools-disable style/wrap -->
|
|
@@ -385,146 +220,24 @@ Keep the wrapping in this region.
|
|
|
385
220
|
Keep *this* delimiter.
|
|
386
221
|
```
|
|
387
222
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
it
|
|
223
|
+
`mdtools-disable` turns rules off from the comment on, and `mdtools-enable`
|
|
224
|
+
turns them on again; without rule names, they apply to every rule.
|
|
225
|
+
`mdtools-disable-next-line` applies to the next line only, even when it is
|
|
226
|
+
blank, so place it directly above the line. A suppressed rule reports nothing
|
|
227
|
+
there and changes nothing that touches the region, so a paragraph that crosses
|
|
228
|
+
into it is left as written. A directive inside code is code, not a directive.
|
|
394
229
|
|
|
395
|
-
##
|
|
230
|
+
## Inspect the result
|
|
396
231
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
232
|
+
`config explain` prints, as JSON, the configuration in effect for one document:
|
|
233
|
+
the workspace `root`, the configuration file as `config` (or `null`), the
|
|
234
|
+
document's `path` from the root with forward slashes, and the `effective`
|
|
235
|
+
settings, with the dialect assumed for that document and the overrides that
|
|
236
|
+
match it. The document need not exist, but like an input of `lint` it must lie
|
|
237
|
+
inside the workspace.
|
|
402
238
|
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
"resolve": { "gitIgnored": true, "nestedRepositories": true },
|
|
406
|
-
}
|
|
239
|
+
```sh
|
|
240
|
+
npx mdtools config explain notes/example.md
|
|
407
241
|
```
|
|
408
242
|
|
|
409
|
-
|
|
410
|
-
files for linting or formatting, including when a path is supplied explicitly.
|
|
411
|
-
Markdown targets are read and parsed only for fragment checks; attachments need
|
|
412
|
-
only a discovered file entry. Built-in traversal exclusions still apply. `.git`,
|
|
413
|
-
`.obsidian`, `node_modules`, `.npm-cache`, `dist`, and `coverage` are excluded
|
|
414
|
-
from traversal, as are symlinks. Nested Git repositories are traversed for
|
|
415
|
-
targets only when opted in. Explicit symlink inputs are rejected. Shell-expanded
|
|
416
|
-
globs work; the CLI does not expand path globs.
|
|
417
|
-
|
|
418
|
-
`lint --json` and `format --json` print a single object with `version`, `mode`,
|
|
419
|
-
`files`, and `written`, and with `skipped` when the run left out something it
|
|
420
|
-
was not permitted to read. Each file carries diagnostics with rule ID, severity,
|
|
421
|
-
message, offsets, and one-based line/column locations. Source offsets and
|
|
422
|
-
columns use JavaScript UTF-16 units; wrapping widths use display columns.
|
|
423
|
-
Formatting diagnostics refer to the resulting source. `written` records whether
|
|
424
|
-
the requested write phase was allowed, not how many files changed; inspect each
|
|
425
|
-
file's `changed` field.
|
|
426
|
-
|
|
427
|
-
Without `--json`, a command that processed files ends with one summary line on
|
|
428
|
-
stderr. `lint` counts the files and the findings it reported, as in
|
|
429
|
-
`3 file(s) linted; 1 error(s), 2 warning(s).` `format` counts the files and
|
|
430
|
-
those it changed or would change, as in `3 file(s) processed; 1 would change.`
|
|
431
|
-
Both add `; 1 could not be read` when a selected document
|
|
432
|
-
[could not be read](#paths-that-cannot-be-read). Versions up to `0.2.0-rc.1`
|
|
433
|
-
ended `lint` with `0 would change`, whatever it found. The line is meant for
|
|
434
|
-
people; a script should read the JSON report or the exit code.
|
|
435
|
-
|
|
436
|
-
`format --diff` is the default for file input. `--check`, `--diff`, and
|
|
437
|
-
`--write` are mutually exclusive. `format - --stdin-filepath notes/example.md`
|
|
438
|
-
reads stdin with configuration and resolution context; it cannot be used with
|
|
439
|
-
`--write`.
|
|
440
|
-
|
|
441
|
-
| Exit | Meaning |
|
|
442
|
-
| ---- | -------------------------------------------------------------------------------------------- |
|
|
443
|
-
| `0` | Completed; no errors or failed formatting check |
|
|
444
|
-
| `1` | Lint errors, exceeded `--max-warnings`, or changes required by `format --check` |
|
|
445
|
-
| `2` | Configuration, execution, or formatting safety failure, or a document that could not be read |
|
|
446
|
-
|
|
447
|
-
Warnings do not fail a command unless `--max-warnings` is supplied. A successful
|
|
448
|
-
formatting command can still report remaining lint problems. Inspect its exit
|
|
449
|
-
code and diagnostics. An unsafe-format diagnostic blocks the complete batch's
|
|
450
|
-
write phase, and so does a selected document that
|
|
451
|
-
[cannot be read](#paths-that-cannot-be-read). An I/O error during writing can
|
|
452
|
-
leave earlier files written; replacement is atomic per file, not a
|
|
453
|
-
workspace-wide transaction.
|
|
454
|
-
|
|
455
|
-
## Paths that cannot be read
|
|
456
|
-
|
|
457
|
-
A directory that the system does not permit the tool to read is skipped. The
|
|
458
|
-
tool reports it once as a warning that names it, indexes nothing below it, and
|
|
459
|
-
processes the rest of the workspace. The warning alone does not change the exit
|
|
460
|
-
code and is not counted by `--max-warnings`. It is printed on stderr as
|
|
461
|
-
`mdtools: warning: ...`; with `--json` it is an entry of the report's `skipped`
|
|
462
|
-
list instead, with the directory's `path`, `type`, the system's error `code`,
|
|
463
|
-
and a `message`. This applies to a directory that can be neither listed nor
|
|
464
|
-
entered, to one that can only be listed, and to one that can only be entered. It
|
|
465
|
-
also applies to a directory whose `.gitignore` cannot be read, because without
|
|
466
|
-
the ignore rules nothing tells which of its files may be processed. Versions up
|
|
467
|
-
to `0.2.0-rc.1` stopped every command, with exit code `2`, when the workspace
|
|
468
|
-
contained such a directory.
|
|
469
|
-
|
|
470
|
-
A link that leads into a skipped directory cannot be checked. `links/valid`
|
|
471
|
-
reports it as `Local target could not be checked`, naming the directory, with
|
|
472
|
-
the rule's configured severity. The target is not called missing, and the link
|
|
473
|
-
is never rewritten. An Obsidian link that names a note without a path is
|
|
474
|
-
searched for in every directory, so when no readable file matches, it is
|
|
475
|
-
reported the same way, naming the skipped directories. A note that such a search
|
|
476
|
-
does find is accepted, and so is a note found beside the linking note when the
|
|
477
|
-
vault-root path of the same spelling leads into a skipped directory.
|
|
478
|
-
`links/path` and `links/notation` leave such a link as written, and an edit by a
|
|
479
|
-
plugin that changes its destination is refused, because a skipped directory may
|
|
480
|
-
hold a second note of that name, or the one that Obsidian would choose.
|
|
481
|
-
|
|
482
|
-
A path named on the command line that cannot be used stops the command with exit
|
|
483
|
-
code `2`. The message says what the path was named as and what is wrong with it:
|
|
484
|
-
a workspace root, a configuration file, or an input that `does not exist` or
|
|
485
|
-
`cannot be read`, a workspace root that `is not a directory`, a configuration
|
|
486
|
-
file that `is not a file`, as in `Input does not exist: notes/absent.md`. An
|
|
487
|
-
input and a file given with `--config` are named as they were given, the
|
|
488
|
-
workspace root with its full path. Versions up to `0.2.0-rc.1` printed the
|
|
489
|
-
system's own message, which named an internal step. An `--exclude` path that
|
|
490
|
-
does not exist excludes nothing; one that the tool is not permitted to examine
|
|
491
|
-
is an error, because it cannot tell which file the path stands for.
|
|
492
|
-
|
|
493
|
-
Naming a skipped directory, or a path inside it, as an input is an error with
|
|
494
|
-
exit code `2`, and so is a workspace root that cannot be read. Configuration
|
|
495
|
-
`ignore` patterns and `--exclude` choose which documents are processed; they do
|
|
496
|
-
not keep the tool out of a directory, because an ignored document remains a link
|
|
497
|
-
target. To leave a directory out without a warning, list it in a `.gitignore`:
|
|
498
|
-
Git-ignored content is not indexed unless `resolve.gitIgnored` asks for it.
|
|
499
|
-
|
|
500
|
-
If a vault's `.obsidian/app.json` cannot be read, the tool warns in the same way
|
|
501
|
-
and treats `strictLineBreaks` as unverified for that vault, so its documents are
|
|
502
|
-
not reflowed. The same holds when the file's content cannot be used, because it
|
|
503
|
-
is not valid JSON or is not a file; the entry's `code` is then `INVALID`.
|
|
504
|
-
Versions up to `0.2.0-rc.1` stopped every command in that case. A file named
|
|
505
|
-
`.obsidian` is not a vault's settings folder and is ignored. When the system
|
|
506
|
-
does not let the tool find out whether a folder is a vault, which takes a
|
|
507
|
-
`.obsidian` that is a link into a place it may not read, or a document named for
|
|
508
|
-
`config explain` or `--stdin-filepath` in a directory it may not enter, the
|
|
509
|
-
command stops with exit code `2`: reading a vault's notes as another dialect is
|
|
510
|
-
not a safe fallback. A configuration file that cannot be read still stops the
|
|
511
|
-
run, as does a directory that refuses the search for one: default rules must not
|
|
512
|
-
take the place of a configuration that exists. An error about a configuration
|
|
513
|
-
file names the file, also when its content is not valid JSON, does not fit the
|
|
514
|
-
configuration format, or is a script that fails to load.
|
|
515
|
-
|
|
516
|
-
A selected document that cannot be read is reported for that file, as an error
|
|
517
|
-
diagnostic with the rule ID `engine/unreadable-file` at line 1, in the text
|
|
518
|
-
output and in the file's entry of the JSON report. The other files are processed
|
|
519
|
-
and reported, and the run ends with exit code `2`. As with an unsafe-format
|
|
520
|
-
diagnostic, `format --write` then writes none of the batch; pass `--exclude` for
|
|
521
|
-
the file to format the rest. A link to a heading or block in a file that cannot
|
|
522
|
-
be read is reported by `links/valid` as `Fragment could not be checked`, naming
|
|
523
|
-
the file, with the rule's configured severity, and is never rewritten. A link to
|
|
524
|
-
the file without a fragment is valid, because the file is known to exist.
|
|
525
|
-
Versions up to `0.2.0-rc.1` stopped at the first such file or link without
|
|
526
|
-
reporting anything else.
|
|
527
|
-
|
|
528
|
-
Only the system errors `EACCES` and `EPERM` count as not permitted. Any other
|
|
529
|
-
read error, such as a path that disappeared during the run or a failing device,
|
|
530
|
-
stops the run with exit code `2`.
|
|
243
|
+
It reads `--config`, `--root`, and `--dialect`, before or after `explain`.
|