Марафон v2.0

Урок 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:

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

Вывод

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

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

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

Новый марафон 2.0 от WPnew
С уважением, Пётр Александров.
Подпишитесь на бесплатные уроки

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Руслан

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

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

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

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

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

Анжелика

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

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

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

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

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

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

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

seoonly.ru http://seoonly.ru/

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

alright http://intmoney.com.ua

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

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

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

Дмитрий

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

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

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

IvYur http://kuponam.ru

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

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

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

ThunderBolt http://secretplanet.pp.ua

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

Алексей

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

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

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

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

Нет, не надо.

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

decom_2016-05-31_172333_574db3dab5fb9.jpgdecom_2016-05-31_172333_574db3dab5fb9.jpg

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

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

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

Айк https://1informer.com

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

Наверх Рейтинг@Mail.ru