Оглавление
Генерация оглавления с помощью регулярного выражения
Для поиска всех заголовков в статье, воспользуемся функцией
preg_match_all()
и регулярным выражением вида '/<h([2-5])>\n*(.*?)\n*<\/h[2-5]>/'
. Так же нам потребуется передавать в функцию генерации оглавления URL детальной странице, на которой это оглавление будет показываться. Это нужно для правильной работы якорей.
<?php
/**
* Получитьь оглавление статьи
* @param $input - html статьи
* @param $detailPageUrl
* @return string|void
*/
function getTableOfContetn($input, $detailPageUrl = ''){
// Если в тексте нет заголовков от h2 до h5 - выходим
if (!preg_match_all('/<h([2-5])>\n*(.*?)\n*<\/h[2-5]>/', $input, $headers)) {
return;
}
// Если заголовков меньше 2х - не выводим оглавление
if (is_countable($headers[0]) && count($headers[0]) < 2) {
return;
}
$base = $detailPageUrl;
$from = $to = [];
$depth = 0;
$start = null;
// Генерация оглавления
$contents = '<div class="page-content-wrapper"><div class="page-content-header">Оглавление</div><ul id="page-contents">';
foreach ($headers[2] as $i => $header) {
$header = preg_replace('#\s+#', ' ', trim(rtrim($header, ':!.?;')));
$anchor = 'header_' . $i;
$header = "<a href=\"{$base}#{$anchor}\">{$header}</a>";
//Формируем вложенность списка
if ($depth > 0) {
if ($headers[1][$i] > $depth) {
while ($headers[1][$i] > $depth) {
$contents .= '<ul>';
$depth ++;
}
} elseif ($headers[1][$i] < $depth) {
while ($headers[1][$i] < $depth) {
$contents .= '</ul>';
$depth --;
}
}
}
$depth = $headers[1][$i];
if ($start === null) {
$start = $depth;
}
$contents .= '<li>' . $header . '</li>';
$from[$i] = $headers[0][$i];
$to[$i] = '<a id="' . $anchor . '" name="' . $anchor . '" class="page-contents-link"></a>' . $headers[0][$i];
}
// Закрытие всех открытых списков
for ($i = 0; $i <= ($depth - $start); $i ++) {
$contents .= "</ul>";
}
// Добавление якорей к заголовкам
$input = str_replace($from, $to, $input);
$contents .= '</div><!-- END page-content-wrapper-->';
return $contents . $input;
}
Теперь, можно обработать тело статьи, получить html код оглавления и вывести в удобном нам месте (обычно после заголовка
h1
).Пример использования
На примере 1С Битрикс. Файл result_modifier.php шаблона компонента, вызываем нашу функцию передавая в качестве основного аргумента DETAIL_TEXT массива $arResult и пересохраняем DETAIL_TEXT.//Файл result_modifier.php шаблона вашего компонента детальной страницы новости
$arResult['DETAIL_TEXT'] = getTableOfContetn($arResult['DETAIL_TEXT'], '');
Хотя конечно вы можете использовать для любого сайта, главное передать сформированную html страницу со всем заголовками.