CommonMark の強調の分かち書きヤバすぎ~

このサイトをビルドするスクリプト群を CommonJS (CJS) 形式から ESModule (ESM) 形式に対応させた。また、使用している npm パッケージ群のバージョンも全て最新版にアップした。

…ということは、Pedantic モードに対応していた remark-parse とオサラバし、CommonMark 準拠な Markdown に書き換える必要があるということだ。

このサイトのブログ記事は4,400記事を超えているらしい。それらの記事中に出てくるアンダースコアをひたすらアスタリスクに変換した。強調以外の理由で使っているアンダースコアも当然あるので、機械的な一括置換ではダメで、かなり手作業を交えて頑張った。

全てアスタリスクにしたら上手く CommonMark でも強調されるだろうと思ったら、ちょくちょく強調されずにアスタリスクがそのまま表示されている場所がある。何だコレ?そう思って調べたら、以下の記事が見つかった。

なんと、アスタリスクを使う場合でも、約物とアスタリスクが隣接していると強調されないパターンがあるというのだ。以下にいくつか例を並べておくので、commonmark.js demo で動作確認してみて欲しい。

- この*場合は*、強調される
- この*場合は、*強調されない
- この*場合は*。強調される
- この*場合は。*強調されない
- これは「*強調*」される
- これは*「強調」*されない
- これは『*強調*』される
- これは*『強調』*されない
- これ*は?* 強調される
- これ*は?*強調されない

- この**場合は**、強調される
- この**場合は、**強調されない
- この**場合は**。強調される
- この**場合は。**強調されない
- これは「**強調**」される
- これは**「強調」**されない
- これは『**強調**』される
- これは**『強調』**されない
- これ**は?** 強調される
- これ**は?**強調されない

アスタリスクはスペースを開けて分かち書きせずとも強調されるのがデフォだと思っていたが、句読点やカギカッコを内包する形でアスタリスクと隣接している場合は強調されないという挙動をするようだ。謎なことに、コレが CommonMark の仕様として確定しているのである。まさか文字コードまで見て約物をわざわざ判定しているとは…。

厄介なのが、VSCode のプレビューは CommonMark の仕様どおりに強調構文を解釈するのに、入力しているウィンドウのシンタックスハイライトは微妙に緩く強調してくれてしまうので、入力画面のハイライトを見て強調が上手くできているつもりになっていても、実際は強調されていない、というケースも起こりそうだ。

「この仕様、日本語では使いづらいんだが?仕様変えない?」という話は CommonMark のフォーラムにも挙がっているが、6年経った現在も変更の予定はなく、「元々の Markdown の仕様と CommonMark との互換性を守るために、わざわざ CJK 対応はしないだろう」とされている。

元々英語話者が作った軽量マークアップ言語だし、日本語だけではなく中国語や韓国語などではまた違った文字入力の文化があるので、英語のようにスペースで区切った分かち書きが前提とされた仕様をおいそれとは変えられないようだ。

うーん、だとすると、Pedantic モードをもっと広めて欲しいな…。少なくとも Remark や Unified.js の中で日本語や CJK 文化圏向けのパーサが欲しい。remark-parse の後に remark-pedantic みたいなプラグインを噛ませることで、Pedantic な強調構文も解釈してくれるようにはできんかのう。

実はちょっとだけそれっぽい Remark プラグインを作りかけたんだけど、Remark の中の mdast や micromark の仕様がよく分からなくて断念している。GFM の中の打ち消し線 ~ による <del> のコードを参考にして若干の Pedantic さを手に入れられたが、求めるところまで緩くはできていない。コチラはもうコレ以上頑張る気はない…。

とりあえず、このサイトのスクリプトに関しては全部 CommonMark 準拠に変えたし、CJS → ESM 対応もして Node.js v18 以降を要求するように更新できたから、しばらく延命できるだろう。やっぱり過去のブログ記事は Markdown をソースにしないで、HTML 化した版を持っておいた方が良い気がしてきたなー。