Проставновка якорей в тегах <H

Приветствую!
Столкнулся с задачей автоматической генерации оглавления к статье, для удобства навигации. Хотел было решить проблему js, но отказался от этой затеи, ввиду — «зачем обвешиваться лишним?». Готового решения не нашел, но нашел сниппет, немного модернизировал его, но осталась проблема с тем, что он не вставляет якоря в заголовки, с которых формирует оглавление.

Код сниппета:
<?php
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);

// Parameters/options
// What should the snippet output? Either 'toc' or 'content'
$options = isset($options) && ($options == 'content' || $options == 'toc') ? $options : 'toc';

    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;
    }

    preg_match_all( '/<h([2-6])(.*)>([^<]+)<\/h[2-6]>/i', $input, $matches, PREG_SET_ORDER );
 
    global $anchors;
 
    $anchors = array();
    $toc     = '<div id="toc_container" class="no_bullets"><p class="toc_title">Содержание</p><!--noindex--><ul class="toc_list">'."\n";
    $i       = 0;
    
    // Content should be MODX input
    $content = $input;
 
    foreach ( $matches as $heading ) {
 
        if ($i == 0)
            $startlvl = $heading[1];
            $lvl        = $heading[1];
 
        $ret = preg_match( '/id=[\'|"](.*)?[\'|"]/i', stripslashes($heading[2]), $anchor );
        if ( $ret && $anchor[1] != '' ) {
            $anchor = stripslashes( $anchor[1] );
            $add_id = false;
        } else {
            $anchor = preg_replace( '/\s+/', '1', preg_replace('/[^a-z\s]/', '', strtolower( $heading[3] ) ) );
            $add_id = true;
        }
 
        if ( !in_array( $anchor, $anchors ) ) {
            $anchors[] = $anchor;
        } else {
            $orig_anchor = $anchor;
            $i = 2;
            while ( in_array( $anchor, $anchors ) ) {
                $anchor = $i;
                $i++;
            }
            $anchors[] = $anchor;
            $anchor = transl4url( $title );
        }

        if ( $add_id ) {
            // This section is where you can mess with the 'to home arrow and remove it entirely if you don't want it
            // It is in the <span><a href="#.... section on the next line. Add a class to the span if you want to style it in your CSS
            $content = substr_replace( $content, '<h'.$lvl.' id="'.transl4url( $title ).'"'.$heading[2].'>'.$heading[3].'>', strpos( $content, $heading[0] ), strlen( $heading[0] ) );
        }
 
        $ret = preg_match( '/title=[\'|"](.*)?[\'|"]/i', stripslashes( $heading[2] ), $title );
        if ( $ret && $title[1] != '' )
            $title = stripslashes( $title[1] );
        else    
            $title = $heading[3];
        $title      = trim( strip_tags( $title ) );
 
        if ($i > 0) {
            if ($prevlvl < $lvl) {
                $toc .= "\n"."<ul>"."\n";
            } else if ($prevlvl > $lvl) {
                $toc .= '</li>'."\n";
                while ($prevlvl > $lvl) {
                    $toc .= "</ul>"."\n".'</li>'."\n";
                    $prevlvl--;
                }
            } else {
                $toc .= '</li>'."\n";
            }
        }
 
        $j = 0;
        $anchor = transl4url( $title );
        $toc .= '<li><a href="#'.$anchor.'">'.$title.'</a>';
        $prevlvl = $lvl;
 
        $i++;
    }
 
    unset( $anchors );
 
    while ( $lvl > $startlvl ) {
        $toc .= "\n</ul>";
        $lvl--;
    }
 
    $toc .= '</li>'."\n";
    $toc .= '</ul><!--/noindex--></div>'."\n";
    
// Finally output the content
if ($options == 'content') {
	echo $content;
} else {
	echo $toc;
}
вызываю его — [[*content:TOCх=toc]]
sml.bellagio
20 марта 2017, 09:02
modx.pro
608
0

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

Роман
09 февраля 2021, 23:02
0
Удалось решить вопрос? Тоже встал такой вопрос, очень интересно.
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    1