Advertisement
Guest User

Untitled

a guest
Apr 30th, 2017
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.03 KB | None | 0 0
  1. <?php
  2. /**
  3. * 目次に関する情報を取得します。
  4. *
  5. * @param string $content 記事本文
  6. * @return array content: 見出し用更新後の記事本文、outline: 目次
  7. */
  8. function get_outline_info($content) {
  9. // 目次のHTMLを入れる変数を定義します。
  10. $outline = '';
  11. // 記事内のh1〜h6タグを検索します。
  12. if (preg_match_all('/<h([1-6])>(.*?)<\/h\1>/', $content, $matches, PREG_SET_ORDER)) {
  13. // 記事内で使われているh1〜h6タグの中の、1〜6の中の一番小さな数字を取得します。
  14. // ※以降ソースの中にある、levelという単語は1〜6のことを表します。
  15. $min_level = min(array_map(function($m) { return $m[1]; }, $matches));
  16. // スタート時のlevelを決定します。
  17. // ※このレベルが上がる毎に、<ul></li>タグが追加されていきます。
  18. $current_level = $min_level - 1;
  19. // 各レベルの出現数を格納する配列を定義します。
  20. $sub_levels = array('1' => 0, '2' => 0, '3' => 0, '4' => 0, '5' => 0, '6' => 0);
  21. // 記事内で見つかった、hタグの数だけループします。
  22. foreach ($matches as $m) {
  23. $level = $m[1]; // 見つかったhタグのlevelを取得します。
  24. $text = $m[2]; // 見つかったhタグの、タグの中身を取得します。
  25. // li, ulタグを閉じる処理です。2ループ目以降に中に入る可能性があります。
  26. // 例えば、前回処理したのがh3タグで、今回出現したのがh2タグの場合、
  27. // h3タグ用のulを閉じて、h2タグに備えます。
  28. while ($current_level > $level) {
  29. $current_level--;
  30. $outline .= '</li></ul>';
  31. }
  32. // 同じlevelの場合、liタグを閉じ、新しく開きます。
  33. if ($current_level == $level) {
  34. $outline .= '</li><li>';
  35. } else {
  36. // 同じlevelでない場合は、ul, liタグを追加していきます。
  37. // 例えば、前回処理したのがh2タグで、今回出現したのがh3タグの場合、
  38. // h3タグのためにulを追加します。
  39. while ($current_level < $level) {
  40. $current_level++;
  41. $outline .= sprintf('<ul class="indent_%s"><li>', $current_level);
  42. }
  43. // ※2016/1/13追加
  44. // 見出しのレベルが変わった場合は、現在のレベル以下の出現回数をリセットします。
  45. for ($idx = $current_level + 0; $idx < count($sub_levels); $idx++) {
  46. $sub_levels[$idx] = 0;
  47. }
  48. }
  49. // 各レベルの出現数を格納する配列を更新します。
  50. $sub_levels[$current_level]++;
  51. // 現在処理中のhタグの、パスを入れる配列を定義します。
  52. // 例えば、h2 -> h3 -> h3タグと進んでいる場合は、
  53. // level_fullpathはarray(1, 2)のようになります。
  54. // ※level_fullpath[0]の1は、1番目のh2タグの直下に入っていることを表します。
  55. // ※level_fullpath[1]の2は、2番目のh3を表します。
  56. $level_fullpath = array();
  57. for ($idx = $min_level; $idx <= $level; $idx++) {
  58. $level_fullpath[] = $sub_levels[$idx];
  59. }
  60. $target_anchor = '#outline_' . implode('_', $level_fullpath);
  61. // ※2016/1/13修正
  62. // 目次に、<a href="#outline_1_2">1.2 見出し</a>のような形式で見出しを追加します。
  63. $outline .= sprintf('<a href="%s">%s. %s</a>', $target_anchor, implode('.', $level_fullpath), $text);
  64. // 本文中の見出し本体を、<h3>見出し</h3>を<h3 data-outline="#outline_1_2">見出し</h3>
  65. // のような形式で置き換えます。
  66. $content = preg_replace('/<h([1-6])>/', '<h\1 data-outline="' . $target_anchor . '">', $content, 1);
  67. }
  68. // hタグのループが終了後、閉じられていないulタグを閉じていきます。
  69. while ($current_level >= $min_level) {
  70. $outline .= '</li></ul>';
  71. $current_level--;
  72. }
  73. }
  74. return array('content' => $content, 'outline' => $outline);
  75. }
  76. /**
  77. * 目次を作成します。
  78. */
  79. function add_outline($content) {
  80. if (!is_single() && !is_page()) {
  81. // 個別記事ページと固定ページ以外には目次を表示させません。
  82. return $content;
  83. } else if (strtolower(get_post_meta(get_the_ID(), 'disable_outline', true)) == 'true') {
  84. // カスタムフィールド(disable_outline)にtrueが設定されている場合、目次を表示しません。
  85. return $content;
  86. }
  87. // 目次関連の情報を取得します。
  88. $outline_info = get_outline_info($content);
  89. $content = $outline_info['content'];
  90. $outline = $outline_info['outline'];
  91. if ($outline != '') {
  92. // 目次を装飾します。
  93. $decorated_outline = sprintf('<div id="outline"><div class="outline_header">目次 [<a href="#"><span class="hide_text">非表示</span><span class="show_text" style="display: none;">表示</span></a>]</div>%s</div>', $outline);
  94. // 目次を追加します。
  95. $shortcode_outline = '[outline]';
  96. if (strpos($content, $shortcode_outline) !== false) {
  97. // 記事内にショートコードがある場合、ショートコードを目次で置換します。
  98. $content = str_replace($shortcode_outline, $decorated_outline, $content);
  99. } else if (preg_match('/<h[1-6].*>/', $content, $matches, PREG_OFFSET_CAPTURE)) {
  100. // 最初のhタグの前に目次を追加します。
  101. $pos = $matches[0][1];
  102. $content = substr($content, 0, $pos) . $decorated_outline . substr($content, $pos);
  103. }
  104. }
  105. return $content;
  106. }
  107. add_filter('the_content', 'add_outline');
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement