TL;DR
(2023.07追記)
-
Prettierを入れているとMarkdownも自動フォーマットされる
- Prettier v2までは日本語Markdown文書の整形ルールに問題があった
- JS整形に比べて、Markdown整形はルール設定はほとんどできない
- Prettier v3にアップグレードするといい感じになる
- 整形ルールを自由に設定したければ
-
.prettierignore
を作って*.md
はフォーマットさせないように - Remarkをインストールすれば柔軟な整形ルール設定が可能
-
この記事を書いた背景
(2023.07追記)
Prettier v2時代にハマったのがきっかけですが、v3.0になって見事に改善されました。めでたい!!!
Prettier 3.0: Hello, ECMAScript Modules!
原文引用
Stop inserting spaces between Chinese or Japanese and Western characters
Previously, Prettier would insert spaces between Chinese or Japanese and Western characters (letters and digits). While some people prefer this style, it isn’t standard, and is in fact contrary to official guidelines. Please see here for more details. We decided it’s not Prettier’s job to enforce a particular style in this case, so spaces aren’t inserted anymore, while existing ones are preserved. If you need a tool for enforcing spacing style, consider textlint-ja or lint-md (rules space-round-alphabet and space-round-number).
DeepL訳
中国語または日本語と欧米語の文字の間にスペースを挿入しないようにした。
以前は、Prettierは中国語または日本語と西洋文字(文字と数字)の間にスペースを挿入していました。このスタイルを好む人もいますが、標準ではありませんし、公式ガイドラインにも反しています。詳しくはこちらをご覧ください。この場合、特定のスタイルを強制するのはPrettierの仕事ではないと判断し、スペースは挿入されなくなり、既存のスペースは保持されるようになりました。スペーシングスタイルを強制するツールが必要なら、textlint-jaかlint-md(ルールspace-round-alphabetとspace-round-number)を検討してください。
「詳しくはこちら」で紹介されてるように、こんなプラグインが2022年にリリースされていたんですね。知らなかった!Qiita記事も見つけました。
和欧文字間(漢字仮名と英数字の間)に半角スペースが挿入されないようにするPrettier Markdownプラグインを作った
Prettier v3ではこのプラグインの機能がデフォルトで入ったようです。
@tats-u さん、良い仕事してくださってありがとうございました!!!
ほとんどの方は、Prettier v3に移行すればこの記事の解説は不要だと思います。
しかし、やはり整形ルールは細かいところまで自分で調整したいのだ!という方は、整形ルールを自由に設定する方法から読んでください
当時の苦悩の記録として以下は残しておきますが、あくまでPrettire v2以前の問題として理解をお願いします。
Markdownの自動フォーマットが意味不明だった
Visual Studio Codeでeditor.formatOnSave
を有効にすると、なぜかMarkdownのファイルも保存時に自動整形されちゃってました。
特にフォーマッタの設定をした覚えがないのに、やって欲しくないフォーマットを勝手にするので結構悩んでたのですよ。
例えば以下のように、英語・日本語が連続する文字を入れると
PDFテンプレート
↓
PDF テンプレート
ご丁寧に、境界にスペースを入れてくださるのです。
これはレンダリング後の表示にも影響してくるので勘弁してほしい。
英語圏の人は、こんな問題には気づかないんだろうなー。
犯人はPrettier
JavaScriptコードを自動フォーマットする目的で入れているPrettier - Code formatterが、Markdownも自動フォーマットしてくれてたのが原因でした。JS専用じゃなくて、言語の守備範囲はかなり広いのですな・・・
Prettierのドキュメントを読んでも、JSのルールは調整できるんですが、Markdownのルール調整が全然できなくて、上記の「英語と日本語の境界にスペースが入る問題」は解決できませんでした。
parser
を何とかしてやれば行けそうな気もするけど、ハードル高いのでやめておく。
整形ルールを自由に設定する方法
PrettierではMarkdownの整形ルール設定がほとんどできないので、自由に設定したければ他のツールでフォーマットする必要があります。
PrettierのMarkdownフォーマットを無効化
まずはVSCodeの設定に以下を追記して、Markdownをフォーマットしないように設定します。
"prettier.disableLanguages": [
"vue",
"markdown",
],
ちなみにvue
はデフォルトなのでそのまま含んでますが、vue
にはPrettier使いたければ含まなくてもOK。
RemarkでMarkdownを独自にフォーマット
Markdownの自動フォーマットができて、自分で設定調整もできるVSCodeの機能拡張を探したところ、Remarkが一番良さげでした。
インストールして、コマンドパレットからRemark: Beautify markdown code
を選ぶとmdファイルのフォーマットができます。なぜかeditor.formatOnSave
では動いてくれないので、「フォーマットする」というトリガは自分で操作しないとダメっぽいですね。
この時点で、最初の「英語と日本語の境界にスペースが入る問題」は解決されとります!あとは、もう少し自分好みの整形ルールに調整してあげるだけ。
整形ルールの調整は、VSCodeの設定ファイル内にこんな感じで書けます。
"remark.format": {
"rules": {
"bullet": "*",
"listItemIndent": 1,
"fences": true,
}
},
rules
の設定項目は、こちら本家Remarkドキュメントのoptions
のプロパティが使えます。
https://github.com/remarkjs/remark/blob/master/packages/remark-stringify/readme.md#options
VSCodeのプラグインとしてもデフォルト値は持っていて、package.json
にベタ書きされてました。
https://github.com/mrmlnc/vscode-remark/blob/master/package.json
ほとんどは本家Remarkのdefault
そのまんまだけど、一部書かれてないプロパティもあったので、本家とは若干違うのかも。詳しくは見てません。
あと「英語と日本語の境界にスペースを入れる」設定を、そもそもどうやるのか分かりませんでしたw
remark.js系ツールについて
remarkとremark-lintの違い
僕が以前書いたこの記事
Atomのlinter-markdownを.remarkrcで設定する方法
当時はVSCodeではなくAtom使ってたわけですが、そこではremark-lintというのを使ってました。
今回のVSCode機能拡張で使われてるremarkとは別物で、でも両方同じGitHub Organizationのremarkjs配下のリポジトリです。
VSCode機能拡張の方に、こんなIssueも出てました。
Implement remark-lint #4
なので、remark-lint
の方が新しくて機能充実してるってことなのかな?
上の記事ではremark-lint
の設定を.remarkrc
ファイルで書いてたんですけど、remark
ではそのファイルが使えないっぽいです。できればVSCodeの設定じゃなくて、プロジェクト単位で.remarkrc
を置いておきたいなーと思うので、対応してほしいですねー。
PrettierのParserもremark-parseだった
PrettierドキュメントのParserセクションからリンク貼られてるのも、「remark-parse」という「remark」リポジトリ内のページでした。
https://github.com/remarkjs/remark/tree/master/packages/remark-parse
とにかくMarkdownを解析するならremarkって感じなんでしょうね。(テキトーな解釈)
MDAST
そもそもremark.js系の色々なリポジトリからリンク貼られてるのが、こちらの「MDAST」というリポジトリ。
https://github.com/syntax-tree/mdast
remarkは、全体的にこのMDASTを使っているっぽいです。
MDASTやASTについては、この辺の記事が参考になりそう。(あまりしっかり読んでないけど、奥が深そうです・・・)
markdownを直接ReactElementに変換するコンパイラを書いた
QiitaとMarkdownとコンテンツオーサリング#Markdown AST
おわりに
例のごとく、後半は色々と枝葉の情報ばかり調べちゃいました。
コードフォーマッタを作るときは、結局はその言語の構文解析が必要で、末端のツールは違っても最終的に同じツールに収束していくのが面白かったです。
あと「remark.js」って、全然別物として2種類あるんですね。。
今回使った「Markdownプロセッサ」がこちら。
https://remark.js.org/
もひとつが、「Markdownのスライドショーツール」
https://remarkjs.com/
紛らわしい。。。