» » Содержание статьи в WordPress без плагинов

Содержание статьи в WordPress без плагинов

0
Содержание статьи в WordPress без плагинов

С помощью кода, взятого на wp-kama.ru мы покажем на примере, как добавить этот код на сайт, чтобы автоматически в начале каждого поста было содержание.

Итак, код содержания, который нужно вставить в файл functions.php вашей темы:
/**
 * Содержание/оглавление для больших постов.
 * Автор: Тимур Камаев
 * Страница: http://wp-kama.ru/?p=1513
 * Версия: 3.0
 *
 * Changelog: http://wp-kama.ru/?p=1513#obnovleniya
 */
class Kama_Contents{    
          // defaults options
          public $opt = array(
                    // Отступ слева у подразделов в px.
                    'margin'     => 40,
                    // Теги по умолчанию по котором будет строиться оглавление. Порядок имеет значение. 
                    // Кроме тегов, можно указать атрибут classа: array('h2','.class_name'). Можно указать строкой: 'h2 h3 .class_name'
                    'selectors'  => array('h2','h3','h4'),
                    // Ссылка на возврат к оглавлению. '' - убрать ссылку
                    'to_menu'    => 'к содержанию ↑',
                    // Заголовок. '' - убрать заголовок 
                    'title'      => 'Содержание:',
                    // Css стили. '' - убрать стили
                    'css'        => '.kc__gotop{ display:block; text-align:right; } .kc__title{ font-style:italic; margin:1em 0; }',
                    // Минимальное количество найденных тегов, чтобы оглавление выводилось.
                    'min_found'  => 4,
                    // Минимальная длина (символов) текста, чтобы оглавление выводилось.
                    'min_length' => 2000,
                    // Ссылка на страницу для которой собирается оглавление. Если оглавление выводиться на другой странице...
                    'page_url'   => '',
                    // Название шоткода
                    'shortcode'  => 'contents',
                    // Оставлять символы в анкорах
                    'spec'       => '\'.+$*~=',
                    // Какой тип анкора использовать: 'a' - <a name="anchor"></a> или 'id' - 
                    'anchor_type' => 'id',
                    // Включить микроразметку?
                    'markup' => true,
          );
 
          public $contents; // collect html contents
 
          private $temp;
 
          static $inst;
 
          function __construct( $args = array() ){
                    $this->set_opt( $args );
                    return $this;
          }
 
          ## экземпляр
          static function init( $args = array() ){
                    is_null( self::$inst ) && self::$inst = new self( $args );
                    if( $args ) self::$inst->set_opt( $args );
                    return self::$inst;
          }
 
          function set_opt( $args = array() ){
                    $this->opt = (object) array_merge( (array) $this->opt, (array) $args );
          }
 
          /**
           * Обрабатывает текст, превращает шоткод в нем в оглавление.
           * @param (string) $content текст, в котором есть шоткод.
           * @param (string) $contents_cb колбек фунция, которая обработает список оглавления.
           * @return Обработанный текст с оглавлением, если в нем есть шоткод.
           */
          function shortcode( $content, $contents_cb = '' ){
                    if( false === strpos( $content, '['. $this->opt->shortcode ) ) 
                              return $content; 
 
                    // get contents data
                    if( ! preg_match('~^(.*)\['. $this->opt->shortcode .'([^\]]*)\](.*)$~s', $content, $m ) )
                              return $content;
 
                    $contents = $this->make_contents( $m[3], $m[2] );
 
                    if( $contents && $contents_cb && is_callable($contents_cb) )
                              $contents = $contents_cb( $contents );
 
                    return $m[1] . $contents . $m[3];
          }
 
          /**
           * Заменяет заголовки в переданном тексте (по ссылке), создает и возвращает оглавление.
           * @param (string)        $content текст на основе которого нужно создать оглавление.
           * @param (array/string)  $tags    массив тегов, которые искать в переданном тексте. 
           *                                 Можно указать: имена тегов "h2 h3" или классы элементов ".foo .foo2".
           *                                 Если в теги добавить маркер "embed" то вернется только тег <ul>
           *                                 без заголовка и оборачивающего блока. Нужно для использования внутри текста, как список.
           * @return                html код оглавления.
           */
          function make_contents( & $content, $tags = '' ){
                    // выходим если текст короткий
                    if( mb_strlen( strip_tags($content) ) < $this->opt->min_length ) return;
 
                    $this->temp     = $this->opt;
                    $this->temp->i  = 0;
                    $this->contents = '';
 
                    if( is_string($tags) && $tags = trim($tags) )
                              $tags = array_map('trim', preg_split('~\s+~', $tags ) );
 
                    if( ! $tags )
                              $tags = $this->opt->selectors;
 
                    // check tags
                    foreach( $tags as $k => $tag ){
                              // remove special marker tags and set $args
                              if( in_array( $tag, array('embed','no_to_menu') ) ){
                                        if( $tag == 'embed' ) $this->temp->embed = true;
                                        if( $tag == 'no_to_menu' ) $this->opt->to_menu = false;
 
                                        unset( $tags[ $k ] );
                                        continue;
                              }
 
                              // remove tag if it's not exists in content
                              $patt = ( ($tag[0] == '.') ? 'class=[\'"][^\'"]*'. substr($tag, 1) : "<$tag" );
                              if( ! preg_match("/$patt/i", $content ) ){
                                        unset( $tags[ $k ] );
                                        continue;
                              }
                    }
 
                    if( ! $tags ) return;
 
                    // set patterns from given $tags
                    // separate classes & tags & set
                    $class_patt = $tag_patt = $level_tags = array();
                    foreach( $tags as $tag ){
                              // class
                              if( $tag{0} == '.' ){
                                        $tag  = substr( $tag, 1 );
                                        $link = & $class_patt;
                              }
                              // html tag
                              else
                                        $link = & $tag_patt;
 
                              $link[] = $tag;         
                              $level_tags[] = $tag;
                    }
 
                    $this->temp->level_tags = array_flip( $level_tags );
 
                    // заменяем все заголовки и собираем оглавление в $this->contents
                    $patt_in = array();
                    if( $tag_patt )   $patt_in[] = '(?:<('. implode('|', $tag_patt) .')([^>]*)>(.*?)<\/\1>)';
                    if( $class_patt ) $patt_in[] = '(?:<([^ >]+) ([^>]*class=["\'][^>]*('. implode('|', $class_patt) .')[^>]*["\'][^>]*)>(.*?)<\/'. ($patt_in?'\4':'\1') .'>)';
 
                    $patt_in = implode('|', $patt_in );
 
                    // collect and replace
                    $_content = preg_replace_callback("/$patt_in/is", array( &$this, '__make_contents_callback'), $content, -1, $count );
 
                    if( ! $count || $count < $this->opt->min_found )
                              return;
 
                    $content = $_content; // опять работаем с важной $content
 
                    // html
                    static $css;
                    $embed   = !! isset($this->temp->embed);
                    $_tit    = & $this->opt->title;
                    $_is_tit = ! $embed && $_tit;
 
                    // markup
                    $ItemList = $this->opt->markup ? ' itemscope itemtype="http://schema.org/ItemList"' : '';   
 
                    $this->contents = 
                              ( $_is_tit ? '<div class="kc__wrap"'. $ItemList .' >' : '' ) .
                              ( ( ! $css && $this->opt->css ) ? '<style>'. $this->opt->css .'</style>' : '' ) .
                              ( $_is_tit ? '<div class="kc-title kc__title" id="kcmenu"'. ($ItemList?' itemprop="name"':'') .'>'. $_tit .'</div>'. "\n" : '' ) .
                                        '<ul class="contents"'. ( (! $_tit || $embed) ? ' id="kcmenu"' : '' ) . ( ($ItemList && ! $_is_tit ) ? $ItemList : '' ) .'>'. "\n". 
                                                  implode('', $this->contents ) .
                                        '</ul>'."\n" .
                              ( $_is_tit ? '</div>' : '' );
 
                    return $this->contents;
          }
 
          ## callback функция для замены и сбора оглавления
          private function __make_contents_callback( $match ){
                    // it's only class selector in pattern
                    if( count($match) == 5 ){
                              $tag   = $match[1];
                              $attrs = $match[2];
                              $title = $match[4];
 
                              $level_tag = $match[3]; // class_name
                    }
                    // it's found tag selector
                    elseif( count($match) == 4 ){
                              $tag   = $match[1];
                              $attrs = $match[2];
                              $title = $match[3];
 
                              $level_tag = $tag;
                    }
                    // it's found class selector
                    else{
                              $tag   = $match[4];
                              $attrs = $match[5];
                              $title = $match[7];
 
                              $level_tag = $match[6]; // class_name
                    }
 
                    $anchor = $this->__sanitaze_anchor( $title );
                    $opt = & $this->opt;
 
                    $level = @ $this->temp->level_tags[ $level_tag ];
                    if( $level > 0 )
                              $sub = ( $opt->margin ? ' style="margin-left:'. ($level*$opt->margin) .'px;"' : '') . ' class="sub sub_'. $level .'"';
                    else
                              $sub = ' class="top"';
 
                    // собираем оглавление
                    // markup
                    $_is_mark = & $this->opt->markup;
 
                    $this->contents[] = "\t".
                              '<li'. $sub . ($_is_mark?' itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"':'') .'>'.
                                        '<a rel="nofollow"'. ($_is_mark?' itemprop="item"':'') .' href="'. $opt->page_url .'#'. $anchor .'">'. ($_is_mark?'<span itemprop="name">'. $title .'</span>':$title) .'</a>
                              </li>'. "\n";
 
                    // заменяем
                    $to_menu = $new_el = '';
                    if( $opt->to_menu )
                              $to_menu = (++$this->temp->i == 1) ? '' : '<a rel="nofollow" class="kc-gotop kc__gotop" href="'. $opt->page_url .'#kcmenu">'. $opt->to_menu .'</a>';
 
                    $new_el = "\n<$tag id=\"$anchor\" $attrs>$title</$tag>";
                    if( $opt->anchor_type == 'a' )
                              $new_el = '<a class="kc-anchor kc__anchor" name="'. $anchor .'"></a>'."\n<$tag $attrs>$title</$tag>";
 
                    return $to_menu . $new_el;
          }
 
          ## Транслитерация УРЛ
          private function __sanitaze_anchor( $str ){
                    $str = strip_tags( $str );
 
                    $iso9 = array(
                              'А'=>'A', 'Б'=>'B', 'В'=>'V', 'Г'=>'G', 'Д'=>'D', 'Е'=>'E', 'Ё'=>'YO', 'Ж'=>'ZH',
                              'З'=>'Z', 'И'=>'I', 'Й'=>'J', 'К'=>'K', 'Л'=>'L', 'М'=>'M', 'Н'=>'N', 'О'=>'O',
                              'П'=>'P', 'Р'=>'R', 'С'=>'S', 'Т'=>'T', 'У'=>'U', 'Ф'=>'F', 'Х'=>'H', 'Ц'=>'TS',
                              'Ч'=>'CH', 'Ш'=>'SH', 'Щ'=>'SHH', 'Ъ'=>'', 'Ы'=>'Y', 'Ь'=>'', 'Э'=>'E', 'Ю'=>'YU', 'Я'=>'YA',
                              // small
                              'а'=>'a', 'б'=>'b', 'в'=>'v', 'г'=>'g', 'д'=>'d', 'е'=>'e', 'ё'=>'yo', 'ж'=>'zh',
                              'з'=>'z', 'и'=>'i', 'й'=>'j', 'к'=>'k', 'л'=>'l', 'м'=>'m', 'н'=>'n', 'о'=>'o',
                              'п'=>'p', 'р'=>'r', 'с'=>'s', 'т'=>'t', 'у'=>'u', 'ф'=>'f', 'х'=>'h', 'ц'=>'ts',
                              'ч'=>'ch', 'ш'=>'sh', 'щ'=>'shh', 'ъ'=>'', 'ы'=>'y', 'ь'=>'', 'э'=>'e', 'ю'=>'yu', 'я'=>'ya',
                              // other
                              'Ѓ'=>'G', 'Ґ'=>'G', 'Є'=>'YE', 'Ѕ'=>'Z', 'Ј'=>'J', 'І'=>'I', 'Ї'=>'YI', 'Ќ'=>'K', 'Љ'=>'L', 'Њ'=>'N', 'Ў'=>'U', 'Џ'=>'DH',          
                              'ѓ'=>'g', 'ґ'=>'g', 'є'=>'ye', 'ѕ'=>'z', 'ј'=>'j', 'і'=>'i', 'ї'=>'yi', 'ќ'=>'k', 'љ'=>'l', 'њ'=>'n', 'ў'=>'u', 'џ'=>'dh'
                    );
 
                    $str = strtr( $str, $iso9 );
 
                    $spec = preg_quote( $this->opt->spec );
                    $str  = preg_replace("/[^a-zA-Z0-9\-_$spec]+/", '-', $str ); // все ненужное на '-'
                    $str  = preg_replace('/^-+|-+$/', '', $str ); // кил конечные ---
 
                    return strtolower( $str );
          }
 
          ## Вырезает шоткод из контента
          function strip_shortcode( $text ){
                    return preg_replace('~\['. $this->opt->shortcode .'[^\]]*\]~', '', $text );
          }
}
## Вывод содержания вверху, автоматом для всех постов
add_filter('the_content', 'contents_on_post_top' );
function contents_on_post_top( $content ){
          if( ! is_singular() ) return $content;
 
          //$args['margin'] = 50;
          //$args['to_menu'] = true;
          //$args['title'] = false;
          $tags = array('h2','h3');
          $contents = Kama_Contents::init( $args )->make_contents( $content, $tags );
          return $contents . $content;
}


Скорее всего, после установки содержание будет выглядеть не очень красиво, поэтому настраиваем стили, которые позволят задать любой внешний вид нашему списку. Например для одного из моих сайтов они такие:
.content .kc__wrap {
    border: 0px solid #e2e4e6;
    border-left: 0;
    border-right: 0;
    padding-top: 0px;
          padding-bottom: 0px;
          padding-left: 8px;
    background: #f3f4f4;
}
.content .kc__title {
    font-style: normal;
          font-size: 14px;
          color:#fff;
          padding: 3px;
          background: #6BB32D;
          display: inline-block;
          margin-bottom: 5px;
}
.content .kc__gotop {
    display: block;
    text-align: right;
}
.contents {
font-size: 14px;
padding-bottom: 8px;
}
.content ul.contents{
font-size: 14px;
padding-bottom: 10px;
margin-bottom: 12px;
}
.contents{ list-style-type:none; counter-reset:list;  background: none; }
/* цвет чисел */
.contents li:before{ color:#555; }
/* уровень 0 */
.contents li.top{ counter-increment:list; counter-reset:list1; background: none; margin-bottom:5px;}
.contents li.top:before{ content:counter(list) '. '; }
/* уровень 1 */
.contents li.sub_1{ counter-increment:list1; counter-reset:list2; background: none; margin-bottom:5px;}
.contents li.sub_1:before{ content:counter(list) '.' counter(list1) '. '; }
/* уровень 2 */
.contents li.sub_2{ counter-increment:list2; background: none; margin-bottom:5px;}
.contents li.sub_2:before{ content:counter(list) '.' counter(list1) '.' counter(list2) '. '; }


Этот код нужно добавить перед тегом в файле header.php(в зависимости от шаблона, это мажет быть и footer.php), чтобы сделать плавную прокрутку:
<script type="text/javascript">
jQuery(document).ready(function($){
 
          // Прокрутка на все якоря (#) и на a[name]. v1.1
          $('a[href*="#"]').on('click.smoothscroll', function( e ){
                    var hash    = this.hash,
                              _hash   = hash.replace(/#/,''),
                              theHref = $(this).attr('href').replace(/#.*/, '');
 
                    if( theHref && location.href.replace(/#.*/,'') != theHref ) return; // не текущая страница
 
                    var $target = _hash === '' ? $('body') : $( hash + ', a[name="'+ _hash +'"]').first();
					headerHeight = $('.header').height() + 110;  


                    if( ! $target.length ) return;
 
                    e.preventDefault();
 
                    $('html, body').stop().animate({ scrollTop: $target.offset().top - headerHeight}, 400, 'swing', function(){
                              window.location.hash = hash;
                    });
          });
 
});
</script>


А этот код нужно добавить, если хотим добавить возможность скрыть содержание:
<script type="text/javascript">
/**
 * Показать/скрыть Содержание. Кнопка добавляется после Текста в заголовок - "Содержание: [скрыть]"
 * v 0.2
 */
jQuery(document).ready(function($){
          var $title = $('.kc__title'),
                    showtxt = '[показать]',
                    hidetxt = '[скрыть]',
                    $but = $('<span class="kc-show-hide" style="cursor:pointer;margin-left:.5em;font-size:80%;">'+ hidetxt +'</span>')
                    $but.click(function(){
                              var $the = $(this),
                                        $cont = $the.parent().next('.contents');
 
                              if( $the.text() == hidetxt ){
                                        $the.text( showtxt );
                                        $cont.slideUp();
                              }
                              else{
                                        $the.text( hidetxt );
                                        $cont.slideDown();      
                              }
                    });
 
          $title.append( $but );
});
</script>


Вот и все.
Источник: lucky-seo.com


Внимание!
Для просмотра скрытого текста, Вам необходимо Войти или Зарегистрироваться.
  • WordPress
  • 6-08-2018, 11:25
  • 158
Вернуться назад
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.