はてなブログにおけるはてな記法の展開バグあれこれ

はてなブログにおけるはてな記法の解釈にはバグが多い。こちらでつかんでいるものは以下で、すべて運営に報告済みであるが、ここでいったんまとめておこうと思う。

定義リスト記法のdt要素にURLなどがあるとその中のコロンからdd要素になる

定義リスト記法は行頭に「:」を書き、続く文字列と「:」を書く。「:A:B」のように書くと、Aがdl(定義リスト)要素のdt要素、Bがdd要素になる。

:A(定義リストの見出し、dt要素):B(定義リストの内容、dd要素)

↑こう書くとこうなる↓

<dl>
<dt>A(定義リストの見出し、dt要素)</dt>
<dd>B(定義リストの内容、dd要素)</dd>
</dl>

表示結果は以下。

A(定義リストの見出し、dt要素)
B(定義リストの内容、dd要素)

この定義リスト記法において、「A」の範囲にURLやid記法(例:id:Imamura)など「:」を含む文字列があると、そこでdt要素が終わったものと勘違いされてしまうことがある。

たとえば「:https://www.hatena.ne.jp/:はてな」と書いたとする。期待されるHTMLは以下である。

<dl>
<dt>https://www.hatena.ne.jp/</dt>
<dd>はてな</dd>
</dl>

はてなダイアリーではこの通りのHTMLが出力され、以下のようになっていた。

https://www.hatena.ne.jp/
はてな

しかし、今のはてなブログではこういうHTMLが生成される。

<dl>
<dt>https</dt>
<dd>//www.hatena.ne.jp/:はてな</dd>
</dl>

表示結果はこうなっちゃう。

https
//www.hatena.ne.jp/:はてな

この書き方に限ってはURLを「[~]」で囲む「http記法」にすると解消するのだが、http記法の前に文字列があるとちゃんと解釈されない。

現状うまく解釈されない書き方

:はてな<a href="http://www.hatena.ne.jp/">はてな</a>:はてなです
:http://www.hatena.ne.jp/:はてなです
:はてな[http://www.hatena.ne.jp/:title=はてな]:はてなです
:はてな[http://www.hatena.ne.jp/:bookmark]:はてなです
:はてな[http://www.hatena.ne.jp/:title=はてな:bookmark]:はてなです
:はてな[http://www.hatena.ne.jp/]:はてなです
:はてな [http://www.hatena.ne.jp/]:はてなです
:はてなブログ[id:hatenablog:detail]:はてなブログです

表示結果はこう。

はてな
//www.hatena.ne.jp/">はてな:はてなです
http
//www.hatena.ne.jp/:はてなです
はてな[http
//www.hatena.ne.jp/:title=はてな]:はてなです
はてな[http
//www.hatena.ne.jp/:bookmark]:はてなです
はてな[http
//www.hatena.ne.jp/:title=はてな:bookmark]:はてなです
はてな[http
//www.hatena.ne.jp/]:はてなです
はてな [http
//www.hatena.ne.jp/]:はてなです
はてなブログ[id
hatenablog:detail]:はてなブログです

記事掲載時点ではこういうHTMLが生成されている。(はてなブログ タグ(はてなキーワード)へのリンクは省略)

<dl>
<dt>はてな</dt>
<dd>//www.hatena.ne.jp/">はてな</a>:はてなです</dd>
<dt>http</dt>
<dd>//www.hatena.ne.jp/:はてなです</dd>
<dt>はてな[http</dt>
<dd>//www.hatena.ne.jp/:title=はてな]:はてなです</dd>
<dt>はてな[http</dt>
<dd>//www.hatena.ne.jp/:bookmark]:はてなです</dd>
<dt>はてな[http</dt>
<dd>//www.hatena.ne.jp/:title=はてな:bookmark]:はてなです</dd>
<dt>はてな[http</dt>
<dd>//www.hatena.ne.jp/]:はてなです</dd>
<dt>はてな [http</dt>
<dd>//www.hatena.ne.jp/]:はてなです</dd>
<dt>はてなブログ[id</dt>
<dd>hatenablog:detail]:はてなブログです</dd>
</dl>

正しく解釈される書き方

:<a href="http://www.hatena.ne.jp/">はてな</a>:はてなです
:[http://www.hatena.ne.jp/:title=はてな]:はてなです
:[http://www.hatena.ne.jp/:title=はてな]はてな:はてなです
:[http://www.hatena.ne.jp/:title=はてな] はてな:はてなです
:[http://www.hatena.ne.jp/:title=はてな:bookmark]:はてなです
:[http://www.hatena.ne.jp/:title=はてな:bookmark]はてな:はてなです
:[http://www.hatena.ne.jp/]:はてなです
:[http://www.hatena.ne.jp/:bookmark]:はてなです
:[id:hatenablog:detail]:はてなブログです
:[id:hatenablog:detail]はてなブログ:はてなブログです

表示結果はこう。

はてな
はてなです
はてな
はてなです
はてなはてな
はてなです
はてな はてな
はてなです
はてな
はてなです
はてなはてな
はてなです
http://www.hatena.ne.jp/
はてなです
はてなです
id:hatenablog
はてなブログです
id:hatenablogはてなブログ
はてなブログです

生成されるHTMLは以下。ちゃんとしている。

<dl>
<dt><a href="http://www.hatena.ne.jp/">はてな</a></dt>
<dd>はてなです</dd>
<dt><a href="http://www.hatena.ne.jp/">&#x306F;&#x3066;&#x306A;</a></dt>
<dd>はてなです</dd>
<dt><a href="http://www.hatena.ne.jp/">&#x306F;&#x3066;&#x306A;</a>はてな</dt>
<dd>はてなです</dd>
<dt><a href="http://www.hatena.ne.jp/">&#x306F;&#x3066;&#x306A;</a> はてな</dt>
<dd>はてなです</dd>
<dt><a href="http://www.hatena.ne.jp/">&#x306F;&#x3066;&#x306A;</a><a href="https://b.hatena.ne.jp/entry/http://www.hatena.ne.jp/" class="http-bookmark"><img src="https://b.hatena.ne.jp/entry/image/http://www.hatena.ne.jp/" alt="" class="http-bookmark" /></a></dt>
<dd>はてなです</dd>
<dt><a href="http://www.hatena.ne.jp/">&#x306F;&#x3066;&#x306A;</a><a href="https://b.hatena.ne.jp/entry/http://www.hatena.ne.jp/" class="http-bookmark"><img src="https://b.hatena.ne.jp/entry/image/http://www.hatena.ne.jp/" alt="" class="http-bookmark" /></a>はてな</dt>
<dd>はてなです</dd>
<dt><a href="http://www.hatena.ne.jp/">http://www.hatena.ne.jp/</a></dt>
<dd>はてなです</dd>
<dt><a href="https://b.hatena.ne.jp/entry/http://www.hatena.ne.jp/" class="http-bookmark"><img src="https://b.hatena.ne.jp/entry/image/http://www.hatena.ne.jp/" alt="" class="http-bookmark" /></a></dt>
<dd>はてなです</dd>
<dt><a href="http://blog.hatena.ne.jp/hatenablog/" class="hatena-id-icon"><img src="https://cdn.profile-image.st-hatena.com/users/hatenablog/profile.png" width="16" height="16" alt="" class="hatena-id-icon">id:hatenablog</a></dt>
<dd>はてなブログです</dd>
<dt><a href="http://blog.hatena.ne.jp/hatenablog/" class="hatena-id-icon"><img src="https://cdn.profile-image.st-hatena.com/users/hatenablog/profile.png" width="16" height="16" alt="" class="hatena-id-icon">id:hatenablog</a>はてなブログ</dt>
<dd>はてなブログです</dd>
</dl>

http記法の行内にコメント(<!--~-->)があると記法として認識されない

[http://www.hatena.ne.jp/:title=はてな]<!--コメント-->

↑こう書くと、こうなってほしい↓

<a href="http://www.hatena.ne.jp/">はてな</a>

しかしこういうHTMLが生成されてしまう。(はてなブログ タグ(はてなキーワード)へのリンクは省略)

[http://www.hatena.ne.jp/:title=はてな]

はてなブログ タグ(はてなキーワード)を「[[」~「]]」で囲むとタグ(キーワード)へのリンクの見栄えにならない

たとえばこう書く。

はてなブログ

[[はてなブログ]]

記事掲載時点で、下のようなHTMLが生成される。(改行を追加しています)

<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%D6%A5%ED%A5%B0">はてなブログ</a></p>
<p><a href="http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%D6%A5%ED%A5%B0">はてなブログ</a></p>

タグ(キーワード)へのリンクに「class="keyword"」をつけてくれないので、「はてなブログ」のような普通のリンクの見栄えになってしまう。

対策としては、以下のようなCSSを「設定」-「デザイン」-「デザインCSS」に追加するとよい。

.entry-content a[href*="d.hatena.ne.jp/keyword"]{
    color: inherit!important; /*タグ(キーワード)へのリンクの文字色を地の文と同じにする*/
    border-bottom: 1px solid #dedede; /*キーワードリンクの見た目をカスタマイズしているならそれに合わせる*/
}

これは「<a href="http://d.hatena.ne.jp/keyword/~">~</a>」というHTMLを見つけて、キーワードと同じ見た目にするというCSSである。でもそういうバッドノウハウがいらなくなってほしい。

はてなブログ タグについては以下で書いた。


http記法や引用記法の「:title=」に「[」や「]」を使えない

[http://www.hatena.ne.jp/:title=[hatena]はてな]

↑こう書いたら、こうなってほしい↓

<a href="http://www.hatena.ne.jp/">[hatena]はてな</a>

しかしこうなってしまう。

[http://www.hatena.ne.jp/:title=[hatena]はてな]

記事掲載時点で、このようなHTMLが生成される。

[<a href="http://www.hatena.ne.jp/:title=">http://www.hatena.ne.jp/:title=</a>[hatena];はてな]

「[」は「&91;」、「]」は「&93;」に置き換えればよい。

[http://www.hatena.ne.jp/:title=&#91;hatena&#93;はてな]

これで以下のようになる。

[hatena]はてな

しかし、そうしなくてもうまいこと処理してほしい。

「[」~「]」で囲まないダイアリー記法がid記法として解釈されることがある

ダイアリー記法ははてなダイアリーの記事へのリンクを生成する記法で、「d:id:Imamura:20030217:p1」のように書く。これが「d:id:Imamura:20030217:p1」ではなく「d:id:Imamura:20030217:p1」となってしまうことがある。「id:Imamura」はidへリンクする「id記法」である。

「[」~「]」で囲んで「[d:id:Imamura:20030217:p1]」と書くと問題は起きない。でも「[」~「]」で囲まなくてもちゃんとダイアリー記法として解釈されることもあり、条件がわからなくてモヤモヤする。

今まで多くのケースを見てきて、idにアンダーバーを含むときと、日付の次が「:」ではなく「#」のときが怪しいのだが確証が持てない。

まったく同じダイアリー記法を書いていても展開結果が異なる例も見つかった。

f:id:Imamura:20191004112054p:plain

これは http://ima.hatenablog.jp/entry/20060310/umigame3 のキャプチャである(今は「[」~「]」で囲んで修正済み)。一度書かれたダイアリー記法をくり返すとid記法として解釈されるのだろうか? 謎である。

「拡張id記法」を解釈してほしい

これは不具合ではなく仕様であるが、いい機会なので要望させてほしい。

はてなダイアリーにダイアリー記法が実装される以前、「d:id:Imamura:20030217:p1」に相当するリンク記法は「id:Imamura:20030217:p1」というid記法が担っていた。これははてなダイアリー(とはてなグループ)だけで使える独自の「拡張id記法」ともいうべき書き方で、id記法は本来「id:Imamura」という書き方しか解釈しない。

「歴史的な経緯で、はてなダイアリー(やはてなグループ)では『id:Imamura:20030217:p1』という書き方もダイアリー記法として解釈されていた」ということだ。

はてなブログはこの「拡張id記法」をサポートしていないので、「id:Imamura:20030217:p1」と書いても「id:Imamura:20030217:p1」にならず、「id:Imamura:20030217:p1」となってしまう。

これは仕様としては正しい。しかしはてなダイアリーからインポートした記事でこうなっていると、本来想定されたURLへのリンクにならない。つまり大量のリンク切れが発生しているのと変わらない。

この下に紹介した記事の通りにすれば、「拡張id記法」で書かれた記事をダイアリー記法へ一括置換することはできる。一方で物故者のダイアリーなど、はてなブログへ自動移行したものの修正を期待できないものもある。そういった記事でも目的の記事へきちんとリンクするよう、「id:Imamura:20030217:p1」や「id:Imamura:20030217#p1」といった書き方を「[d:id:Imamura:20030217:p1]」と書いたものとして扱うようにしてほしい。

(あるいは拡張id記法をダイアリー記法として扱うGreasemonkeyを書いて、自分が閲覧するときに限ってちゃんとしたリンクになるようにするとか…また勉強しないと)

はてなダイアリーには15年にわたる膨大な記事の蓄積があった。それをはてなブログへインポートできるようにして資産を生かすことにしたのははてなの判断である。であれば、はてなブログは仕様が違うのだからと切り捨てるのではなく、責任を持ってきちんとリンクするようにしてほしい。「10年後もユーザーの皆さんとともにあるサービスを目指す」(2019年“マイ推し記事”7選! はてなブログ編集部スタッフの心に残ったのはこれだ - 週刊はてなブログ)とはそういうことではないだろうか。

はてなブログライターで一括置換できます

ここまで紹介したはてな記法は決して特殊な書き方ではなく、はてなダイアリーではきちんと解釈してくれていた。はてなダイアリーからはてなブログへインポートした記事で、意図しない表示結果になっていることが多い。

すでにはてなブログへ投稿した記事やはてなダイアリーからインポートした記事を1つのテキストファイルにまとめ、テキストエディタで一括置換して登録し直すことができる。方法は以下で解説しています。


冒頭にも書いたように、これらの不具合はすべて運営へ報告済みである。しかし概して反応は鈍い。また「修正しました」と連絡があっても修正もれがあったりする。この記事が参考になるかはわからないが、ぜひきちんと修正してほしい。