ここ最近「サイトでも作ってみようかな」と思い立ち、『LION MEDIA』というテーマを見つけました。

私の求める機能がある程度デフォルトで備わっていたため、早速ダウンロードし、ローカルでいろいろいじってみています。

ローカルでWordPress実行環境作成に関してはこちらをご参考ください。

前置き

そもそもなぜ今回タイトルのような設定が必要になったかというと、『LION MEDIA』にはリンクカードがデフォルト機能として備わっていない事が発端でした。

当ブログでは以前、リンクカードを作成してくれるプラグイン『Pz-LinkCard』を使用してきましたが、現在は『賢威8』デフォルトのリンクカードを使用しています。

Pz-LinkCard』から『賢威8』デフォルトのリンクカードへ切り替えたのは『賢威8』デフォルトのデザインの方が好きだったという単純な理由だったので、『LION MEDIA』でリンクカードを作成出来るように、と考えた時にも真っ先に思い浮かんだのは『Pz-LinkCard』でした。

しかし、ローカル開発環境がある中でプラグインだけで済ませてしまうのは面白くない、と(何を思ったか)思い立ち、実装する方向でリサーチを続けました。

調べてみて思ったことですが、世の流れとしてはプラグインによる導入よりも自作に傾いているようです。

その大きな理由としては、プラグイン(特に『Pz-LinkCard』)を有効化することでサイト自体が重くなる、ことが挙げられるようです。

結果として、プラグインではなくサービスに頼ることにしました。今はPHPやってる場合ジャナイ。

参考にしたサイトはこちらです。『Embed』の他にも2つほど紹介しているので、リンクカードに悩んだ時にはどうぞご参考ください。

目次に表示される見出しタグの制御

前述の通り、『Embed』のサービスを利用してリンクカードを表示するためのコードは取得できたのですが、実際に表示してみたところ…。

このように、リンクカード表示用のコードにh4タグが入っているため、目次に表示されてしまいます。

Pz-LinkCard』であれば目次として表示するタグをGUI設定で変更可能でしたが、今回はコードから生成しているため、目次を表示する機能を書き換える必要があります。

変更するのは『functions.php』の、(デフォルトであれば)5596行目から始まる『get_outline_info』関数です。

//////////////////////////////////////////////////
//オリジナル目次を作成
//////////////////////////////////////////////////
function get_outline_info($content) {
	// 目次のHTMLを入れる変数を定義します。
	$outline = '';
	// h1〜h6タグの個数を入れる変数を定義します。
	$counter = 0;
    // 記事内のh1〜h6タグを検索します。(idやclass属性も含むように改良)
    if (preg_match_all('/<h([1-6])[^>]*>(.*?)<\/h\1>/', $content, $matches,  PREG_SET_ORDER)) {
    	   // 記事内で使われているh1〜h6タグの中の、1〜6の中の一番小さな数字を取得します。
    	   // ※以降ソースの中にある、levelという単語は1〜6のことを表します。
        $min_level = min(array_map(function($m) { return $m[1]; }, $matches));
        // スタート時のlevelを決定します。
        // ※このレベルが上がる毎に、<ul></li>タグが追加されていきます。
        $current_level = $min_level - 1;
        // 各レベルの出現数を格納する配列を定義します。
        $sub_levels = array('1' => 0, '2' => 0, '3' => 0, '4' => 0, '5' => 0, '6' => 0);
        // 記事内で見つかった、hタグの数だけループします。
        foreach ($matches as $m) {
            $level = $m[1];  // 見つかったhタグのlevelを取得します。
            $text = $m[2];  // 見つかったhタグの、タグの中身を取得します。
            // li, ulタグを閉じる処理です。2ループ目以降に中に入る可能性があります。
            // 例えば、前回処理したのがh3タグで、今回出現したのがh2タグの場合、
            // h3タグ用のulを閉じて、h2タグに備えます。
            while ($current_level > $level) {
                $current_level--;
                $outline .= '</li></ul>';
            }
            // 同じlevelの場合、liタグを閉じ、新しく開きます。
            if ($current_level == $level) {
                $outline .= '</li><li class="outline__item">';
            } else {
                // 同じlevelでない場合は、ul, liタグを追加していきます。
                // 例えば、前回処理したのがh2タグで、今回出現したのがh3タグの場合、
                // h3タグのためにulを追加します。
                while ($current_level < $level) {
                    $current_level++;
                    $outline .= sprintf('<ul class="outline__list outline__list-%s"><li class="outline__item">', $current_level);
                }
                // 見出しのレベルが変わった場合は、現在のレベル以下の出現回数をリセットします。
                for ($idx = $current_level + 0; $idx < count($sub_levels); $idx++) {
                    $sub_levels[$idx] = 0;
                }
            }
            // 各レベルの出現数を格納する配列を更新します。
            $sub_levels[$current_level]++;
            // 現在処理中のhタグの、パスを入れる配列を定義します。
            // 例えば、h2 -> h3 -> h3タグと進んでいる場合は、
            // level_fullpathはarray(1, 2)のようになります。
            // ※level_fullpath[0]の1は、1番目のh2タグの直下に入っていることを表します。
            // ※level_fullpath[1]の2は、2番目のh3を表します。
            $level_fullpath = array();
            for ($idx = $min_level; $idx <= $level; $idx++) {
                $level_fullpath[] = $sub_levels[$idx];
            }
            $target_anchor = 'outline__' . implode('_', $level_fullpath);

            // 目次に、<a href="#outline_1_2">1.2 見出し</a>のような形式で見出しを追加します。
            $outline .= sprintf('<a class="outline__link" href="#%s"><span class="outline__number">%s.</span> %s</a>', $target_anchor, implode('.', $level_fullpath), strip_tags($text));
            // 本文中の見出し本体を、<h3>見出し</h3>を<h3 id="outline_1_2">見出し</h3>
            // のような形式で置き換えます。
            $hid = preg_replace('/<h([1-6])/', '<h\1 id="' .$target_anchor . '"', $m[0]);
            $content = str_replace($m[0], $hid, $content);
			
        }
        // hタグのループが終了後、閉じられていないulタグを閉じていきます。
        while ($current_level >= $min_level) {
            $outline .= '</li></ul>';
            $current_level--;
        }
        // h1〜h6タグの個数
        $counter = count($matches);
    }
    return array('content' => $content, 'outline' => $outline, 'count' => $counter);
}

get_outline_info』関数内の変数『$level』に見出しタグ(h)の数字部分が入りますので、値を取得したところで処理をスキップし、繰り返し処理を続行させます。

        // 記事内で見つかった、hタグの数だけループします。
        foreach ($matches as $m) {
            $level = $m[1];  // 見つかったhタグのlevelを取得します。
			$text = $m[2];  // 見つかったhタグの、タグの中身を取得します。
			
			// h4以下は目次に含めない
			if (3 < $level) {
				continue;
			}

            // li, ulタグを閉じる処理です。2ループ目以降に中に入る可能性があります。
            // 例えば、前回処理したのがh3タグで、今回出現したのがh2タグの場合、
            // h3タグ用のulを閉じて、h2タグに備えます。
            while ($current_level > $level) {
                $current_level--;
                $outline .= '</li></ul>';
            }

暫定感が半端ありませんが、上記変更により目次として表示される見出しタグをh1~3に制御することが出来ます。

こういった対処がすぐ思いつく点に関しては、システムエンジニアやってて良かったと思いますね、本当に。

以上です。

スポンサーリンク