WordPressの目次をプラグイン無しで自動生成する【コピペOK】
「WordPressサイトに目次の自動生成を導入したいけど、プラグインは増やしたくない」「使っているプラグインに不具合や望ましくない挙動がある」などとお考えの方に向けて、プラグイン無しでの実装方法を解説します。
コードはコピペOKなので、ご活用ください。
WordPressの目次をプラグイン無しで自動生成する
本コラムで解説する目次の自動生成の仕様は下記の通りです。
- ページ内の
h2
,h3
を取得して目次に含める - 「ページ内の
h2
の数がいくつ以下の場合は目次を生成しない」という設定ができる - アンカーポイントとして、IDを持つ
span
を目的地のh要素の中に挿入する - 生成された目次はページ内の最初の
h2
の上に挿入される - サーバーサイドで目次を生成する
以下で、具体的なPHPのコードを提示した上でその使い方を解説します。
PHP
function generate_table_of_contents($headings) {
$table_of_contents = '<div class="toc__container"><p class="toc__title">目次</p><ol class="toc__list">';
$current_h2_item = '';
$has_h3 = false;
foreach ($headings as $heading) {
if ($heading['tag'] == 'h2') {
if ($current_h2_item !== '') {
if ($has_h3) {
$table_of_contents .= '</ol>';
}
$table_of_contents .= '</li>';
}
$current_h2_item = '<li class="toc__item toc__item--h2"><a href="#' . $heading['id'] . '" class="toc__link">' . $heading['text'] . '</a>';
$has_h3 = false;
$table_of_contents .= $current_h2_item;
} else {
if (!$has_h3) {
$table_of_contents .= '<ol class="toc__sublist">';
$has_h3 = true;
}
$table_of_contents .= '<li class="toc__item toc__item--h3"><a href="#' . $heading['id'] . '" class="toc__link">' . $heading['text'] . '</a></li>';
}
}
if ($current_h2_item !== '') {
if ($has_h3) {
$table_of_contents .= '</ol>';
}
$table_of_contents .= '</li>';
}
$table_of_contents .= '</ol></div>';
return $table_of_contents;
}
function insert_table_of_contents($content) {
if (is_single()) {
$heading_pattern = '/<(h2|h3)(.*?)>(.*?)<\/(h2|h3)>/is';
$matches = array();
$heading_count = preg_match_all($heading_pattern, $content, $matches, PREG_SET_ORDER);
if ($heading_count >= 2) {
$headings = array();
$heading_counter = 0;
foreach ($matches as $match) {
$headings[] = array(
'tag' => $match[1],
'attributes' => $match[2],
'text' => $match[3],
'id' => 'heading-' . $heading_counter
);
$heading_counter++;
}
$content = preg_replace_callback($heading_pattern, function ($match) use ($headings) {
static $index = 0;
$id = $headings[$index]['id'];
$index++;
return sprintf('<%1$s%2$s><span id="%3$s">%4$s</span></%1$s>', $match[1], $match[2], $id, $match[3]);
}, $content);
$table_of_contents = generate_table_of_contents($headings);
$first_h2_position = strpos($content, '<h2>');
if ($first_h2_position !== false) {
$content = substr_replace($content, $table_of_contents, $first_h2_position, 0);
}
}
}
return $content;
}
add_filter('the_content', 'insert_table_of_contents');
コードの使い方
上述のPHPはWordPressのテーマフォルダ内にあるfunctions.php
に記載してください。
また、38行目と43行目は記述を差し替えることで設定を変更できますので、以下でそれぞれ解説します。
38行目:if (is_single())
目次生成を有効化するページのタイプを指定する箇所で、上述のコードではsingle
(投稿ページ)を記載しています。
例えば特定のカスタム投稿タイプを指定したい場合は、if ( is_singular('投稿タイプ名') )
と書き換えてください。
また、URLを基準に条件を指定したい場合は、例えば/blog/
であれば下記のように記述できます。
$url = $_SERVER['REQUEST_URI'];
if(strpos($url,'/blog/')!== false) {...}
43行目:if ($heading_count >= 2)
ページ内にいくつ以上のh2
があれば目次を生成するかを指定しています。
仮に一つしか無いのであれば目次を配置する必要性が無いので、上述のコードでは2以上(>= 2
)で設定しています。
2
の部分を他の数値に差し替えることで、任意の最小数を設定可能です。