Рубрики

Урок 374 Как сделать автоматическое содержание статьи (оглавление) в WordPress

Петр Александров
Автор статьи Пётр Александров
39
Время прочтения: 8 мин.

Warning: preg_replace_callback(): Compilation failed: missing terminating ] for character class at offset 29 in /var/www/wpnew/data/www/wpnew.ru/wp-content/themes/wpnew2021/functions.php on line 510

Привет. Где-то пару недель назад я активно начал к объемным статьям составлять содержания (оглавления). После этого в мой адрес посыпалось куча вопросов в стиле: «Как это сделать?». Решил ответить постом. Вот как выглядит содержание статьи:

Данное оглавление имеет массу плюсов:

  • Посетитель сразу видит всю структуру статьи. Не устану повторять: главное в продвижении сайтов — это структура. Структура сайта, статьи и всего остального.
  • Размещены ссылки. То есть можно кликнуть по интересующему пункту и осуществится автоматическое пролистывание вниз до выбранного пункта.
  • Все это создается автоматически, за 2 секунды. Не нужно тратить время. Интересно? Еще бы. Читаем далее.

Необходимый код для составления содержания

Вручную создавать подобное содержание очень долгое занятие, ведь нужно:

  1. Понаставить «якори».
  2. Вручную задать название каждому пункту.
  3. Подбирать правильные ссылки с якорями.

Из-за сложностей и неудобств, я не использовал данный метод. Только в исключительных случаях. Для реализации автоматического оглавления, мне помог код, который я взял на одном классном блоге WP-Kama (скорей всего вы слышали о нем). Вот и сама статья — «Содержание больших постов«.

В статье показаны разные возможности реализации, я покажу, как использовал все это для себя.

Сначала скопируйте этот код:

/**
* Содержание для больших постов.
* Автор: Тимур Камаев
* Страница: http://wp-kama.ru/?p=1513
* Версия: 2.6
*/
class Kama_Contents {
var $margin;    // отступ слева у подразделов в пикселях. 40
var $rep_tags;  // теги по умолчанию по котором будет строиться содеражние. Порядок имеет значение. array('h2','h3','h4')
var $to_menu;   // ссылка на возврат к содержанию. '' - убрать ссылку
var $title;     // Заголовок. '' - убрать заголовок
var $css;       // css стили. '' - убрать стили
var $min_found; // минимальное количество найденных тегов, чтобы содержание выводилось.

var $temp;

protected static $instance;

function __construct( $args ){
// параметры по умолчанию
$def = array(
'margin'    => 40,
'rep_tags'  => array('h2','h3','h4'),
'to_menu'   => 'к содержанию ↑',
'title'     => 'Содержание:',
'css'       => '.kc_gotop{ display:block; text-align:right; } .kc_title{ font-style:normal;font-size:20px; padding:10px 0 10px; }',
'min_found' => 2,
);
// установим свойства
foreach( array_merge( $def, $args ) as $k => $v ) $this->$k = $v;
}

static function init( $args = array() ){
is_null( self::$instance ) AND self::$instance = new self( $args );
return self::$instance;
}

/**
* Обрабатывает текст, превращает шоткод в нем в содержание.
* @param (string) $content текст, в котором есть шоткод.
* @return Обработанный текст с содержанием, если в нем есть шоткод.
*/
function shortcode( $content ){
// получаем данные о содержании
if( ! preg_match('~^(.*)\[contents([^\\]]*)\](.*)$~s', $content, $m ) )
return $content;

if( $tags = trim( $m[2] ) )
$tags = array_map('trim', explode(' ', $tags ) );

$contents = $this->make_contents( $m[3], $tags );

return $m[1] . $contents . $m[3];
}

/**
* Заменяет заголовки в переданном тексте (по ссылке), создает и возвращает содержание.
* @param (string) $content текст на основе которого нужно создать содержание.
* @param (array)  $tags    массив тегов, которые искать в переданном тексте.
* @return                  html код содержания.
*/
function make_contents( $content, $tags = array() ){
// переменные
$this->temp    = new stdClass;
$this->temp->i = 0;

if( ! $tags ) $tags = $this->rep_tags;

$this->temp->tag_level = array_flip( $tags ); // перевернем

// заменяем все заголовки и собираем содержание в $this->temp->contents
$h_patt = implode('|', $tags );
$_content = preg_replace_callback('@<('. $h_patt .')([^>]*)>(.*?)</(?:'. $h_patt .')>@is', array( $this, 'make_contents_callback'), $content, -1, $count );

if( ! $count || $count < $this->min_found ) return;

$content = $_content; // опять работаем с важной $content

// html содержания
$contents = '';
if( $this->title )
$contents .= '
<div class='kc_title' id='kcmenu'>'. $this->title .'</div>

'. '\n';

$contents .= '
<ul class='contents''. (!$this->title ? ' id='kcmenu'' : '') .'>'. '\n' .
implode('', $this->temp->contents ) .
'</ul>

'.'\n';

$contents = '
<div class='contents-wrap'>'. $contents .'</div>

';

$this->temp = new stdClass; // чистим

static $css;
$css = ( ! $css $this->css ) ? '
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E'.%20%24this-%3Ecss%20.'%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" />

' : '';

return $css . $contents;
}

## callback функция для замены и сбора содержания
protected function make_contents_callback( $match ){
$tag   = $match[1];
$attrs = $match[2];
$txt   = $match[3];
$anchor = $this->transl4url( $txt );

if( 0 < $level = $this->temp->tag_level[ $tag ] )
$sub = ( $this->margin ? ' style='margin-left:'. ($level*$this->margin) .'px;'' : '') . ' class='sub sub_'. $level .''';
else
$sub = ' class='top'';

// собираем содержание
$this->temp->contents[] = '\t'. '<li'. $sub .'><a href='#'. $anchor .''>'. $txt .'</a></li>

'. '\n';

// заменяем
$out = '';
if( $this->to_menu )
$out .= $this->temp->i == 1 ? '' : '<a class='kc_gotop' href='#kcmenu'>'. $this->to_menu .'</a>';
$out .= '<a name=''. $anchor .''></a>'.'\n'.'<'. $tag . $attrs .'>'. $txt .'</'. $tag .'>;';

return $out;
}

## транслитерация для УРЛ
function transl4url( $str ){
$conv = array(
'а' => 'a',  'б' => 'b',  'в' => 'v',  'г' => 'g',  'д' => 'd',  'е' => 'e',  'ё' => 'e',  'ж' => 'zh',  'з' => 'z',
'и' => 'i',  'й' => 'y',  'к' => 'k',  'л' => 'l',  'м' =>; 'm',  'н' => 'n',  'о' => 'o',  'п' => 'p',  'р' => 'r',
'с' => 's',  'т' => 't',  'у' => 'u',  'ф' => 'f',  'х' => 'h',  'ц' => 'c',  'ч' => 'ch',  'ш' => 'sh',  'щ' => 'sch',
'ы' => 'y',  'э' => 'e',  'ю' => 'yu',  'я' => 'ya',

'А' => 'A',  'Б' => 'B',  'В' => 'V',  'Г' => 'G',  'Д' => 'D',  'Е' => 'E',  'Ё' => 'E',  'Ж' => 'Zh',  'З' => 'Z',
'И' => 'I',  'Й' => 'Y',  'К' => 'K',  'Л' => 'L',  'М' => 'M',  'Н' => 'N',  'О' => 'O',  'П' => 'P',  'Р' => 'R',
'С' =>'S',   'Т' => 'T',  'У' => 'U',  'Ф' => 'F',  'Х' => 'H',  'Ц' => 'C',  'Ч' => 'Ch',  'Ш' => 'Sh',  'Щ' => 'Sch',
'Ы' => 'Y',  'Э' => 'E',  'Ю' => 'Yu', 'Я' => 'Ya',
);

$str = strtr( $str, $conv );
$str = strtolower( $str );
$str = preg_replace('~[^-a-z0-9_]+~u', '-', $str ); // все ненужное на '-'
$str = trim( $str, '-'); // начальные и конечные '-'

return $str;
}
}

## Обработка шоткода [contents] в тексте
add_filter('the_content', 'kama_contents_shortcode');
function kama_contents_shortcode( $content ){
if( ! is_singular() ) return preg_replace('~\]*\]~', '', $content); // если не отдельная страница вырезаем выходим
if( false === strpos( $content, '[content') ) return $content; // если нет шоткода выходим

//$args['margin'] = 30;
$args['to_menu'] = 'к оглавлению ↑';
$args['title'] = 'Оглавление:';
return Kama_Contents::init( $args )->shortcode( $content );
}

Откройте файл function.php, который располагается в папке вашего шаблона и вставьте этот код в конец файла:

Стили оглавления

Дальше скопируйте этот код:

.contents{ list-style-type:none; counter-reset:list; }
/* цвет чисел */
.contents li:before{ color:#555; }
/* уровень 0 */
.contents li.top{ counter-increment:list; counter-reset:list1; }
.contents li.top:before{ content:counter(list) '. '; }
/* уровень 1 */
.contents li.sub_1{ counter-increment:list1; counter-reset:list2; }
.contents li.sub_1:before{ content:counter(list) '.' counter(list1) '. '; }
/* уровень 2 */
.contents li.sub_2{ counter-increment:list2; }
.contents li.sub_2:before{ content:counter(list) '.' counter(list1) '.' counter(list2) '. '; }

Откройте файл style.css Вашей темы и вставьте в его в конец файла:

Как использовать

Теперь просто в нужных местах во время написания статей используете заголовок 2 (h2) и заголовок 3 (h3) при необходимости:

Напомню, очень важно правильно использовать заголовки h1, h2, h3 в SEO. В итоге, прописанные заголовки h2 и h3  будут теми самими пунктами оглавления. Надеюсь, хоть это содержание заставит многих использовать заголовки в своих статьях, а то многие вообще игнорируют все это.

Уже потом выводим в нужном месте само меню. Как? Просто вставляем вот шорткод contents в редакторе статьи туда, где нужно вывести содержание.

Выглядит будет примерно так:

В результате получим то необходимое меню, в которым основные пункты — это использованные заголовки h2, а подпункты — заголовки h3:

Вывод

Вот так просто все это внедрить себе на блог. Спасибо Тимуру Камаеву за такой классный код. Если вы вдруг захотите добавить какие-то дополнительные «плюшки», перейдите по ссылке, там есть интересные дополнения, которые могут кому-то пригодятся.

Я же очень хочу, чтобы вы использовали данный код хотя бы для того, чтобы Ваши статьи получались более структурированными и Вы «рвали» ТОП со своими классными статьями. Всего вам хорошего!

И спасибо за ретвит. 🙂

39 комментариев на «Урок 374 Как сделать автоматическое содержание статьи (оглавление) в WordPress»
  1. seoonly.ru
    https://seoonly.ru/

    Спасибо ВПкаме))

    • Пётр Александров Автор статьи
      https://wpnew.ru

      ВПкама, ВПнью, ахаххаха) Да, спасибо Тимуру.

  2. Мария Хайнц
    http://superhappy.ru

    Петр, спасибо, что объяснили! Как всегда, все доступно и понятно!

    • Пётр Александров Автор статьи
      https://wpnew.ru

      Рад был помочь )

  3. Анжелика

    Делала содержание статьи вручную, довольно неудобно, с кодом, конечно проще. Петр, подскажите, как правильно ставить рекламные блоки РСЯ на сайт, каким инструментом или плагином пользоваться. Пробовала добавить в сайтбар через виджет, блок не отображается. Подскажите, если можно. И еще, у Вас не работает поиск по сайту, пыталась поискать информацию, не загружаются результаты.

    • Пётр Александров Автор статьи
      https://wpnew.ru

      Вставляйте сразу в файл темы — sidebar.php, single.php и прочее

  4. Alex

    1. А вы не боитесь использовать чужой код? Или так хорошо разбираетесь в php, что сразу видите какие-нибудь «закладки»? Я не про данный код, а вообще.
    2. Вы используете «дочернюю» тему WP или вообще «самописную»? Неплохо было бы упомянуть про влияние обновления тем на изменения в файлах function.php и style.css!
    P.S. у автора уже версия 2.7.1 от 14.04.15

    • Пётр Александров Автор статьи
      https://wpnew.ru

      1. Честно, боюсь, поэтому беру только у проверенных авторов.
      2. Самописная.
      P.s. Да, плагин регулярно обновляется. Весь необходимый функционал есть и в этом коде этой версии. В обновлениях разные «плюшки», которые рядовому пользователю практически не нужны.

      • Alex

        Плагин? Не являюсь знатоком WP, как вы, но плагины, вроде бы, не в файле function.php должны быть, хотя функция add_filter намекает на сходство с плагинами 🙂

        • Пётр Александров Автор статьи
          https://wpnew.ru

          Ой, оговорился. Код. Не плагин.

      • Руслан

        Есть плагин с похожим функционалом, делает то же самое что и скрипт в статье, называется toc+

  5. Alex

    какие-то проблемы со временем в комментариях: получается, что на мое сообщение в 20:23 вы мне ответили в 20:12!

Добавить комментарий
Ваш адрес email не будет опубликован. Обязательные поля помечены
Нажав на кнопку «Отправить комментарий» вы принимаете соглашение на обработку персональных данных.
Подпишитесь на бесплатные уроки по e‑mail и получите книгу в подарок
Нажав на кнопку «Подписаться» вы принимаете соглашение на обработку персональных данных.
Книга по SEO