Сниппет для создания оглавления статьи

Сниппет для создания оглавления статьи

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

Представленный здесь сниппет обрабатывает содержимое поля и на основе заголовков H2 создает оглавление с сылками на эти самые заголовки. Самим заголовкам добавляется уникальный id.

Код сниппета

Назовем его TextLink.

<?php
$dom = new DOMDocument();
$input = mb_convert_encoding($input, 'HTML-ENTITIES', 'utf-8');
$dom->loadHTML($input);
$xpath = new DOMXPath($dom);
$h2 = $xpath->query('//h2');
if ($h2->length == 0) return ''; // Проверка на количество
$url = $modx->makeUrl($modx->resource->get('id'));
$i = 0;
$out = '';
if ($h2) {
    $out .= '<div class="subtitle">Оглавление</div>';
    $out .= '<ol class="ogl-list">';
    foreach ($h2 as $h) {
    $i++;
    $out .= '<li class="ogl-item"><a href="'.$url.'/#toh'.$i.'" title="'.$h->textContent.'">'.$h->textContent.'</a></li>';
    $nodePre = $h2->item($i-1);
    $nodePre->setAttribute("id", 'toh'.$i);
    }
    $out .= '</ol>';
}
$out .= $dom->saveHTML();
return $out;

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

if ($h2->length < 3) return '';

Тогда оглавление будет более к месту.

Использование

Используется вместе с элементом шаблона, плейсхолдером, обычно это [[*content]], следующим образом:

[[*content:TextLink]]
Сказать $пасибо

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

Комментарии ()