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

Содержание статьи в WordPress

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/wpnew20/functions.php on line 270

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

Содержание статьиДанное оглавление имеет массу плюсов:

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

Содержание статьи WordPress

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

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

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

Код автоматического содержания статьи

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

Оглавление статьи

Вывод

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

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

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

Подпишитесь на бесплатные уроки
Нажав на кнопку «Подписаться» вы принимаете
соглашение на обработку персональных данных .

Понравился урок? Вы не хотите пропускать новые бесплатные уроки по созданию, раскрутке и монетизации блога? Тогда подпишитесь на RSS или на электронный ящик в форме выше и получайте новые уроки мгновенно! Также можете следить за мной в Twitter.

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

Ваш адрес 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://wpnew.ru

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

      • Alex

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

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

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

      • Руслан

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

  3. Анжелика

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. Евгений

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

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

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

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

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

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

    • Пётр АлександровАвтор статьи
      https://wpnew.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://wpnew.ru

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

  13. Дмитрий

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

    • IvYur

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

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

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

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

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

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

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

  16. Алексей

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

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

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

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

      Нет, не надо.

  18. Елена

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

    • Елена

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

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

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

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

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

  21. Сергей

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