Купить рекламу на WPnew.ru
Автопилот для контекста

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

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

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

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

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

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

Такой e-mail уже зарегистрирован. Воспользуйтесь формой входа или введите другой.

Вы ввели некорректные логин или пароль

Извините, для комментирования необходимо войти.

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

38 комментариев

по хронологии
по рейтингу сначала новые по хронологии

1. А вы не боитесь использовать чужой код? Или так хорошо разбираетесь в php, что сразу видите какие-нибудь "закладки"? Я не про данный код, а вообще.

2. Вы используете "дочернюю" тему WP или вообще "самописную"? Неплохо было бы упомянуть про влияние обновления тем на изменения в файлах function.php и style.css!

P.S. у автора уже версия 2.7.1 от 14.04.15

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

1. Честно, боюсь, поэтому беру только у проверенных авторов.

2. Самописная.

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

Руслан

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

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

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

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

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

Анжелика

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

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

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

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

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

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

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

seoonly.ru http://seoonly.ru/

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

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

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

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

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

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

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

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

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

Евгений http://goo.gl/PQJ1do

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

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

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

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

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

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

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

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

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

Не соглашусь с вами, что якори расставлять сложно и долго.

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

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

Артём http://vysokoff.ru/

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

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

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

alright http://intmoney.com.ua

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

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

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

Дмитрий

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

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

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

IvYur http://kuponam.ru

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

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

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

ThunderBolt http://secretplanet.pp.ua

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

Алексей

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

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

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

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

Нет, не надо.

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

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

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

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

Айк https://1informer.com

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

Сергей

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

Наверх