Содержание (оглавление) статьи автоматически

Здравствуйте, в погоне за юзабилити, решил попробовать и сделать содержание для больших статей с подзаголовками (h2 и h3). Нашел материал realadmin.ru (ссылку даю не для рекламы, а потому, что автор помог с регулярными выражениями) на основе которого сделал плагин, который собирает из content заголовки h2 и h3 и на их основе делает содержание (оглавление) статьи.
1. создаю tv (туда записываю содержание) id-search-content-tv
2. костыль (есть tv с ссылкой на видео (ролики с ютуба)), находится не в content но добавляется в содержание
3. событие для срабатывания плагина OnDocFormSave
4. плагин который ищет и записывает в tv результат
<?php
$str = $resource->content;
        $str = preg_replace_callback('|<h([2,3]{1})>(.+)</h[2,3]{1}>|iU', function($matches){
	        static $id = 0;
        	$id++;
        	return '<h'.$matches[1].' id="'.$id.'">'.$matches[2].'</h'.$matches[1].'>';
        }, $str);
    $resource->set('content',$str);
    $str1 = $resource->content;
    $res = preg_match_all('|<h([2,3]{1})[\s]+id=[\s]*\"([^\"]*)\">(.+)</h[2,3]{1}>|iU',$str1, $result);
    if (!empty($res)){ $strres='<b>Содержание:</b></br>';} else { $strres=''; }

foreach ($result[3] as $key => $value) {
    $strres=$strres.'<a class="list-content" href="[[++site_url]][[~[[*id]]]]#'.$result[2][$key].'">'.$result[3][$key].'</a></br>';
                             
                            }
   $tv = $modx->getOption('TV',$scriptProperties,'video');
   $video = $resource->GetTVValue($tv); 
   
   if($video!='') {
      $strres=$strres.'<a class="list-content" href="[[++site_url]][[~[[*id]]]]#video">'.'Видео</a></br>';   
    }
  $tv = $modx->getOption('TV',$scriptProperties,'id-search-content-tv');
  $contentslist = $resource->GetTVValue($tv);                           
$resource->setTVValue($tv,$strres);
  
$resource->save();
Подскажите пожалуйста, как получить ссылку на конкретный ресурс не используя конструкцию [[++site_url]][[~[[*id]]]]. Получается что все ссылки записаны в tv в такой форме [[++site_url]][[~[[*id]]]]#якорь и становятся обычными ссылками только после обработки их modx. Хотелось бы записывать в tv уже реальные ссылки и не заставлять modx каждый раз при открытии страницы их обрабатывать.
Борис И
Борис И
07 декабря 2014, 09:26
modx.pro
4 940

Комментарии: 10

wld
wld
08 декабря 2014, 01:12
    Борис И
    08 декабря 2014, 21:42
    Все сделал.
    Установил
    <base href="[[++base_url]]" />
    Настройках системы — core — Сайт
    Схема URL (link_tag_scheme) установить значение abs

    В коде ссылка
    <a href="#test">Ссылка</a>

    При наведении
    site.ru/#test
    а должна быть
    site.ru/page.html#test
      wld
      wld
      09 декабря 2014, 07:58
      <base href="[[++base_url]]" />
      — не надо указывать

      и ссылка должна быть:
      <a href="#test">Ссылка</a>
Борис И
27 ноября 2015, 00:00
<?php
$str = $resource->content;
        $str = preg_replace_callback('|<h([2,3]{1})>(.+)</h[2,3]{1}>|iU', function($matches){
	        static $id = 0;
        	$id++;
        	return '<h'.$matches[1].' id="'.$id.'">'.$matches[2].'</h'.$matches[1].'>';
        }, $str);
    $resource->set('content',$str);
    $str1 = $resource->content;
    $res = preg_match_all('|<h([2,3]{1})[\s]+id=[\s]*\"([^\"]*)\">(.+)</h[2,3]{1}>|iU',$str1, $result);
    if (!empty($res)){ $strres='<b>Содержание:</b></br>';} else { $strres=''; }

foreach ($result[3] as $key => $value) {
    $strres=$strres.'<a class="list-content" href="[[*uri]]#'.$result[2][$key].'">'.$result[3][$key].'</a></br>';
                             
                            }
   $tv = $modx->getOption('TV',$scriptProperties,'video');
   $video = $resource->GetTVValue($tv); 
   
   if($video!='') {
      $strres=$strres.'<a class="list-content" href="[[*uri]]#video">'.'Видео</a></br>';   
    }
  $tv = $modx->getOption('TV',$scriptProperties,'id-search-content-tv');
  $contentslist = $resource->GetTVValue($tv);                           
$resource->setTVValue($tv,$strres);
  
$resource->save();
    Борис И
    08 августа 2017, 12:41
    Задали вопрос в личку:
    не могу поменять в самом плагине названия тегов: 'Содержание:' После внесения изменений, плагин все равно применяет все старое,… При этом кеш чищу
    .
    В личку ответить не получается, отвечаю здесь: В тексте плагина поменяйте «Содержание» на что угодно. Для того чтобы в «старых» ресурсах поменялось содержание их нужно пересохранить, для того, чтобы сработал плагин и записал новое значение в tv. Чистка кеша здесь не поможет.
    Принцип работы:
    1. при сохранении документа (событие OnDocFormSave) плагин срабатывает
    2. ищет теги h2,h3 в content и записывает
    3. записывет результат в tv с именем id-search-content-tv

    Василий давно уже написал сниппет, который создает содержание modx.pro/solutions/4384-automatic-generation-of-table-of-contents-page/.
      brioni
      19 марта 2019, 18:05
      У вас компонент Василия не выдает на странице:
      Notice: Undefined offset: 2 in /home/site.ru/public_html/core/components/jevix/model/jevix/jevix.class.php on line 135
      Notice: Undefined offset: 3 in /home/site.ru/public_html/core/components/jevix/model/jevix/jevix.class.php on line 135
      Если да, то как это убрать?
        Борис И
        19 марта 2019, 19:10
        Нет, не было такого. И каким образом снипет для оглавления завязан с jevix, ума не приложу
        Саня
        09 марта 2021, 20:51
        отлично, работает. вызов текста помещаем вместо штатного в шаблон. А список ссылок вызывается как из шаблона, так и из поля ресурса.
        Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
        10