ワードプレスの投稿に目次を付ける(開発者向け)|wordpress
ワードプレスに目次を付けるには優秀なプラグインがいくつかあります。
これらは本当に優秀で簡単に記事に目次を付けれます。しかも基本的にノーコードでいれれます。
しかし、独自テーマの開発などでは少し使いづらいと感じるところも…
というわけで開発者向けにオリジナルの目次を追加する方法を伝授いたしましょう。
記事のhタグにIDを付与
まずは、記事内のhタグにアンカーリンクを作るためのIDを付与します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function add_heso_ids($content) { if (!is_singular('post')) { return $content; } $counter = 1; return preg_replace_callback( '/<h([2-3])([^>]*)>(.*?)<\/h\1>/', function($matches) use (&$counter) { $id = 'post-target' . $counter++; return '<h' . $matches[1] . $matches[2] . ' id="' . esc_attr($id) . '">' . $matches[3] . '</h' . $matches[1] . '>'; }, $content ); } add_filter('the_content', 'add_heso_ids'); |
上記コードでは正規表現でh2とh3タグを検索し、IDを付与しています。
このコードをfunctions.phpにでも記載しておきましょう。
hタグの範囲を変更したい場合は8行目の「’/<h([2-3])([^>]*)>(.*?)<\/h\1>/’,」を「’/<h([2-4])([^>]*)>(.*?)<\/h\1>/’,」の様に修正してください。
また、2-4行目でpostに限定してますのでカスタム投稿タイプに適応したい場合は適宜修正をいれましょう。
目次を生成するコードを記述
次は目次を生成するコードです。以下を引き続きfunctions.phpに記載しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
<?php function generate_nested_toc($content) { preg_match_all('/<h([2-3])[^>]*>(.*?)<\/h\1>/', $content, $matches, PREG_SET_ORDER); if (count($matches) < 2) return false; $toc = ''; $item_array = array( 'level' => 0, 'kaso' => [], ); $counter = 1; $prev_level = 0; $now_kaiso = [&$item_array]; foreach ($matches as $key => $match) { $level = intval($match[1]); $text = trim(strip_tags($match[2])); $id = 'post-target' . $counter; $class = 'toc-h' . $level; if($prev_level === 0){ //初回 $now_kaiso[0]['kaso'][] = array( 'item' => "<a href=\"#{$id}\" class=\"{$class}\">{$text}</a>", 'key' => $key, 'level' => $level, 'id' => $id, 'kaso' => [], ); }else if($prev_level === $level){//同じレベル $last_key = array_key_last($now_kaiso); $now_kaiso[$last_key]['kaso'][] = array( 'item' => "<a href=\"#{$id}\" class=\"{$class}\">{$text}</a>", 'key' => $key, 'level' => $level, 'id' => $id, 'kaso' => [], ); }else if($prev_level<$level){//大きい数字のh $last_key = array_key_last($now_kaiso); $next_key = array_key_last($now_kaiso[$last_key]['kaso']); $now_kaiso[$last_key]['kaso'][$next_key]['kaso'][] = array( 'item' => "<a href=\"#{$id}\" class=\"{$class}\">{$text}</a>", 'key' => $key, 'level' => $level, 'id' => $id, 'kaso' => [], ); $now_kaiso[] =& $now_kaiso[$last_key]['kaso'][$next_key]; }else if($prev_level>$level){//小さい数字のh $prev_key = true; $stop = 0;//念のため while($prev_key){ $last_key = array_key_last($now_kaiso); if($now_kaiso[$last_key]['level']>=$level){ array_pop($now_kaiso); }else{ $prev_key = false; } $stop++; if($stop>6){ break; } } $last_key = array_key_last($now_kaiso); $now_kaiso[$last_key]['kaso'][] = array( 'item' => "<a href=\"#{$id}\" class=\"{$class}\">{$text}</a>", 'key' => $key, 'level' => $level, 'id' => $id, 'kaso' => [], ); } $prev_level = $level; $counter++; } if(!empty($item_array['kaso'])){ $toc .= '<ul class="nested-toc">'; $toc .= render_toc($item_array['kaso']); $toc .= '</ul>'; } return $toc; } function render_toc($items){ $html = ''; foreach($items as $item){ $html .= '<li>'; $html .= $item['item']; if(!empty($item['kaso'])){ $html .= '<ul>'; $html .= render_toc($item['kaso']); $html .= '</ul>'; } $html .= '</li>'; } return $html; } |
ちょっと長いですが貼り付けましょう。
注意点として3行目の「preg_match_all」で指定する正規表現のhタグの範囲は前述の記事内のhタグにIDを付与した処理と同じ範囲になるよう気をつけてください。
軽く解説すると「generate_nested_toc」は目次を生成するための関数で、「render_toc」はhtmlを付与するための関数です。
single.phpなどで使用するのは「generate_nested_toc」の方となりますので間違えないようにしましょう。
目次の出力
ここまで来たら後は簡単、目次を表示したい箇所に関数を記述しましょう。
第1引数で記事の内容が必要なのでおきをつけください。
例としては下記のようにつかいます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php get_header(); the_post(); $my_toc = generate_nested_toc(get_the_content());//目次の生成 ?> <main> <article> <h1><?php the_title_attribute(); ?></h1> <div class="kokoni-mokuji"><?php echo $my_toc ?></div> <div class="user_contents"><?php the_content(); ?></div> </article> </main> <?php get_footer(); ?> |
これで目次が生成できたと思います。
それでは良きコーディングライフを。
WordPress