mmdfmt 0.0.0 → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yosuke Ota
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.ja.md ADDED
@@ -0,0 +1,429 @@
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-を知っている方へ)の 2 つの場合を除き、
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 <pattern>...
117
+ mmdfmt --check <pattern>...
118
+ mmdfmt --stdin-filepath <path>
119
+ ```
120
+
121
+ | オプション | 動作 |
122
+ | ------------------------- | ---------------------------------------------------------------- |
123
+ | `--write` | ファイルを直接整形し、変わったものを標準出力に挙げます。 |
124
+ | `--check` | 何も変えず、`--write` が変えるファイルを標準出力に挙げます。 |
125
+ | `--stdin-filepath <path>` | 標準入力を `<path>` のファイルとして整形し、標準出力に書きます。 |
126
+ | `-h`, `--help` | 使い方を標準出力に書きます。 |
127
+ | `-v`, `--version` | バージョンを標準出力に書きます。 |
128
+
129
+ `--write` か `--check` のどちらかにパターンを付けるか、
130
+ `--stdin-filepath` を単独で指定します。
131
+ `--help` と `--version` は、
132
+ 表のほかのオプションを一緒に付けても出力するだけです。
133
+ ほかの組み合わせはエラーです。
134
+ 引数がまったくないときは、`mmdfmt` は使い方を標準エラー出力に書き、
135
+ `2` で終了します。
136
+
137
+ ほかのオプションはありません。
138
+ 整形オプションも、独自の設定ファイルも、
139
+ 無視ファイルを指定するオプションもありません。
140
+ 値を取らないオプションでは、
141
+ 引数のライブラリ [gunshi](https://gunshi.dev) の読み方に従い、
142
+ `=` の後ろの値を無視します。
143
+ `--write=false` は `--write` と同じに読みます。
144
+
145
+ `head` が必要な行数を読み終えたときのように、標準出力の読み手がいなくなると、
146
+ `mmdfmt` はそこへの出力を止め、何も報告せずに最後まで処理します。
147
+ `--write` は引き続きすべてのファイルを書き換え、
148
+ 終了コードも処理の結果を示します。
149
+
150
+ ### パターン
151
+
152
+ - ファイルのパスは、そのファイルを選びます。
153
+ - `.` などのディレクトリのパスは、その下のファイルを選びます。
154
+ - ほかのパターンは glob で、名前がドットで始まるものにも一致します。
155
+ シェルではなく `mmdfmt` が展開するよう、引用符で囲みます。
156
+ 例: `npx mmdfmt --write "docs/**/*.md"`。
157
+ Windows では、glob の `\` を `/` と読みます。
158
+ - `!` で始まるパターンは、
159
+ 一致するファイルをほかのパターンの選択から取り除きます。
160
+ [ファイルの除外](#ファイルの除外)を参照してください。
161
+ - `--` の後ろの引数はすべてパターンなので、`mmdfmt --write -- -a.md` のように、
162
+ `-` で始まる名前のファイルも渡せます。
163
+
164
+ 選んだファイルのうち、名前が `.md`、`.markdown`、`.mmd`、
165
+ `.mermaid` で終わるものを、いくつのパターンが選んでも 1 回ずつ整形します。
166
+ そのどれも選ばないパターンはエラーです。
167
+ そのようなファイルのないプロジェクトでは `mmdfmt --check .` は失敗し、
168
+ ほかの語尾のファイルを名前で指定しても同じです。
169
+ Prettier の CLI と同じく、
170
+ `!` のパターンによって選んだファイルがすべて取り除かれるパターンもエラーです。
171
+ `.gitignore` が挙げるファイルだけを選ぶパターンはエラーではありません。
172
+
173
+ Prettier の CLI と同じく、`mmdfmt` は、
174
+ `node_modules` やバージョン管理のディレクトリ内のパスを名指すパターンを、
175
+ ファイル、ディレクトリ、glob のどれであっても何も報告せずに飛ばします。
176
+ 例: `node_modules/pkg` や `"node_modules/**/*.md"`。
177
+ ファイルを選ぶパターンが 1 つも残らないときはエラーです。
178
+
179
+ ## ファイルの除外
180
+
181
+ `mmdfmt` は次のファイルを除外します。
182
+
183
+ - `node_modules` と、バージョン管理のディレクトリ(`.git`、`.hg`、`.jj`、`.sl`、
184
+ `.svn`)の下にあるファイル。
185
+ パターンで名指す場合も同じです([パターン](#パターン))。
186
+ - `mmdfmt` を実行するディレクトリの `.gitignore` が挙げるファイル。
187
+ サブディレクトリや親ディレクトリの `.gitignore` は読みません。
188
+ - `!` のパターンに一致するファイル。
189
+ bash では、二重引用符内の `!` は履歴展開を始めるため、単一引用符で囲みます。
190
+ 例: `npx mmdfmt --write . '!vendor/**'`。
191
+ Windows のコマンドプロンプトでは二重引用符を使います。
192
+
193
+ `mmdfmt` は `.prettierignore` を読みません。
194
+ そこに Markdown を挙げて Prettier で整形しないようにしたプロジェクトでも、
195
+ 図を整形できます。
196
+
197
+ Markdown ファイルの図を 1 つそのまま残すには、
198
+ コードブロックの前に `<!-- prettier-ignore -->` を置き、
199
+ 間には空行以外を入れません。
200
+ リストや引用の外では、
201
+ `<!-- prettier-ignore-start -->` と `<!-- prettier-ignore-end -->`
202
+ の間の図をすべてそのまま残します。
203
+ これらは Prettier が読むコメントです。
204
+ `.mmd` ファイル全体をそのまま残すには、
205
+ `!` のパターンか `.gitignore` で除外します。
206
+
207
+ ## CI で確認する
208
+
209
+ プロジェクトに `mmdfmt` をインストールし、
210
+ CI で依存パッケージをインストールして(`npm ci`)、次を実行します。
211
+
212
+ ```sh
213
+ npx mmdfmt --check .
214
+ ```
215
+
216
+ 整形されていないファイルがあると、`--check` は標準出力に挙げ、`1` で終了します。
217
+ すべて整形済みなら、何も出力せず `0` で終了します。
218
+ 依存パッケージをインストールしていないと、
219
+ `npx` は固定したバージョンではなく最新版を実行してしまいます。
220
+
221
+ mermaid.js が拒否する図のある `.mmd` や `.mermaid` ファイルは、
222
+ `2` でチェックに失敗します。
223
+ Markdown 内の図を mermaid.js が拒否しても、警告にとどまります。
224
+ 文書では壊れた図を意図して示すことがあり、
225
+ `mmdfmt` にはそれで失敗させるオプションはありません。
226
+ そのような図で CI を失敗させるには、
227
+ 図を報告する [`@mmd-toolkit/eslint-plugin`](../eslint-plugin) で Markdown を
228
+ lint します。
229
+
230
+ 図のファイルが 1 つもないプロジェクトでは、`--check .` は `2` で失敗します。
231
+ `.` の代わりに、図のあるディレクトリを指定してください。
232
+
233
+ ## コミット前に整形する
234
+
235
+ husky や simple-git-hooks などの Git フックマネージャーがコミットごとに実行する
236
+ [lint-staged](https://github.com/lint-staged/lint-staged) を使う場合は、
237
+ `package.json` に次を追加します。
238
+
239
+ ```json
240
+ {
241
+ "lint-staged": {
242
+ "*.{md,markdown,mmd,mermaid}": "mmdfmt --write"
243
+ }
244
+ }
245
+ ```
246
+
247
+ glob はこの 4 つの語尾に限ってください。
248
+ `mmdfmt` には Prettier の `--ignore-unknown` のようなオプションはなく、
249
+ ほかの語尾のファイルはエラーです。
250
+ lint-staged が渡す絶対パスを、`mmdfmt` は受け付けます。
251
+
252
+ ## エディターやほかのツールから使う
253
+
254
+ `mmdfmt` にはエディターの拡張機能はありません。
255
+ 標準入力に対してフォーマッターを実行するエディターやツールでは、
256
+ ファイルのテキストを標準入力に渡して次を実行し、
257
+ 標準出力から整形結果を受け取れます。
258
+
259
+ ```sh
260
+ mmdfmt --stdin-filepath docs/guide.md
261
+ ```
262
+
263
+ そのパスのファイルは、読み書きしません。
264
+ 相対パスは `mmdfmt` を実行するディレクトリを基準に解決します。
265
+ パスの語尾がテキストを図として読むか Markdown として読むかを決め、
266
+ ディレクトリがどの `.editorconfig` と Prettier の設定を適用するかを決めます。
267
+
268
+ - Markdown のテキストは、整形したか、すでに整形済みかにかかわらず全体を出力し、
269
+ 図が拒否されても終了コードは `0` です。
270
+ 警告は標準エラー出力に書きます。
271
+ - mermaid.js がテキストを拒否する図では、標準出力に何も書かず、
272
+ 標準エラー出力にエラーを書き、終了コードは `2` です。
273
+ - `node_modules` やバージョン管理のディレクトリの下にあるパス、
274
+ または `mmdfmt` を実行するディレクトリの `.gitignore` が挙げるパスでは、
275
+ テキストをそのまま返します。
276
+ - ほかの語尾のパスはエラーです。
277
+
278
+ ## インデント
279
+
280
+ 図のインデントは空白 2 つです。
281
+ ファイルに `.editorconfig` や Prettier の設定が適用されるときは、
282
+ そのインデントを使います。
283
+ `.editorconfig` の `indent_style`、`indent_size`、`tab_width`、
284
+ または [Prettier の設定ファイル](https://prettier.io/docs/configuration)の
285
+ `useTabs` と `tabWidth` で、
286
+ `overrides` も含めて Prettier の CLI と同じように探します。
287
+ コードブロックでは、そのファイルは Markdown ファイルです。
288
+ 読めない設定ファイルはエラーです。
289
+ たとえば、この `.editorconfig` は図に空白 4 つのインデントを付けます。
290
+
291
+ ```ini
292
+ [*.{md,mmd,mermaid}]
293
+ indent_style = space
294
+ indent_size = 4
295
+ ```
296
+
297
+ 設定のほかの項目は使いません。
298
+
299
+ ## エラーと終了コード
300
+
301
+ mermaid.js が拒否する図はそのまま残し、
302
+ 行と桁を付けて標準エラー出力に報告します。
303
+ ほかのファイルと、同じファイルのほかの図は整形します。
304
+
305
+ ```txt
306
+ docs/flow.mmd:3:1: error: Unexpected end of text
307
+ notes.md:6:1: warning: Unexpected end of text
308
+ ```
309
+
310
+ `.mmd` や `.mermaid` ファイルではエラーです。
311
+ Markdown のコードブロックでは警告です。
312
+ `--write` と `--stdin-filepath` では、警告の位置は整形後のテキストの位置です。
313
+ それより前の図の行が増減していても、実行後に開くテキストのブロックを指します。
314
+ 何も書き換えない `--check` では、整形前のファイル内の位置です。
315
+ 行と桁は 1 から数え、
316
+ 桁は多くのエディターと同じく UTF-16 のコード単位で数えます。
317
+ どの図が拒否されるかは、
318
+ [フォーマッターの互換性](https://mmd-toolkit.github.io/mmd-toolkit/ja/formatter/compatibility.html)
319
+ で説明しています。
320
+
321
+ | コード | 意味 |
322
+ | ------ | -------------------------------------------------------- |
323
+ | `0` | エラーがなく、`--check` ではどのファイルも整形済みです。 |
324
+ | `1` | `--check` で、変わるファイルがあり、エラーはありません。 |
325
+ | `2` | エラーです。 |
326
+
327
+ エラーとは、`.mmd` や `.mermaid` ファイル内の拒否された図、
328
+ 読めないか書けないファイル、ファイルを選ばないパターン、読めない設定、
329
+ オプションの誤った使い方です。
330
+ エラーがあれば、変わるファイルがあっても終了コードは `2` です。
331
+
332
+ ## Prettier を知っている方へ
333
+
334
+ 図は Prettier と `prettier-plugin-mmd` で整形するので、
335
+ プラグインの規則が適用されます。
336
+ Markdown に Prettier とプラグインを使う場合とは、結果が 2 点で異なります。
337
+
338
+ - Prettier は、コードブロックの最後の行の末尾の空白を、
339
+ mermaid.js が図の一部として読む場合も、
340
+ 取り除きます([Markdown のコードブロック][markdown-code-blocks])。
341
+ `mmdfmt` はブロックのテキストだけを置き換えるので、その空白は残ります。
342
+ - Prettier は、`md` と指定したものなど、
343
+ Markdown のコードブロックを Markdown 文書として整形し、
344
+ その中のコードブロックの図も整形します。
345
+ `mmdfmt` はほかのコードブロックをすべてそのまま残します。
346
+
347
+ コマンドも Prettier の CLI とは異なります。
348
+ `.prettierignore` は読まず、`--ignore-path`、`--ignore-unknown`、
349
+ 整形オプションはなく、設定からはインデントだけを使います。
350
+
351
+ ## コードブロックの詳細
352
+
353
+ コードブロックは、情報文字列の最初の語が `mermaid` か `mmd` のもので、
354
+ 大文字と小文字を区別し、Prettier の Markdown パーサーと同じように見つけます。
355
+ ほかのコードブロックの中のフェンスは図として扱わず、
356
+ リストや引用の中のブロックは見つけます。
357
+
358
+ 変わるのはフェンスの間の行だけです。
359
+ `mmdfmt` が書く各行は、開きフェンスと同じ行でその前にあるものから始まり、
360
+ リストのマーカーを空白に変えるので、図はリスト項目や引用の中にとどまります。
361
+ 空の行には、その始まりから末尾の空白を取り除いたものを書き、
362
+ 引用では `>` だけになります。
363
+ たとえば、このブロックは、
364
+
365
+ <!-- prettier-ignore -->
366
+ ````md
367
+ > - ```mermaid
368
+ > flowchart LR
369
+ > A-->B
370
+ >
371
+ > B-->C
372
+ > ```
373
+ ````
374
+
375
+ 次のようになります。
376
+
377
+ <!-- prettier-ignore -->
378
+ ````md
379
+ > - ```mermaid
380
+ > flowchart LR
381
+ > A --> B
382
+ >
383
+ > B --> C
384
+ > ```
385
+ ````
386
+
387
+ 開きフェンスが `>```mermaid` のように `>` の直後にあるときは、
388
+ 書く行では `>` の後ろに空白を付けます。
389
+ 引用は `>` の後ろの空白 1 つをマーカーの一部として読むので、そうしないと、
390
+ 空白で始まる図の行がその空白を失います。
391
+
392
+ 閉じていないブロックは、リスト項目、引用、またはファイルの終わりまで続き、
393
+ ほかと同じく整形します。
394
+ 改行なしでファイルを終えるときは、最後の行も改行なしのままです。
395
+ そのブロックの最後にある空の行や空白とタブだけの行は書かれたまま残し、
396
+ それらだけのブロックも同じく残します。
397
+ Markdown はそれらをブロックの一部として読みますが、続くものとの区切りにもなり、
398
+ リストの項目の間の空の行は、項目の間を空けて描くリストを保ちます。
399
+
400
+ 次の 2 種類のブロックは書かれたまま残し、位置を付けて警告します。
401
+
402
+ - インデントにあるタブの一部がインデント、残りが図と読まれるブロック。
403
+ 空白 2 つでインデントしたリスト項目の行頭などが当てはまります。
404
+ - `[^1]: ```mermaid` のように、開きフェンスが脚注のラベルの行にあるブロック。
405
+
406
+ フェンスの間が空か空白だけの図は空になります。
407
+
408
+ ファイルは改行コードを保ちます。
409
+ `mmdfmt` が書く各行は、ファイルの最初の行と同じ改行コードで終わり、
410
+ 1 行だけのファイルでは `\n` で終わりますが、最後に書く行だけは、
411
+ 整形前の図の最後の行と同じ改行コードで終わります。
412
+ そのため、書いた行の次の行の直前には、整形前と同じ改行コードが残ります。
413
+ 別の改行コードにすると、その行の改行コードとつながって 1 つになることがあり、
414
+ `\n` で終わる空の行の前にある `\r` が 1 つの `\r\n` と読まれるように、
415
+ 行の数が変わってしまいます。
416
+ 図が空になるときは、開きフェンスの行を、元の改行コードの代わりに、
417
+ 整形前の図の最後の行の改行コードで終えます。
418
+ フェンスの間の行の外で変わるのは、この場合だけです。
419
+ Markdown ファイルでは、変わる図の行だけを書きます。
420
+ エラーと警告の行と桁では、行は `\n`、`\r\n`、`\r` で終わります。
421
+
422
+ ## 文書
423
+
424
+ - [フォーマッターのオプション](https://mmd-toolkit.github.io/mmd-toolkit/ja/formatter/options.html):
425
+ 図にインデントをどう適用するか。
426
+ - [フォーマッターの互換性](https://mmd-toolkit.github.io/mmd-toolkit/ja/formatter/compatibility.html):
427
+ 拒否される図、mermaid.js との違い、整形が保証すること。
428
+
429
+ [markdown-code-blocks]: ../prettier-plugin-mmd/docs/compatibility.ja.md#markdown-のコードブロック