はじめに
Prettier - Code formatter(VSCode拡張)でMarkdownをフォーマットすると、英語(アルファベット)と日本語の間に半角スペースが入ります。
例えば、
IPアドレス
は間にスペースが入りIP アドレス
となります。
この問題は以下の記事でも指摘されています。
VSCodeでMarkdownの自動フォーマット&整形ルールを自由に設定
この原因を調査し、強引に修正しました。
コメントより追記(2021.04.05)
この問題に対処する便利なプラグインが @tats-u さんにより作成されました。
記事の『prettier-plugin-md-nocjspを利用する』の項だけお読み下さい。
prettier-plugin-md-nocjspを利用する
環境
動作を確認した環境は以下の通りです。
- Windows 10 Pro(64bit)
- VS Code 1.64.2
- Prettier - Code formatter 9.2.0
原因
原因はPrettierにあります。
これはPrettierのPlaygroundでも動作がそのようになることから明らかです。
対処法がないかググってみると、以下のissueが見つかりました。
Markdown: unnecessary space is inserted between Korean & English words
韓国語と英語の間にスペースが入ってしまうというissueです。
issueを読むと以下のことが分かります。
- CJKV日中韓越情報処理によれば、慣例として余分なスペースを使用するとある。
- 過去に議論があったようで(ref: ikatyang/cjk-regex#48)そちらを読むと、W3C typographyの要件にもスペースを入れるとある。
- PrettierのMarkdown対応部分を書いてる人は台湾に住んでいる
美少女らしい。
スペース無し派、劣勢ですかね・・・
でもこれテキストではなく、プレビューしたときにCSSでスタイリングすべきことのような気がします。
そして、issueを受けて韓国語はスペースを入れないという仕様に変更されています。
どのような修正がされたのかは、下記を見ると大体わかります。
https://github.com/prettier/prettier/pull/5040/commits/da6186995df3ba1f8bdeb126d794fb32c404bcdb
ここまで分かれば何とか出来そうですね。
対処
対処方法として2パターン思いつきました。
- 例外としている韓国語のパターンに日本語も追加する
- スペースを追加している処理をなくす
VSCodeの拡張はJavaScriptで書かれているので、直接拡張のjsファイルを修正して対処できます。
対処法1
まず、Prettierのファイルがあるディレクトリを開きます。
Windowsであれば、下記をコピペしてファイル名を指定して実行で開けます。
%USERPROFILE%\.vscode\extensions\esbenp.prettier-vscode-3.20.0\node_modules\prettier
ディレクトリ内のindex.jsをコピーしてindex.js.bkなどとしてバックアップしておきます。
index.jsをエディタで開き、38438行目まで移動します。
38438 から 38441行目が以下のようになっています。
var cjkPattern = json.cjkPattern,
kPattern = json.kPattern,
punctuationPattern = json.punctuationPattern;
var getLast$3 = util.getLast;
ここのkPattern
と言う変数が韓国語の判定に使われているので、38439行目を修正し以下のようにします。
var cjkPattern = json.cjkPattern,
kPattern = json.cjkPattern,
punctuationPattern = json.punctuationPattern;
var getLast$3 = util.getLast;
kPatternにcjkPatternと同じ、json.cjkPatternを代入します。
中国語も巻き添えですが、まぁ良しとします。
対処法2
対処法1を行った場合は不要です。
まず、Prettierのファイルがあるディレクトリを開きます。
Windowsであれば、下記をコピペしてファイル名を指定して実行で開けます。
%USERPROFILE%\.vscode\extensions\esbenp.prettier-vscode-3.20.0\node_modules\prettier
ディレクトリ内のindex.jsをコピーしてindex.js.bkなどとしてバックアップしておきます。
index.jsをエディタで開き、38514行目まで移動します。
38514 から 38529行が以下のようになっています。
if (lastNode && lastNode.type === "word") {
if (lastNode.kind === KIND_NON_CJK && node.kind === KIND_CJ_LETTER && !lastNode.hasTrailingPunctuation || lastNode.kind === KIND_CJ_LETTER && node.kind === KIND_NON_CJK && !node.hasLeadingPunctuation) {
nodes.push({
type: "whitespace",
value: " "
});
} else if (!isBetween(KIND_NON_CJK, KIND_CJK_PUNCTUATION) && // disallow leading/trailing full-width whitespace
![lastNode.value, node.value].some(function (value) {
return /\u3000/.test(value);
})) {
nodes.push({
type: "whitespace",
value: ""
});
}
}
38518行目
value: " "
となっているのを
value: ""
とします。
もちろん中国語も巻き添えです。
textlintで対処する方法
根本的な解決ではありませんが、textlintで対処するのも良いです。
textlintについては、以下の記事に情報がまとまってます。
Qiitaやはてブロに投稿するようなユーザーはみんなtextlintを使うと捗るぞ!
私はtextlintのpreset-ja-spacingを有効にして、半角文字と全角文字の間にスペースを入れたら警告を出すようにしています。
prettier-plugin-md-nocjspを利用する
作者の@tats-uさんよりコメントで紹介頂いた、prettier-plugin-md-nocjsp
を利用する方法です。
もっとも手軽でスマートなので、こちらを利用することを推奨します。
プラグインの詳細については以下の作者様の記事を一読頂ければと思います。
和欧文字間(漢字仮名と英数字の間)に半角スペースが挿入されないようにするPrettier Markdownプラグインを作った
導入方法についてはプラグインのgithubに丁寧に書かれています。
https://github.com/tats-u/prettier-plugin-md-nocjsp#readme
注意点として
PrettierのVSCode拡張機能にバンドルされているPrettierではPrettierプラグインが利用できません。
Prettierを別途グローバル or ローカルにインストールする必要があります。
推奨はローカルインストールです。
ローカルインストール(推奨)の場合
カレントディレクトリをプロジェクトルートに移動します
以下をコマンド実行し、prettier-plugin-md-nocjsp
をインストールします。
npm install --save-dev prettier-plugin-md-nocjsp
npm install prettier -D --save-exact
次に .prettierrc
をプロジェクトルートに追加します。
# *snip*
overrides:
- files:
- "*.md"
- README
options:
parser: markdown-nocjsp
- files:
- "*.mdx"
options:
parser: mdx-nocjsp
グローバルインストールの場合
以下をコマンド実行し、prettier-plugin-md-nocjsp
をインストールします。
npm install -g prettier-plugin-md-nocjsp
npm install -g prettier
さらにprettier拡張の設定で prettier.resolveGlobalModules
を true
にします。
prettier.resolveGlobalModules
が true
だと動かなくなりました(2022.02.13)
true
になっている場合 false
にしてください。
次に .prettierrc
をユーザーディレクトリ(C:\Users\ユーザー名)に追加します。
# *snip*
overrides:
- files:
- "*.md"
- README
options:
parser: markdown-nocjsp
plugins:
- "./AppData/Roaming/npm/node_modules/prettier-plugin-md-nocjsp"
- files:
- "*.mdx"
options:
parser: mdx-nocjsp
plugins:
- "./AppData/Roaming/npm/node_modules/prettier-plugin-md-nocjsp"
こちらは @u3xbf8i9 さんのコメントが参考になりました。ありがとうございます。
注意
Prettier - Code formatter、Prettierのバージョンアップでこの内容が通用しなくなることがあります。
ご了承ください。
最後に
無理やり修正していますが、プルリクやissueを上げた方が建設的だと思います。
でも、英語無理!
追記(2019.03.08)
issueにあがってました、ありがたい。
https://github.com/prettier/prettier/issues/5938
さらに追記(2020.02.14)
https://github.com/prettier/prettier/issues/6385
オプションで切り替える案が出されてました。
日本語と中国語が切り離せない。
中国語ではスペースを入れるのが一般的派と、中国語でも入れないよ派など
意見が割れているようです。
Prettier自体にあまりオプションを入れたくないともあります。
解決はすぐには難しそうですね。
参考
https://github.com/ikatyang/cjk-regex/issues/48
https://github.com/prettier/prettier/issues/5028
https://github.com/prettier/prettier/pull/5040/commits/da6186995df3ba1f8bdeb126d794fb32c404bcdb
https://qiita.com/kumapo0313/items/92d1597da5f3752f6584#comment-e328de87992dbb82c9a1