IT・個人事業

Markdownで日本語ブログを書くと踏む2つの罠|太字が閉じない、補足ボックスの中のリンクが効かない

公開:

※ 本記事にはアフィリエイト広告(Amazonアソシエイト・楽天アフィリエイト等)が含まれています。

WordPressからAstroの静的サイトに移行して、記事はMarkdownで書くようになりました。軽くて書きやすくて気に入っているのですが、移行後にスマホで自分の記事を読み直していたら、妙なものが目に入りました。

太字にしたはずの箇所に、アスタリスクが2つ、そのまま表示されている。別の記事では、補足ボックスの中のリンクが、青くもならず、タップもできず、[テキスト](URL) という生の文字のまま。

どちらもWordPress時代にはなかった症状です。調べたら、原因は2つともMarkdownの仕様そのもので、しかも日本語で書く人だけがきれいに踏む罠でした。

罠1:日本語の文中で太字が閉じない

まず再現例です。同じ ** の使い方なのに、結果が変わります。

これは**まとめ**です。        → 太字になる
これは**「まとめ」**です。    → ならない(** がそのまま出る)
結論は**「成功」**だった      → ならない
**「まとめ」**。先頭なら       → なる

太字にしたい部分がカギ括弧で始まったり終わったりすると、その直前直後に日本語の文字があるときだけ失敗します。

原因はCommonMark(Markdownの標準仕様)の「flanking」という規則です。Markdownは ** を見たとき、それが「開き」なのか「閉じ」なのかを、前後の文字を見て判断します。英語なら簡単で、** の前がスペースなら開き、後ろがスペースなら閉じです。

ところが日本語にはスペースがありません。これは**「まとめ」**です の最初の ** は、前が「は」という普通の文字で、後ろが「「」という約物(記号)です。仕様上、「前が文字で、後ろが記号」の ** は、開きとも閉じとも認められません。だから処理されず、そのまま表示されます。閉じ側の 」**で も同じ理屈で、「前が記号で、後ろが文字」なので閉じになれません。

行頭に置けば前がスペース扱いなので動く。括弧を使わなければ前後が文字どうしなので動く。でも「文の途中で、括弧つきの語を太字にする」という、日本語ではごく普通の書き方だけが、仕様の隙間に落ちます。

対処:太字はHTMLで書く

直し方は、** をやめて <strong> タグで書くことにしました。

これは<strong>「まとめ」</strong>です。    → 太字になる

MarkdownはHTMLをそのまま通すので、これなら前後の文字が何であれ確実です。「場合によって動かない記法」を使い続けるより、「常に動く記法」に揃えるほうが、書くときに迷いません。このブログでは、以後すべての記事で太字は <strong> と決めました。

過去記事の一括置換は、スクリプトで行いました。ひとつ注意したのが、コードブロックの中は触らないこと。Pythonの記事には **kwargs や 2**3 のような、太字とは無関係のアスタリスクが出てきます。先にコードブロックとインラインコードを退避してから置換し、あとで戻す手順にして、コードを壊さずに済みました。

罠2:補足ボックスの中でMarkdownが効かない

このブログでは、補足を <div class="note"> で囲んで表示しています。その中にMarkdownでリンクを書いたら、こうなりました。

<div class="note">
詳しくは [移行の記事](/blog/wordpress-kara-astro-seiteki-site-ikou/) を見てください
</div>

結果は、リンクにならず [移行の記事](/blog/...) という文字がそのまま表示されます。

これもCommonMarkの仕様で、「HTMLブロック」の扱いです。行頭が <div で始まると、そこから次の空行までは丸ごとHTMLとして扱われ、中身のMarkdownは一切解釈されません。リンクも、太字も、リストも、全部ただの文字になります。

対処は2つある

ひとつは、divの中では最初からHTMLで書くこと。リンクは <a href="...">テキスト</a>、太字は <strong>。

もうひとつは、divの開始タグと終了タグのあとに空行を入れること。空行でHTMLブロックが終わるので、その後の行は普通のMarkdownとして解釈されます。

<div class="note">

詳しくは [移行の記事](/blog/...) を見てください

</div>

このブログでは前者を選びました。空行の有無で挙動が変わる書き方は、忘れたときに静かに壊れます。「divの中はHTML」と決めてしまえば、ルールが一つで済みます。

Lighthouseは、この手の壊れを教えてくれない

2つの罠に共通しているのは、ツールの点数には一切出ないことです。** が文字として表示されていても、リンクがただの文字でも、HTMLとしては正しい。Lighthouseは4カテゴリ満点のまま、読者だけが不便をしていました。

見つけたのは、スマホで自分のブログを読者として読み直したときです。ダークモードのコントラストで96点に落ちた話にも書きましたが、点数を守ることと、読める記事を出すことは、別の作業でした。

Markdownは英語圏で生まれた仕様で、スペースで単語を区切る前提が、ところどころに埋まっています。日本語で書く人は、その前提から外れたところで、こういう小さな罠を踏みます。同じ症状に気づいた方の参考になれば幸いです。