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 секунды. Не нужно тратить время. Интересно? Еще бы. Читаем далее.
Необходимый код для составления содержания
Вручную создавать подобное содержание очень долгое занятие, ведь нужно:
- Понаставить «якори».
- Вручную задать название каждому пункту.
- Подбирать правильные ссылки с якорями.
Из-за сложностей и неудобств, я не использовал данный метод. Только в исключительных случаях. Для реализации автоматического оглавления, мне помог код, который я взял на одном классном блоге 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="&lt;style&gt;" title="&lt;style&gt;" />
' : '';
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:
Вывод
Вот так просто все это внедрить себе на блог. Спасибо Тимуру Камаеву за такой классный код. Если вы вдруг захотите добавить какие-то дополнительные «плюшки», перейдите по ссылке, там есть интересные дополнения, которые могут кому-то пригодятся.
Я же очень хочу, чтобы вы использовали данный код хотя бы для того, чтобы Ваши статьи получались более структурированными и Вы «рвали» ТОП со своими классными статьями. Всего вам хорошего!
И спасибо за ретвит. 🙂





Спасибо ВПкаме))
ВПкама, ВПнью, ахаххаха) Да, спасибо Тимуру.
Петр, спасибо, что объяснили! Как всегда, все доступно и понятно!
Рад был помочь )
Делала содержание статьи вручную, довольно неудобно, с кодом, конечно проще. Петр, подскажите, как правильно ставить рекламные блоки РСЯ на сайт, каким инструментом или плагином пользоваться. Пробовала добавить в сайтбар через виджет, блок не отображается. Подскажите, если можно. И еще, у Вас не работает поиск по сайту, пыталась поискать информацию, не загружаются результаты.
Вставляйте сразу в файл темы — sidebar.php, single.php и прочее
1. А вы не боитесь использовать чужой код? Или так хорошо разбираетесь в php, что сразу видите какие-нибудь «закладки»? Я не про данный код, а вообще.
2. Вы используете «дочернюю» тему WP или вообще «самописную»? Неплохо было бы упомянуть про влияние обновления тем на изменения в файлах function.php и style.css!
P.S. у автора уже версия 2.7.1 от 14.04.15
1. Честно, боюсь, поэтому беру только у проверенных авторов.
2. Самописная.
P.s. Да, плагин регулярно обновляется. Весь необходимый функционал есть и в этом коде этой версии. В обновлениях разные «плюшки», которые рядовому пользователю практически не нужны.
Плагин? Не являюсь знатоком WP, как вы, но плагины, вроде бы, не в файле function.php должны быть, хотя функция add_filter намекает на сходство с плагинами 🙂
Ой, оговорился. Код. Не плагин.
Есть плагин с похожим функционалом, делает то же самое что и скрипт в статье, называется toc+
какие-то проблемы со временем в комментариях: получается, что на мое сообщение в 20:23 вы мне ответили в 20:12!