mmdfmt 0.0.0 → 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/README.ja.md ADDED
@@ -0,0 +1,784 @@
1
+ # mmdfmt
2
+
3
+ 英語版: [README.md](./README.md)
4
+
5
+ Markdown と `.mmd` ファイルの [Mermaid](https://mermaid.js.org/) の図を整形し、
6
+ ほかはすべて書いたまま残します。
7
+
8
+ `mmdfmt` は `.mmd` と `.mermaid` ファイルと、
9
+ `.md` と `.markdown` ファイルの `mermaid` と `mmd` コードブロックを整形します。
10
+ Markdown ファイルのほかの部分は、1 バイトも変えません。
11
+ 図は、
12
+ Prettier の Mermaid プラグインである
13
+ [`prettier-plugin-mmd`](../prettier-plugin-mmd) を使って
14
+ [Prettier](https://prettier.io/) で整形するため、
15
+ [Prettier を知っている方へ](#prettier-を知っている方へ)の場合を除き、
16
+ プラグインと同じ結果になります。
17
+
18
+ [mermaid-js](https://mermaid.js.org/) とは関係のない第三者のプロジェクトです。
19
+ 文書サイトに
20
+ [mmdfmt の案内](https://mmd-toolkit.github.io/mmd-toolkit/ja/formatter/mmdfmt.html)
21
+ があります。
22
+
23
+ ## どんなときに使うか
24
+
25
+ 図を整形したいけれど、Markdown は Prettier で整形しないときに使います。
26
+
27
+ - `markdownlint --fix` や dprint など、
28
+ 別のフォーマッターで Markdown を整形する。
29
+ Prettier を使うと、同じテキストを Prettier のやり方で書き換えてしまいます。
30
+ - Markdown を、意図して書いたまま保つ。
31
+ - ほかのファイルには Prettier を使い、Markdown には使わない。
32
+
33
+ すでに Prettier で Markdown を整形しているなら、
34
+ 代わりに `prettier-plugin-mmd` を追加してください。
35
+ 同じ実行で図も整形されるため、`mmdfmt` は不要です。
36
+
37
+ `mmdfmt` は Prettier の設定なしに、1 つのコマンドで使えます。
38
+
39
+ ## しないこと
40
+
41
+ - 図のほかは整形しません。
42
+ - 図の誤りは、mermaid.js が拒否するもの以外は報告しません。
43
+ それは [`@mmd-toolkit/eslint-plugin`](../eslint-plugin) が行います。
44
+
45
+ ## まず使ってみる
46
+
47
+ `mmdfmt` には Node.js `^22.13.0 || >=24` が必要です。
48
+ `--write` はファイルを直接書き換えるので、先に作業をコミットするか、
49
+ `npx mmdfmt --check .` でどのファイルが変わるか確認してください。
50
+ 現在のディレクトリの下にある図をすべて整形するには、次を実行します。
51
+
52
+ ```sh
53
+ npx mmdfmt --write .
54
+ ```
55
+
56
+ 変わるのは図だけです。
57
+ この `notes.md` は、
58
+
59
+ <!-- prettier-ignore -->
60
+ ````md
61
+ # Notes
62
+
63
+ * A list item that mmdfmt leaves as it is.
64
+
65
+ ```mermaid
66
+ flowchart LR
67
+ A --> B; B --> C
68
+ ```
69
+ ````
70
+
71
+ 次のようになります。
72
+
73
+ <!-- prettier-ignore -->
74
+ ````md
75
+ # Notes
76
+
77
+ * A list item that mmdfmt leaves as it is.
78
+
79
+ ```mermaid
80
+ flowchart LR
81
+ A --> B
82
+ B --> C
83
+ ```
84
+ ````
85
+
86
+ `mmdfmt` をインストールしていない場合、`npx` はダウンロードしてよいか尋ね、
87
+ 最新版を実行します。
88
+ 同じバージョンを使い続けるには、[インストール](#インストール)してください。
89
+
90
+ ## インストール
91
+
92
+ `mmdfmt` の新しいバージョンでは、図の整形が少し変わることがあります。
93
+ プロジェクトに関わる全員と CI が同じように整形するよう、
94
+ プロジェクトでバージョンを厳密に固定します。
95
+
96
+ ```sh
97
+ npm install --save-dev --save-exact mmdfmt
98
+ ```
99
+
100
+ pnpm では、`pnpm add --save-dev --save-exact mmdfmt` を使います。
101
+ 以降は `npx mmdfmt`(または `pnpm exec mmdfmt`)がそのバージョンを実行します。
102
+
103
+ 自分で複数のリポジトリにまたがって使うには、グローバルにインストールし、
104
+ `mmdfmt` として実行します。
105
+
106
+ ```sh
107
+ npm install --global mmdfmt
108
+ ```
109
+
110
+ グローバルなインストールはプロジェクトに固定されないので、
111
+ 2 台のマシンで図の整形結果が異なることがあります。
112
+
113
+ ## 使い方
114
+
115
+ ```sh
116
+ mmdfmt --write [--check | --list-different] <pattern>...
117
+ mmdfmt --check <pattern>...
118
+ mmdfmt --list-different <pattern>...
119
+ mmdfmt --stdin-filepath <path>
120
+ ```
121
+
122
+ | オプション | 動作 |
123
+ | ------------------------- | ------------------------------------------------------------------------------ |
124
+ | `-w`, `--write` | ファイルを直接整形し、整形した各ファイルを所要時間とともに標準出力に挙げます。 |
125
+ | `-c`, `--check` | 整形済みか確認し、要約と整形されていないファイルを報告します。 |
126
+ | `-l`, `--list-different` | 何も変えず、`--write` が変えるファイルを標準出力に挙げます。 |
127
+ | `--stdin-filepath <path>` | 標準入力を `<path>` のファイルとして整形し、標準出力に書きます。 |
128
+ | `-h`, `--help` | 使い方を標準出力に書きます。 |
129
+ | `-v`, `--version` | バージョンを標準出力に書きます。 |
130
+
131
+ `--write`、`--check`、`--list-different` の少なくとも 1 つにパターンを付けます。
132
+ `--write` は `--check` か `--list-different` のどちらかと組み合わせられます。
133
+ `--write --check` はファイルを書き換え、チェックの要約と警告を出力します。
134
+ `--write --list-different` はファイルを書き換えて、変わったものだけを挙げます。
135
+ `--check` と `--list-different` は組み合わせられません。
136
+ `--no-write`、`--no-check`、`--no-list-different` は、そのオプションを外します。
137
+ `--stdin-filepath` はパターンを取らず、
138
+ 一緒に使うと `--write` はファイルを書きません。
139
+ `--help` と `--version` は、
140
+ 表のほかのオプションを一緒に付けても出力するだけです。
141
+ 引数がまったくないときは、`mmdfmt` は使い方を標準エラー出力に書き、
142
+ `2` で終了します。
143
+
144
+ `--write` 単独では Prettier と同じく、整形したファイルごとに 1 行出力します。
145
+ その名前と整形にかかった時間を、`docs/flow.mmd 12ms` のように書き、
146
+ 変わらなかったファイルには、その後ろに `(unchanged)` を付けます。
147
+ 色を出せる端末では、変わらなかったファイルの名前は灰色です。
148
+ 変わったファイルだけを挙げるには、`--write --list-different` を付けます。
149
+ `mmdfmt` が出力するファイルの名前は、実行するディレクトリからの相対パスで、
150
+ Windows でも Prettier と同じく、区切りは `/` です。
151
+
152
+ ほかのオプションはありません。
153
+ 整形オプションも、独自の設定ファイルも、
154
+ 無視ファイルを指定するオプションもありません。
155
+ 値を取らないオプションは、`=` の後ろの値を無視します。
156
+ `--write=false` は `--write` と同じに読みます。
157
+
158
+ `head` が必要な行数を読み終えたときのように、標準出力の読み手がいなくなると、
159
+ `mmdfmt` はそこへの出力を止め、何も報告せずに最後まで処理します。
160
+ `--write` は引き続きすべてのファイルを書き換え、
161
+ 終了コードも処理の結果を示します。
162
+
163
+ ### パターン
164
+
165
+ - ファイルのパスは、そのファイルを選びます。
166
+ - `.` などのディレクトリのパスは、その下のファイルを選びます。
167
+ - ほかのパターンは glob で、名前がドットで始まるものにも一致します。
168
+ シェルではなく `mmdfmt` が展開するよう、引用符で囲みます。
169
+ 例: `npx mmdfmt --write "docs/**/*.md"`。
170
+ Windows では、glob の `\` を `/` と読みます。
171
+ - `!` で始まるパターンは、
172
+ 一致するファイルをほかのパターンの選択から取り除きます。
173
+ [ファイルの除外](#ファイルの除外)を参照してください。
174
+ - `--` の後ろの引数はすべてパターンなので、`mmdfmt --write -- -a.md` のように、
175
+ `-` で始まる名前のファイルも渡せます。
176
+
177
+ 選んだファイルのうち、名前が `.md`、`.markdown`、`.mmd`、
178
+ `.mermaid` で終わるものを、いくつのパターンが選んでも 1 回ずつ整形します。
179
+ そのどれも選ばないパターンはエラーです。
180
+ そのようなファイルのないプロジェクトでは `mmdfmt --check .` は失敗し、
181
+ ほかの拡張子のファイルを名前で指定しても同じです。
182
+ Prettier の CLI と同じく、
183
+ `!` のパターンによって選んだファイルがすべて取り除かれるパターンもエラーです。
184
+ `.gitignore` が挙げるファイルだけを選ぶパターンはエラーではありません。
185
+
186
+ Prettier の CLI と同じく、`mmdfmt` は、
187
+ `node_modules` やバージョン管理のディレクトリ内のパスを名指すパターンを、
188
+ ファイル、ディレクトリ、glob のどれであっても何も報告せずに飛ばします。
189
+ 例: `node_modules/pkg` や `"node_modules/**/*.md"`。
190
+ ファイルを選ぶパターンが 1 つも残らないときはエラーです。
191
+
192
+ ## ファイルの除外
193
+
194
+ `mmdfmt` は次のファイルを除外します。
195
+
196
+ - `node_modules` と、バージョン管理のディレクトリ(`.git`、`.hg`、`.jj`、`.sl`、
197
+ `.svn`)の下にあるファイル。
198
+ パターンで名指す場合も同じです([パターン](#パターン))。
199
+ - `mmdfmt` を実行するディレクトリの `.gitignore` が挙げるファイル。
200
+ サブディレクトリや親ディレクトリの `.gitignore` は読みません。
201
+ - `!` のパターンに一致するファイル。
202
+ bash では、二重引用符内の `!` は履歴展開を始めるため、単一引用符で囲みます。
203
+ 例: `npx mmdfmt --write . '!vendor/**'`。
204
+ Windows のコマンドプロンプトでは二重引用符を使います。
205
+
206
+ `mmdfmt` は `.prettierignore` を読みません。
207
+ そこに Markdown を挙げて Prettier で整形しないようにしたプロジェクトでも、
208
+ 図を整形できます。
209
+
210
+ Markdown ファイルの図を 1 つそのまま残すには、
211
+ コードブロックの前に `<!-- prettier-ignore -->` を置き、
212
+ 間には空行以外を入れません。
213
+ リストや引用の外では、
214
+ `<!-- prettier-ignore-start -->` と `<!-- prettier-ignore-end -->`
215
+ の間の図をすべてそのまま残します。
216
+ これらは Prettier が読むコメントです。
217
+ `.mmd` ファイル全体をそのまま残すには、
218
+ `!` のパターンか `.gitignore` で除外します。
219
+
220
+ ## CI で確認する
221
+
222
+ プロジェクトに `mmdfmt` をインストールし、
223
+ CI で依存パッケージをインストールして(`npm ci`)、次を実行します。
224
+
225
+ ```sh
226
+ npx mmdfmt --check .
227
+ ```
228
+
229
+ 依存パッケージをインストールしていないと、
230
+ `npx` は固定したバージョンではなく最新版を実行してしまいます。
231
+
232
+ `--check` は、`Checking formatting...` を標準出力に書き、
233
+ 変わるファイルごとに `[warn] <name>` を標準エラー出力に書き、
234
+ 最後に要約を 1 つ書きます。
235
+ 変わるファイルがあれば、要約は標準エラー出力に書き、終了コードは `1` です。
236
+
237
+ ```txt
238
+ [warn] Code style issues found in the above file. Run mmdfmt with --write to fix.
239
+ ```
240
+
241
+ 該当するファイルが複数なら、`in the above file` は `in <n> files` になります。
242
+ 色を出せる端末では、`warn` の語は黄色です。
243
+ 変わるファイルがなければ、
244
+ 要約は標準出力の `All diagrams in the matched files use Prettier code style!`
245
+ で、終了コードは `0` です。
246
+ `--list-different` は、変わるファイルの名前だけを標準出力に書き、
247
+ 終了コードは同じです。
248
+
249
+ `--write --check` では、ファイルを書き換え、
250
+ 要約は `[warn] Code style issues fixed in the above file.` で、
251
+ 複数なら末尾が `in <n> files.` になり、終了コードは `0` です。
252
+ エラーがあれば、終了コードは `2` です。
253
+ そのときの要約は、[エラーと終了コード](#エラーと終了コード)に書いてあります。
254
+
255
+ mermaid.js が拒否する図のある `.mmd` や `.mermaid` ファイルは、
256
+ `2` でチェックに失敗します。
257
+ Markdown 内の図を mermaid.js が拒否しても、警告にとどまります。
258
+ 文書では壊れた図を意図して示すことがあり、
259
+ `mmdfmt` にはそれで失敗させるオプションはありません。
260
+ そのような図で CI を失敗させるには、
261
+ 図を報告する [`@mmd-toolkit/eslint-plugin`](../eslint-plugin) で Markdown を
262
+ lint します。
263
+
264
+ 図のファイルが 1 つもないプロジェクトでは、`--check .` は `2` で失敗します。
265
+ `.` の代わりに、図のあるディレクトリを指定してください。
266
+
267
+ ## コミット前に整形する
268
+
269
+ husky や simple-git-hooks などの Git フックマネージャーがコミットごとに実行する
270
+ [lint-staged](https://github.com/lint-staged/lint-staged) を使う場合は、
271
+ `package.json` に次を追加します。
272
+
273
+ ```json
274
+ {
275
+ "lint-staged": {
276
+ "*.{md,markdown,mmd,mermaid}": "mmdfmt --write"
277
+ }
278
+ }
279
+ ```
280
+
281
+ glob はこの 4 つの拡張子に限ってください。
282
+ `mmdfmt` には Prettier の `--ignore-unknown` のようなオプションはなく、
283
+ ほかの拡張子のファイルはエラーです。
284
+ lint-staged が渡す絶対パスを、`mmdfmt` は受け付けます。
285
+
286
+ ## エディターやほかのツールから使う
287
+
288
+ `mmdfmt` にはエディターの拡張機能はありません。
289
+ 標準入力に対してフォーマッターを実行するエディターやツールでは、
290
+ ファイルのテキストを標準入力に渡して次を実行し、
291
+ 標準出力から整形結果を受け取れます。
292
+
293
+ ```sh
294
+ mmdfmt --stdin-filepath docs/guide.md
295
+ ```
296
+
297
+ そのパスのファイルは、読み書きしません。
298
+ 相対パスは `mmdfmt` を実行するディレクトリを基準に解決します。
299
+ パスの拡張子がテキストを図として読むか Markdown として読むかを決め、
300
+ ディレクトリがどの `.editorconfig` と Prettier の設定を適用するかを決めます。
301
+
302
+ - Markdown のテキストは、整形したか、すでに整形済みかにかかわらず全体を出力し、
303
+ 図が拒否されても終了コードは `0` です。
304
+ 警告は標準エラー出力に書きます。
305
+ - mermaid.js がテキストを拒否する図では、標準出力に何も書かず、
306
+ 標準エラー出力にエラーを書き、終了コードは `2` です。
307
+ - `node_modules` やバージョン管理のディレクトリの下にあるパス、
308
+ または `mmdfmt` を実行するディレクトリの `.gitignore` が挙げるパスでは、
309
+ テキストをそのまま返します。
310
+ - `--check` や `--list-different` では、テキストを出力しません。
311
+ 変わるなら、`--write` も付けたときを除き、標準出力に `(stdin)` を書き、
312
+ 終了コードは `1` です。
313
+ それ以外は何も書かず、終了コードは `0` です。
314
+ 警告の位置は、読んだときのテキストの中の位置です。
315
+ - ほかの拡張子のパスはエラーです。
316
+
317
+ ## スクリプトから使う
318
+
319
+ エディターの拡張機能や言語サーバーなど、Node.js 向けに書かれたツールは、
320
+ `mmdfmt` コマンドを実行しなくても、
321
+ コマンドと同じようにファイルの図を整形できます。
322
+ Node.js 向けに書かれていないツールは、
323
+ [`--stdin-filepath`](#エディターやほかのツールから使う)を付けて、
324
+ コマンドを実行できます。
325
+ 新しいバージョンでは図の整形が少し変わることがあるため、
326
+ ツールの依存パッケージに `mmdfmt` を追加するときは、
327
+ [インストール](#インストール)と同じようにバージョンを固定します。
328
+
329
+ ```sh
330
+ npm install --save-exact mmdfmt
331
+ ```
332
+
333
+ Node.js `^22.13.0 || >=24` が必要です。
334
+ `mmdfmt` から、関数 `resolveConfig`、`format`、
335
+ `clearConfigCache` をインポートして使います。
336
+ 引数と戻り値は Prettier の同じ名前の関数にそろえてあり、
337
+ 違う点は関数ごとの節で説明します。
338
+ 次の例は、`docs/notes.md` の図を整形します。
339
+
340
+ ```js
341
+ import { readFile } from "node:fs/promises"
342
+ import { format, resolveConfig } from "mmdfmt"
343
+
344
+ const filepath = "docs/notes.md"
345
+ const source = await readFile(filepath, "utf8")
346
+ const config = await resolveConfig(filepath)
347
+ const formatted = await format(source, { ...config, filepath })
348
+ ```
349
+
350
+ `formatted` には、
351
+ コマンドが `docs/notes.md` を整形して書き出すのと同じテキストが入ります。
352
+ 図は整形され、ほかの部分は書かれたままです。
353
+ ファイルに書き込むかどうかは、ツールが決めます。
354
+
355
+ ### `resolveConfig(fileUrlOrPath)`
356
+
357
+ `resolveConfig` は、
358
+ ファイルに適用される Prettier の設定ファイルと `.editorconfig` を、
359
+ コマンドと同じように `overrides` も含めて探します([設定](#設定)を参照)。
360
+ 引数には、ファイルのパスかファイル URL を渡します。
361
+ 相対パスは現在のディレクトリを基準に解決されるため、
362
+ 言語サーバーでは絶対パスか URL を渡します。
363
+ ファイルそのものは読まないので、存在しないファイルのパスでもかまいません。
364
+
365
+ `resolveConfig` は Promise を返します。
366
+ ファイルに適用される設定があれば、
367
+ Promise は `format` に渡すオプションのオブジェクトで解決され、
368
+ なければ `null` で解決されます。
369
+ `null` を展開しても何も加わらないため、
370
+ `{ ...config, filepath }` はどちらの場合にも使えます。
371
+ オブジェクトが持つのは、`mmdfmt` が設定から読む 8 つのオプションのうち、
372
+ 設定が指定しているものだけです。
373
+ 8 つのオプションの一覧は、[設定](#設定)にあります。
374
+ たとえば、設定が `tabWidth` を指定していなければ、
375
+ `{ tabWidth: 4, ...config, filepath }` の `tabWidth` は 4 のままです。
376
+ TypeScript では、このオブジェクトの型は `ReadOptions` です。
377
+ 設定ファイルを読めないときは、Promise は拒否されます。
378
+
379
+ `resolveConfig` は、コマンドと同じく `.editorconfig` も読みます。
380
+ Prettier の CLI も既定では読みますが、Prettier の `resolveConfig` が読むのは、
381
+ `editorconfig: true` を渡したときだけです。
382
+
383
+ ### `clearConfigCache()`
384
+
385
+ `resolveConfig` は、Prettier の `resolveConfig` と同じく、
386
+ 一度読んだ設定ファイルの内容をプロセスが終わるまで覚えています。
387
+ そのため、後で設定ファイルが変わっても、`resolveConfig` の結果は変わりません。
388
+ エディターのファイル監視などで、
389
+ Prettier の設定ファイルや `.editorconfig` が変わったことをツールが知ったときは、
390
+ `clearConfigCache` を呼び出します。
391
+ すると、次に `resolveConfig` を呼び出したときに、設定ファイルを読み直します。
392
+ `clearConfigCache` は、
393
+ 覚えていた内容を消し終えたときに解決される Promise を返します。
394
+
395
+ ### `format(source, options)`
396
+
397
+ `format` は、Prettier の `format` と同じようにテキストを整形します。
398
+ ただし Markdown では、Mermaid のコードブロックだけを整形し、
399
+ ほかは書かれたまま残します。
400
+ ファイルも設定も読みません。
401
+
402
+ - `source`: ファイルのテキスト。
403
+ - `options.filepath`: ファイルのパスで、必須です。
404
+ パスのうち使うのは拡張子だけで、
405
+ 拡張子が `.mmd` か `.mermaid` ならテキストを 1 つの図として、
406
+ `.md` か `.markdown` なら Markdown として読みます。
407
+ ファイルは存在しなくてもかまいません。
408
+ - ほかのオプション: 同じパスについて `resolveConfig` が返したものを渡します。
409
+ 設定の `overrides` は、パスによって適用されるかどうかが変わるためです。
410
+ 使えるのは、[設定](#設定)に挙げた 8 つのオプションです。
411
+ Markdown では、`printWidth` はファイル全体の行の幅です。
412
+ リスト項目や引用の中の図は、その幅から、
413
+ 図の各行の前にあるものの幅を引いた幅で整形します。
414
+ 詳しくは、[コードブロックの詳細](#コードブロックの詳細)を参照してください。
415
+ - `filepath` とこの 8 つ以外のオプション(`parser`、`endOfLine`、
416
+ `semi` など)は、TypeScript では型エラーになり、JavaScript では無視されます。
417
+ TypeScript では、`format` のオプションの型は `FormatOptions` です。
418
+
419
+ `format` は、整形したテキストで解決される Promise を返します。
420
+ 改行コードとバイトオーダーマークは、テキストに書かれたまま残ります。
421
+ 詳しくは、[コードブロックの詳細](#コードブロックの詳細)を参照してください。
422
+
423
+ Markdown では、`format` は次の 3 種類のブロックを書かれたまま残し、
424
+ どれも報告しません。
425
+
426
+ - mermaid.js が拒否する図。
427
+ - インデントにあるタブの一部がインデント、残りが図と読まれるブロック。
428
+ - 開きフェンスが脚注のラベルの行にあるブロック。
429
+
430
+ 後の 2 種類は、[コードブロックの詳細](#コードブロックの詳細)で説明しています。
431
+ Prettier も、整形できない埋め込みのコードブロックを同じように残します。
432
+ mermaid.js が拒否する図を見つけるには、
433
+ [`@mmd-toolkit/parser`](../parser) で解析するか、
434
+ [`@mmd-toolkit/eslint-plugin`](../eslint-plugin) でファイルを lint します。
435
+
436
+ Promise は、次のときに拒否されます。
437
+
438
+ - `.mmd` か `.mermaid` のテキストを mermaid.js が拒否するときは、
439
+ `SyntaxError` で拒否されます。
440
+ このエラーは、
441
+ Prettier が `prettier-plugin-mmd` でテキストを整形するときに投げるものです。
442
+ エラーの `loc.start` と `loc.end` は、
443
+ エラーの範囲の始まりと終わりを `line` と `column` で示します。
444
+ `line` と `column` は、どちらも 1 から数えます。
445
+ 改行の位置のエラーのように、エラーの範囲が後の行の始まりまで続くときは、
446
+ `loc.end` はありません。
447
+ - オプションに Prettier が受け付けない値があるときは、
448
+ Prettier のエラーで拒否されます。
449
+ たとえば `printWidth: "wide"` なら、
450
+ エラーは `Invalid printWidth value. …` です。
451
+ `.mmd` か `.mermaid` のテキストでは、
452
+ mermaid.js が図を拒否するかどうかにかかわらず、そうなります。
453
+ Markdown のテキストでも、
454
+ `mmdfmt` が図を整形するコードブロックを 1 つでも持てば、
455
+ その図を mermaid.js が拒否するかどうかにかかわらず、そうなります。
456
+ どのブロックの図を整形するかは、
457
+ [コードブロックの詳細](#コードブロックの詳細) にあります。
458
+ そのようなブロックのない Markdown のテキストは、そのまま返します。
459
+ `mermaid` や `mmd` のコードブロックがないものと、
460
+ そのようなブロックがどれも書かれたまま残されるものです。
461
+ 書かれたまま残されるのは、次のブロックです。
462
+ - `<!-- prettier-ignore -->` の後のブロック。
463
+ - `<!-- prettier-ignore-start -->` と、
464
+ `<!-- prettier-ignore-end -->` の間のブロック。
465
+ - 開きフェンスが脚注のラベルの行にあるブロック。
466
+ - 字下げのタブの一部が図と読まれるブロック。
467
+ - `options.filepath` の拡張子が `.md`、`.markdown`、`.mmd`、
468
+ `.mermaid` のどれでもないときは、エラーで拒否されます。
469
+
470
+ ### 整形するファイル
471
+
472
+ コマンドが整形するのは、拡張子が `.md`、`.markdown`、`.mmd`、
473
+ `.mermaid` のファイルだけです。
474
+ また、`node_modules` やバージョン管理のディレクトリの下にあるパスと、
475
+ 実行するディレクトリの `.gitignore` が挙げるパスは飛ばします。
476
+ 詳しくは、[ファイルの除外](#ファイルの除外)を参照してください。
477
+ `format` は、ほかの拡張子のパスを拒否しますが、それ以外は、
478
+ パスがどこにあっても整形します。
479
+ コマンドと同じファイルを飛ばしたいツールは、
480
+ `format` を呼び出す前にパスを調べます。
481
+
482
+ ## 設定
483
+
484
+ 図のインデントは空白 2 つで、行の幅は Prettier の 80 です。
485
+ ファイルに `.editorconfig` や Prettier の設定が適用されるときは、
486
+ `mmdfmt` はそのうち 8 つのオプションを読みます。
487
+ `overrides` も含めて Prettier の CLI と同じように探します。
488
+ `.editorconfig` の `indent_style`、`indent_size`、`tab_width`、
489
+ `max_line_length` と、Prettier の設定ファイルのオプションです。
490
+ 設定ファイルについては、
491
+ [Prettier の文書](https://prettier.io/docs/configuration) を参照してください。
492
+ コードブロックでは、そのファイルは Markdown ファイルです。
493
+ 読めない設定ファイルはエラーです。
494
+ たとえば、この `.editorconfig` は図に空白 4 つのインデントを付け、
495
+ 行を 100 桁まで許します。
496
+
497
+ ```ini
498
+ [*.{md,mmd,mermaid}]
499
+ indent_style = space
500
+ indent_size = 4
501
+ max_line_length = 100
502
+ ```
503
+
504
+ 読む 8 つのオプションは次のとおりです。
505
+
506
+ - `printWidth` は行の幅です。
507
+ 行の幅が図の中で決めるのは、2 つです。
508
+ 1 行に書いたデータブロック `@{ … }` を複数行で印字するかどうかと、
509
+ Gantt のセクションのタスクの `:` をそろえるかどうかです。
510
+ 詳しくは、
511
+ [フォーマッターのオプション](https://mmd-toolkit.github.io/mmd-toolkit/ja/formatter/options.html#行の長さ)
512
+ を参照してください。
513
+ `max_line_length = off` は制限なしです。
514
+ リスト項目や引用の中のコードブロックでは、`printWidth` は、
515
+ 各行の前に `mmdfmt` が書くものの幅を引いた幅です。
516
+ 詳しくは、[コードブロックの詳細](#コードブロックの詳細)を参照してください。
517
+ - `tabWidth` と `useTabs` は、図のインデントを決めます。
518
+ - `embeddedLanguageFormatting`、`singleQuote`、`bracketSpacing`、`proseWrap`、
519
+ `trailingComma` は、図の YAML frontmatter に効きます。
520
+ Prettier が `prettier-plugin-mmd` で整形する場合と同じです。
521
+ `embeddedLanguageFormatting: "off"` は frontmatter を書かれたまま残します。
522
+
523
+ `mmdfmt` はこれ以外のオプションを読みません。
524
+ 後の版の Prettier が足すオプションも読みません。
525
+ 範囲(`rangeStart` と `rangeEnd`)、`cursorOffset`、
526
+ プラグマのオプション(`requirePragma`、`insertPragma`、`checkIgnorePragma`)、
527
+ `filepath`、ほかの言語のオプションは使いません。
528
+ `plugins` と `parser` も使いません。
529
+ `mmdfmt` は常に `prettier-plugin-mmd` で整形するので、
530
+ 設定が挙げるプラグインは読み込みません。
531
+ `endOfLine` は使いません。
532
+ ファイルの改行コードを残すからです。
533
+ 詳しくは、[コードブロックの詳細](#コードブロックの詳細)を参照してください。
534
+
535
+ ## エラーと終了コード
536
+
537
+ mermaid.js が拒否する図はそのまま残し、
538
+ 行と桁を付けて標準エラー出力に報告します。
539
+ ほかのファイルと、同じファイルのほかの図は整形します。
540
+
541
+ ```txt
542
+ docs/flow.mmd:3:1: error: Unexpected end of text
543
+ notes.md:6:1: warning: Unexpected end of text
544
+ ```
545
+
546
+ `.mmd` や `.mermaid` ファイルではエラーです。
547
+ Markdown のコードブロックでは警告です。
548
+ `--write` と `--stdin-filepath` では、警告の位置は整形後のテキストの位置です。
549
+ それより前の図の行が増減していても、実行後に開くテキストのブロックを指します。
550
+ `--write` のない `--check` と `--list-different` では、
551
+ 整形前のファイル内の位置です。
552
+ 行と桁は 1 から数え、
553
+ 桁は多くのエディターと同じく UTF-16 のコード単位で数えます。
554
+ どの図が拒否されるかは、
555
+ [フォーマッターの互換性](https://mmd-toolkit.github.io/mmd-toolkit/ja/formatter/compatibility.html)
556
+ で説明しています。
557
+
558
+ | コード | 意味 |
559
+ | ------ | ---------------------------------------------------------------------------------------------------- |
560
+ | `0` | エラーがなく、`--check` と `--list-different` では変わるファイルがないか、`--write` が付いています。 |
561
+ | `1` | `--write` のない `--check` か `--list-different` で、変わるファイルがあり、エラーはありません。 |
562
+ | `2` | エラーです。 |
563
+
564
+ エラーとは、`.mmd` や `.mermaid` ファイル内の拒否された図、
565
+ 読めないか書けないファイル、ファイルを選ばないパターン、読めない設定、
566
+ オプションの誤った使い方です。
567
+ エラーがあれば、変わるファイルがあっても終了コードは `2` です。
568
+
569
+ `.mmd` や `.mermaid` ファイルの図を mermaid.js が拒否するときのように、
570
+ ファイルを整形できないとき、`--check` の要約は、
571
+ 標準出力の `Error occurred when checking code style in the above file.` で、
572
+ 複数なら末尾が `in <n> files.` になります。
573
+ Prettier の `--check` と同じく、要約は整形できないファイルだけを数えます。
574
+ 読めないファイルと、ファイルを選ばないパターンは、エラーとして報告しますが、
575
+ 要約はそれらがないときと同じです。
576
+ パターンがファイルを 1 つも選ばないときもそうです。
577
+ 書けないファイルは、問題を修正したファイルとして数え、
578
+ `--write` と `--write --list-different` でも名前を挙げます。
579
+
580
+ ## Prettier を知っている方へ
581
+
582
+ 図は Prettier と `prettier-plugin-mmd` で整形するので、
583
+ プラグインの規則が適用されます。
584
+ Markdown と `.mmd` ファイルに Prettier とプラグインを使う場合とは、
585
+ 結果が 5 点で異なります。
586
+
587
+ - Prettier は、コードブロックの最後の行の末尾の空白を、
588
+ mermaid.js が図の一部として読む場合も、
589
+ 取り除きます([Markdown のコードブロック][markdown-code-blocks])。
590
+ `mmdfmt` はブロックのテキストだけを置き換えるので、その空白は残ります。
591
+ - Prettier は、`md` と指定したものなど、
592
+ Markdown のコードブロックを Markdown 文書として整形し、
593
+ その中のコードブロックの図も整形します。
594
+ `mmdfmt` はほかのコードブロックをすべてそのまま残します。
595
+ - Prettier はリスト項目や引用で行の前にあるものを自分で印字しますが、
596
+ `mmdfmt` は書かれたまま残します。
597
+ 詳しくは[コードブロックの詳細](#コードブロックの詳細)を参照してください。
598
+ リスト項目では、Prettier はマーカーを印字して内容を `tabWidth` にそろえます。
599
+ 引用では、`> ` を印字し、`>` とフェンスの間の空白とタブを取り除きます。
600
+ 内容の桁が違うと、項目や引用の中の図に残る行の幅がその差だけ違い、
601
+ 幅の近くにある 1 行のブロックを、一方は分け、他方は分けないことがあります。
602
+ - リスト項目や引用の中では、Prettier は Gantt のセクションのコロンを、
603
+ 行の前にあるものを数えずにそろえるので、
604
+ そろえた行が行の幅を超えることがあります。
605
+ `mmdfmt` はそれを数えるので、幅の近くでは、Prettier はセクションをそろえ、
606
+ `mmdfmt` はそろえないことがあります。
607
+ そのとき `mmdfmt` はコロンをそろえるために名前を空白で埋めず、
608
+ 各コロンの前の空白は書かれたままです。
609
+ 行の幅より広く書かれた行も、そのままです。
610
+ タスクは、どの Gantt の図でも同じ字下げに直すので、書かれた字下げが違うと、
611
+ コロンは行といっしょに動きます。
612
+ - Prettier は、次の 4 つの設定のもとで、図を書かれたまま残します。
613
+ `requirePragma: true` は、ファイルの先頭に、
614
+ `<!-- @format -->` か `<!-- @prettier -->` のコメントがない Markdown
615
+ ファイルを残します。
616
+ frontmatter があるときは、その後ろが先頭です。
617
+ `checkIgnorePragma: true` は、そこに、
618
+ `<!-- @noformat -->` か `<!-- @noprettier -->` のコメントがある Markdown
619
+ ファイルを残します。
620
+ ファイル全体を覆わない範囲は、Markdown ファイルも `.mmd` ファイルも残します。
621
+ `embeddedLanguageFormatting: "off"` は、
622
+ Markdown ファイルのすべてのコードブロックを残します。
623
+ `mmdfmt` は、この 4 つのどれのもとでも図を整形します。
624
+ 最初の 3 つは読みません。
625
+ どのファイルを整形するかは自分で決め(パターンと `.gitignore`)、
626
+ 図全体を整形するからです。
627
+ `embeddedLanguageFormatting` は図の frontmatter にだけ読み、
628
+ そのときは frontmatter を書かれたまま残します。
629
+
630
+ コマンドも Prettier の CLI とは異なります。
631
+ `.prettierignore` は読まず、`--ignore-path`、`--ignore-unknown`、
632
+ 独自の整形オプションはなく、設定は図のためだけに読みます。
633
+ `mmdfmt` が読まないオプションに、Prettier が拒む値を書いても、
634
+ ここではエラーになりません。
635
+ Prettier の CLI はそれをエラーにします。
636
+ たとえば、`semi: "yes"` です。
637
+
638
+ チェックの成功時には、
639
+ Prettier の `All matched files use Prettier code style!` の代わりに、
640
+ `All diagrams in the matched files use Prettier code style!` と書きます。
641
+ `mmdfmt` は図のほかを整形しないので、
642
+ Markdown ファイルの残りの部分はその形式とは限らないためです。
643
+ 警告は `mmdfmt --write` の実行を案内します。
644
+ `prettier --write` では Markdown ファイル全体が整形され、
645
+ プラグインが設定されていないと図は整形されないためです。
646
+
647
+ Prettier は `--write=false` を false と読みます。
648
+ `mmdfmt` は、値を取らないオプションでは `=` の後ろの値を無視し、
649
+ `--write` と読みます。
650
+ `--check=false` と `--list-different=false` も同じです。
651
+ また、
652
+ Prettier は `--write` の後ろに書いた `true` や `false` をその値と読みますが、
653
+ `mmdfmt` はパターンと読みます。
654
+ そのため、`mmdfmt --write false notes.md` は `notes.md` を整形し、
655
+ `false` に合うファイルがないと報告します。
656
+
657
+ `--check --list-different` はどちらでもエラーです。
658
+ `mmdfmt` は、ほかのオプションの誤った使い方と同じく `2` で終了し、
659
+ 書く誤りの文は、
660
+ `mmdfmt: error: Optional argument '--check' conflicts with '--list-different'`。
661
+ Prettier は `[error] Cannot use --check and --list-different together.` を書き、
662
+ `1` で終了します。
663
+ `mmdfmt` は、一緒に使えるオプションかを確かめるとき、
664
+ `--no-` の形もそのオプションを付けたと数えます。
665
+ そのため、`--check --list-different` と同じく、
666
+ `--no-check --list-different` もエラーになります。
667
+ Prettier は `--no-check --list-different` を受け付けます。
668
+
669
+ 標準入力で `--check` や `--list-different` を使うとき、
670
+ Prettier は読めないテキストでも `0` で終了しますが、`mmdfmt` は、
671
+ ほかの場合と同じく、
672
+ 拒否された図では `2` で終了します([エラーと終了コード](#エラーと終了コード))。
673
+ `.mmd` や `.mermaid` のファイルの拒否された図を、`mmdfmt` は、
674
+ `docs/flow.mmd:3:1: error: Unexpected end of text` のように、
675
+ 位置を付けた 1 行で報告します。
676
+ Prettier は `[error] docs/flow.mmd: SyntaxError: Unexpected end of text`
677
+ を書き、続けてその場所の前後の行を、それぞれ `[error]` の後に書きます。
678
+ Markdown のファイルの中の拒否された図では、
679
+ `mmdfmt` は `notes.md:6:1: warning: Unexpected end of text` のような警告を 1
680
+ 行書き、Prettier は何も書きません。
681
+ どちらも、これをエラーとはしません。
682
+
683
+ Prettier は、`CI` の環境変数があるときや Windows では、
684
+ 出力先が端末でなくても `warn` の語を黄色にし、
685
+ 変わらなかったファイルの名前を灰色にします。
686
+ `mmdfmt` がそれらに色を付けるのは、色を出せる端末か、
687
+ `FORCE_COLOR` があるときだけで、`--color` や `--no-color` はありません。
688
+
689
+ ## コードブロックの詳細
690
+
691
+ コードブロックは、情報文字列の最初の語が `mermaid` か `mmd` のもので、
692
+ 大文字と小文字を区別し、Prettier の Markdown パーサーと同じように見つけます。
693
+ ほかのコードブロックの中のフェンスは図として扱わず、
694
+ リストや引用の中のブロックは見つけます。
695
+
696
+ 変わるのはフェンスの間の行だけです。
697
+ `mmdfmt` が書く各行は、開きフェンスと同じ行でその前にあるものから始まり、
698
+ リストのマーカーを空白に変えるので、図はリスト項目や引用の中にとどまります。
699
+ 空の行には、その始まりから末尾の空白を取り除いたものを書き、
700
+ 引用では `>` だけになります。
701
+ たとえば、このブロックは、
702
+
703
+ <!-- prettier-ignore -->
704
+ ````md
705
+ > - ```mermaid
706
+ > flowchart LR
707
+ > A-->B
708
+ >
709
+ > B-->C
710
+ > ```
711
+ ````
712
+
713
+ 次のようになります。
714
+
715
+ <!-- prettier-ignore -->
716
+ ````md
717
+ > - ```mermaid
718
+ > flowchart LR
719
+ > A --> B
720
+ >
721
+ > B --> C
722
+ > ```
723
+ ````
724
+
725
+ 開きフェンスが `>```mermaid` のように `>` の直後にあるときは、
726
+ 書く行では `>` の後ろに空白を付けます。
727
+ 引用は `>` の後ろの空白 1 つをマーカーの一部として読むので、そうしないと、
728
+ 空白で始まる図の行がその空白を失います。
729
+
730
+ リスト項目や引用の中の図の行の幅は、ファイルの行の幅から、
731
+ `mmdfmt` が各行の前に書くものの幅を引いた幅で、幅は 1 以上です。
732
+ 前に書くものは、1 文字を 1 桁と数えます。
733
+ タブだけは次の `tabWidth` の倍数の桁まで進み、
734
+ `tabWidth` が 0 のときは幅を持ちません。
735
+ たとえば、行の幅が 40 のとき、行が空白 2 つで始まるリスト項目の中の図は、
736
+ 38 桁として整形します。
737
+ `tabWidth` が 4 のとき、行が `>` とタブで始まる引用の中の図は、
738
+ タブが 4 桁目まで進むので、36 桁として整形します。
739
+ Prettier は、コンテナの中のデータブロックから、
740
+ 自分が行の前に印字するものの幅を同じように引きますが、
741
+ 印字するものが `mmdfmt` の書くものと違うことがあります。
742
+ 詳しくは、
743
+ [Prettier を知っている方へ](#prettier-を知っている方へ)を参照してください。
744
+ Gantt のセクションのコロンは例外で、Prettier はそろえるとき、
745
+ 行の前にあるものを数えません。
746
+
747
+ 閉じていないブロックは、リスト項目、引用、またはファイルの終わりまで続き、
748
+ ほかと同じく整形します。
749
+ 改行なしでファイルを終えるときは、最後の行も改行なしのままです。
750
+ そのブロックの最後にある空の行や空白とタブだけの行は書かれたまま残し、
751
+ それらだけのブロックも同じく残します。
752
+ Markdown はそれらをブロックの一部として読みますが、続くものとの区切りにもなり、
753
+ リストの項目の間の空の行は、項目の間を空けて描くリストを保ちます。
754
+
755
+ 次の 2 種類のブロックは書かれたまま残し、位置を付けて警告します。
756
+
757
+ - インデントにあるタブの一部がインデント、残りが図と読まれるブロック。
758
+ 空白 2 つでインデントしたリスト項目の行頭などが当てはまります。
759
+ - `[^1]: ```mermaid` のように、開きフェンスが脚注のラベルの行にあるブロック。
760
+
761
+ フェンスの間が空か空白だけの図は空になります。
762
+
763
+ ファイルは改行コードを保ちます。
764
+ `mmdfmt` が書く各行は、ファイルの最初の行と同じ改行コードで終わり、
765
+ 1 行だけのファイルでは `\n` で終わりますが、最後に書く行だけは、
766
+ 整形前の図の最後の行と同じ改行コードで終わります。
767
+ そのため、書いた行の次の行の直前には、整形前と同じ改行コードが残ります。
768
+ 別の改行コードにすると、その行の改行コードとつながって 1 つになることがあり、
769
+ `\n` で終わる空の行の前にある `\r` が 1 つの `\r\n` と読まれるように、
770
+ 行の数が変わってしまいます。
771
+ 図が空になるときは、開きフェンスの行を、元の改行コードの代わりに、
772
+ 整形前の図の最後の行の改行コードで終えます。
773
+ フェンスの間の行の外で変わるのは、この場合だけです。
774
+ Markdown ファイルでは、変わる図の行だけを書きます。
775
+ エラーと警告の行と桁では、行は `\n`、`\r\n`、`\r` で終わります。
776
+
777
+ ## 文書
778
+
779
+ - [フォーマッターのオプション](https://mmd-toolkit.github.io/mmd-toolkit/ja/formatter/options.html):
780
+ 図にインデントと行の幅をどう適用するか。
781
+ - [フォーマッターの互換性](https://mmd-toolkit.github.io/mmd-toolkit/ja/formatter/compatibility.html):
782
+ 拒否される図、mermaid.js との違い、整形が保証すること。
783
+
784
+ [markdown-code-blocks]: ../prettier-plugin-mmd/docs/compatibility.ja.md#markdown-のコードブロック