WordPressの目次を自動生成する定番プラグインTable of Contents Plus(TOC+)ですが、サイドバーウィジェットで使った際に不具合が発生しました。その原因と対策をご説明します。
検証で使ったバージョンは以下ですが、多少ずれてもそんなに変わらないはずなので参考にしてみてください。
| バージョン | |
|---|---|
| WordPress | 6.8.3 |
| TOC+ | 2411.1 |
もくじ
サイドバーの目次のある項目をクリックしても無反応
サイドバーの目次のある項目をクリックしても、正しい場所に飛ばず無反応。そして、それより下の項目をクリックすると、一つずれた場所に飛んでしまう、という事象が発生しました。
本文中に表示された目次は正常に機能しました。
サイドバーの目次のaタグを見てみました。
|
1 |
<a href="#8230">見出しの内容です…</a> |
実際の見出しの方は、
|
1 |
<h2><span id="i">見出しの内容です...</span></h2> |
となっており、リンクが #8230 と、 i が合っていないのです。さらに、サイドバーの見出し内容の最後に見慣れない記号と数字が並んできます。
そして、サイドバーの当該項目の次のaタグは
|
1 |
<a href="#i">見出し2の内容です</a> |
となっており、先ほどの見出しにリンクされているのです。一個ずつずれていました。
ピリオド3つが三点リーダーに自動変換されているのが原因
見出しは、
「見出しの内容です...」
これの最後はピリオドが3つです。
サイドバーの目次の項目の表示は
「見出しの内容です…」
と最後が三点リーダーの記号に変換されていました。これをHTMLで見ると先ほどの
|
1 |
<a href="#8230">見出しの内容です…</a> |
となるっているのです。 … という文字列は、三点リーダーのHTML文字参照というものらしいです。
TOC+の仕様は、リンクの文字列として、日本語のような全角文字は使わず、半角英数の記号しか使わないので、 #8230 が使われたということです。
プラグインでwptexturizeをオフにしてたのが真の原因
なんで、サイドバーだけ変換されてしまうか調べてみました。class-toc-widget.phpというファイルの38行目で、
|
38 |
$items = $toc_plus->extract_headings( $find, $replace, wptexturize( do_shortcode( $post->post_content ) ) ); |
wptexturize() というコマンドで変換されていました。
本文の方の見出しを生成する部分はどうなっているかを見てみました。class-toc-plus.phpというファイルの1632行目が該当しますが、
|
1632 |
$items = $this->extract_headings( $find, $replace, $content ); |
wptexturize() は実行されていません。
本文側のロジックとサイドバー側のロジックが違うというのはバグなのではないかと最初は思いました。
しかし、よく考えたら、 wptexturize() には見覚えがありました。
実はあるオリジナルのプラグインで、これを以下のようにオフにしていたのです。
|
1 |
remove_filter('the_content', 'wptexturize'); |
つまり、WordPressのデフォルトとして、 wptexturize() は実行されるようになっているので、オフにしているのです。
TOC+でも wptexturize() が実行されるのを前提にしてあるので、本文側のロジックには無かったのでしょう。サイドバー側は、DBからデータを取得して生成するので、デフォルトでは行われないので、ロジックの中に wptexturize() があると思われます。
実際、上の wptexturize() をオフにしている部分をコメントアウトしたら、このような事象は無くなりました。
とりあえず三点リーダーを使わないという対応
まぁ、オリジナルのプラグインで wptexturize() をオフにしないというのが正攻法な対応策です。
ただ、理由があって wptexturize() をオフにしているので、簡単には変えられません。
なので、とりあえずは、三点リーダーを使わないという方法でしのぎます。
さいごに
問題の原因がわかってよかったです。しかし、おそらく三点リーダー以外にも変換されておかしくなってしまうケースも出てくる可能性があります。
なので、今後根本的な対応をする必要が出るでしょう。
そもそも、本文の目次とサイドバーの目次を別々に生成しているという仕様をなんとかして欲しいなと思います。