同じ文書でパーサーごとに結果が食い違う理由
Markdown は 2004 年に、Perl スクリプト 1 本と 1 ページの解説文として公開されました。形式文法はありません。この緩さこそ普及した理由であり、同時に同じ文書がツールごとに違って描画される理由でもあります。原典の実装は数十もの挙動を未定義のまま残しました。3 スペース字下げしたリストマーカーはどう扱うのか、単語内にネストした強調はどう解釈するのか、見出しの前に空行は必要か。実装者はそれぞれ推測で穴を埋め、そしてその推測は食い違いました。
CommonMark はこの溝を埋めるために存在します。原典が曖昧に残した場面をまさに対象とする数百件の適合性テストを備えた、厳密な仕様です。本コンバーターは CommonMark のテストスイートを完全に通過する markdown-it を使っているため、出力は GitHub、Reddit、Discourse をはじめ現代的なツールの大半と一致します。ここで正しく描画される文書は、それらの場所でも同じように描画されます。
GitHub Flavored Markdown はその上に重ねられた上位集合で、表・打ち消し線・タスクリスト・URL 自動リンクを加えます。本ツールは表とタスクリストに対応しており、サンプル文書にも両方を含めてあります。この区別は、自分が制御できない相手向けに書くときに効いてきます。表は CommonMark 本体の一部ではなく、厳格なパーサーはそれをただの平文として素通しするからです。
4 つのスイッチが実際に変えるもの
自動リンクは裸の URL をアンカーに変えます。変更履歴やメモには便利ですが、裸のリンクを山括弧で囲むことを求める CommonMark からは逸脱します。厳格なパーサーへ持ち込む必要があるなら切ってください。
スマート約物は直線引用符を曲線引用符に、-- を en ダッシュに書き換えます。散文には正しく、コードブロック外にあるコード片には誤りです。コマンドラインのフラグを平然と壊します。インラインコードとフェンス付きブロックは常に対象外です。
強制改行は単一改行の意味を変えます。既定の Markdown は連続行を 1 つの段落に連結します。これは大半の文書が前提とする挙動です。しかし改行のたびに Enter を押すチャット風の入力では、これを有効にしないと整形が崩壊します。
生 HTML の通過だけはセキュリティに直結します。無効なら、原文中の <img onerror=...> はエスケープされ文字として表示されます。有効なら、生きたマークアップとして出力されます。ユーザー投稿を扱うなら無効のままにしてください。
サニタイズは別の仕事
Markdown パイプラインで最もありがちな誤解は、コンバーターが守ってくれるという思い込みです。守りませんし、守る役割でもありません。生 HTML を無効にしていても、リンク先は依然として攻撃者の制御下にあり、[click](javascript:alert(1)) はブラウザーが実行しうるアンカーを生成します。Markdown の構文だけで実用的な攻撃が組み立てられるのです。
正しい手順は、変換 → サニタイズ → 挿入です。DOMPurify のような専用サニタイザーにタグと属性の許可リストを設定して HTML を通し、そのうえでページに入れてください。著者以外に見せる内容なら、この処理はサーバー側で行う必要があります。クライアント側のサニタイズは、API を直接叩ける相手には迂回されるからです。本ツールは自分の入力を自分のブラウザーで描画しているだけで、他人の Markdown を公開する場合とは脅威モデルが異なります。