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

Здравствуйте, в погоне за юзабилити, решил попробовать и сделать содержание для больших статей с подзаголовками (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
2
3 061
-1

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

wld
wld
08 декабря 2014, 01:12
0
    Борис И
    08 декабря 2014, 21:42
    0
    Все сделал.
    Установил
    <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
      0
      <base href="[[++base_url]]" />
      — не надо указывать

      и ссылка должна быть:
      <a href="#test">Ссылка</a>
        Борис И
        09 декабря 2014, 10:27
        0
        Спасибо, помогло.
    Борис И
    27 ноября 2015, 00:00
    0
    <?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
      0
      Задали вопрос в личку:
      не могу поменять в самом плагине названия тегов: 'Содержание:' После внесения изменений, плагин все равно применяет все старое,… При этом кеш чищу
      .
      В личку ответить не получается, отвечаю здесь: В тексте плагина поменяйте «Содержание» на что угодно. Для того чтобы в «старых» ресурсах поменялось содержание их нужно пересохранить, для того, чтобы сработал плагин и записал новое значение в tv. Чистка кеша здесь не поможет.
      Принцип работы:
      1. при сохранении документа (событие OnDocFormSave) плагин срабатывает
      2. ищет теги h2,h3 в content и записывает
      3. записывет результат в tv с именем id-search-content-tv

      Василий давно уже написал сниппет, который создает содержание modx.pro/solutions/4384-automatic-generation-of-table-of-contents-page/.
        Yar
        Yar
        19 марта 2019, 18:05
        0
        У вас компонент Василия не выдает на странице:
        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
          0
          Нет, не было такого. И каким образом снипет для оглавления завязан с jevix, ума не приложу
        Yar
        Yar
        28 февраля 2019, 17:03
        0
          Саня
          09 марта 2021, 20:51
          0
          отлично, работает. вызов текста помещаем вместо штатного в шаблон. А список ссылок вызывается как из шаблона, так и из поля ресурса.
          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
          10