Рубрики

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

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

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

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

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

  • Посетитель сразу видит всю структуру статьи. Не устану повторять: главное в продвижении сайтов – это структура. Структура сайта, статьи и всего остального.
  • Размещены ссылки. То есть можно кликнуть по интересующему пункту и осуществится автоматическое пролистывание вниз до выбранного пункта.
  • Все это создается автоматически, за 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:

Вывод

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

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

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

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

38 комментариев на «Урок 374 Как сделать автоматическое содержание статьи (оглавление) в WordPress»
  1. Alex

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

  2. Alex

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

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

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

      • Alex

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

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

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

      • Руслан

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

  3. Анжелика

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

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

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

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

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

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

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

  5. seoonly.ru
    https://seoonly.ru/

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

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

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

  6. Молодой Искатель
    http://vremenami.com/

    А я всегда вручную делаю – прописываю якоря и т. д. Это поначалу кажется сложным, но, сделав так в нескольких статьях, потом получается быстрее и не так накладно.

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

      Попробуйте через код и вы поймете насколько проще это все. 🙂

  7. Андрей Хвостов
    http://ingenerhvostov.ru

    Кодом интересно было бы вставить. А структура, оглавление видел на некоторых сайтах с высокой посещаемости.

  8. Евгений

    Где посты? Заболел что-ли ? Или творческий кризис?)

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

      Весна… Хорошая погода… 🙂

  9. Дмитрий Жилин
    https://biznessystem.ru

    Тоже этот код у Камаева видел, хотел поставить, но потом передумал – делаю руками.

    Смущает то, что при смене шаблона нужно будет все коды вносить заново. Ручное содержание в этом случае никак не пострадает. Да и ручками можно более гибко все настроить.

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

      1. Вы настолько часто меняете шаблон?
      2. 1 раз сделать CTRL+C CTRL+V, по-моему проще, чем все меню вручную делать.

  10. Юрий

    Ну это уже перебор, такой огород нагородил Тимур, почему не использовать ссылки-якори с тегами ul и li? Это намного проще, чем засорять код шаблона лишним мусором.
    Не соглашусь с вами, что якори расставлять сложно и долго.

    • Алексей Туманов

      Тут делается упор на то, что ты установил плагин и можешь больше никогда не думать про оглавление. А якоря нужно каждый раз расставлять.. А если статья ну очень объемная? Ужас..

  11. Артём
    https://vysokoff.ru/

    Код установил и сайт сломал, поэтому решил использовать вот этот плагин Table of Contents Plus, куча настроек и всё на автомате.

    • Алексей Туманов

      Ну видите, другие поставили и у них всё работает. Всё всегда работает, если руки из того места ростут 🙂

  12. alright
    http://intmoney.com.ua

    Скажу как частый читатель… С содержанием тема всегда смотрит более привлекательней, при чём даже подсознательно. Особенно удобно когда читаешь статью второй раз и нужно перейти на определённую её часть.

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

      Да, я тоже заметил, что когда нужно вернуться к старым статьям, найти что-то конкретное, по меню (содержание) очень удобно ориентироваться.

  13. Дмитрий

    Хрень! у меня весь код вылез в хедер.

    • IvYur

      Если вылез в шапку сайта, то значит что то упустили. Либо в вашем шаблоне немного код надо переделать.

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

      Проверьте внимательно, все ли правильно сделали. Потому что у меня на нескольких сайтах все ок.

  14. Алексей Туманов

    Оглавление – очень полезный инструмент для блога, особенно ддя авторов, которые публикуют относительно большой материал. Всё становится буквально по полочкам.

  15. ThunderBolt
    http://secretplanet.pp.ua

    А вот чтобы не вставлять каждый раз {contents} в статью, можно эту команду как-то вставить в single.php ?

  16. Алексей

    Петр, подскажи в чем может быть причина.
    Копирую код, вставляю в файл functions.php сохраняю и код весь вылезает вверху админки.

  17. Александр
    http://webpodrugi.ru

    Добрый день, нужно или нет добавлять к ссылкам содержания статьи тег rel=”nofollow”. Спасибо за ответ.

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

      Нет, не надо.

  18. Елена

    подскажите, пожалуйста, как можно скрыть маркированный список? то есть, чтобы заголовки оглавления были помечены только нумерованным списком.

    • Елена

      разобралась сама…добавила в стили: .contents li{ list-style-type:none;}. маркированный список теперь не выводится.

  19. Евгений
    https://amfus.ru

    Наиогромнейшее спасибо! Писал обьемную статью, и вовремя нее задумался о том как долго и нудно будет составлять оглавления якорями. Но теперь то все иначе. Спасибо!

  20. Айк
    https://1informer.com

    Давно искал подробную инструкцию. 😉 😉 😉
    Спасибо большое 8)

  21. Сергей

    Здравствуйте. Будьте добры, подскажите код, который позволял бы изменить цветовой фон оглавления с рамками вокруг него.
    Спасибо!

Добавьте свой комментарий
Добавить комментарий