WBCE CMS Forum

WBCE CMS – Way Better Content Editing.

You are not logged in.

#1 23.08.2023 17:43:15

grimblefritz
Member

Updated CreateToc droplet

I don't git and never will - so I'll just post this here. If someone knows how to "make it official" and available for installs by all, please do.

Changes are shown in the initial comments, and they'll display in the droplets help. They are:  numdrop, topskip, debug.

The debug option is not in the comment docs. Include debug=true and it will show how it has interpreted all the options. In a very ugly, not for production way!

Also, I updated the code to improve handling of the options in general.

//:Creates a Table of Contents from Headings (h1 - h6)
//:Create a Table of Contents by extracting all headings from a page.

/* 
[[CreateTox?skip=#]]
Skip X headings, where X is a number (example: skip=1 skips the first heading)
 
[[CreateToc?number=true]]
Number the Toc items
 
[[CreateToc?numdrop=#]]
Drop X levels from numbering
 
[[CreateToc?float=right]]
Let the Toc float right
 
[[CreateToc?toplink=false]]
Suppress addition of "back to top" links
 
[[CreateToc?topskip=#]]
Skip X back to top links
 
You may style the Toc by CSS class "toc".
*/

$toc     = array();
$output  = NULL;
$float   = ( isset($float)  ? $float   : ''    ); // 'right' is only recognized option
$number  = ( isset($number) ? $number  : false ); // number the headings in Toc
$numdrop = ( isset($numdrop)? $numdrop : 0     ); // drop X segments from heading numbers
$skip    = ( isset($skip)   ? $skip    : 0     ); // skip X headings
$toplink = ( isset($toplink)? $toplink : true  ); // add 'back to top' links
$topskip = ( isset($topskip)? $topskip : 0     ); // skip X 'back to top' links
$debug   = ( isset($debug)  ? $debug   : false ); // show option values on page
$number  = ( filter_var($number,  FILTER_VALIDATE_BOOLEAN) ? true : false) ;   // ensure we get a real true/false
$toplink = ( filter_var($toplink, FILTER_VALIDATE_BOOLEAN) ? true : false) ;   // ensure we get a real true/false
$debug   = ( filter_var($debug,   FILTER_VALIDATE_BOOLEAN) ? true : false) ;   // ensure we get a real true/false
$numdrop = intval($numdrop);   // ensure weird strings are zero (0)
$skip    = intval($skip);      // ensure weird strings are zero (0)
$topskip = intval($topskip);   // ensure weird strings are zero (0)
$current = array( '1' => 0 );
$last    = 1;
$dump    = array();
$strings = array(
  'DE' => 'Auf dieser Seite...',
  'EN' => 'On this page…',
);
$btt     = array(
  'DE' => 'Zurück zum Anfang',
  'EN' => 'Back to top ↑',
);

preg_match_all( '#<h([1-6]).*>([^<].+)</h[1-6]>#i', $wb_page_data, $matches, PREG_PATTERN_ORDER );

if ( count($matches) ) {
    $found = 0;
    foreach( $matches[2] as $i => $text ) {
        $found++;
        if ( $skip && $found <= $skip ) {
            continue;
        }
        $level = $matches[1][$i]; // current level
        if ( $number == 'true' ) {
            if ( $level < $last ) {
                for( $n=($level+1); $n<=$last; $n++ ) {
                    unset($current[$n]);
                }
            }
            if ( isset( $current[$level] ) ) {
                $current[$level]++;
            }
            else {
                $current[$level]=1;
            }
            $prefix = array();
            for( $m=1; $m<=$level; $m++ ) {
                if ( ! isset($current[$m] ) ) {
                    $current[$m] = 1;
                }
                $prefix[] = $current[$m];
            }
            $text = implode('.', array_slice($prefix,$numdrop)) . ' &nbsp;' . $text;
        }
        $last  = $level;
        $toc[] = '<span style="margin-left:'
               . ( 10 * ( $level - 1 ) )
               . 'px;"><a href="#toc'.$i.'">'.$text.'</a></span>';
        $wb_page_data = str_replace(
            $matches[0][$i],
            ( ( $i > $topskip && $toplink ) ? '<br /><a href="#toc">'.(isset($btt[LANGUAGE]) ? $btt[LANGUAGE] : $btt['EN']).'</a><br />' : '' ).
            '<a name="toc'.$i.'"> </a>' . $matches[0][$i],
            $wb_page_data
        );
    }

    $output = '<div class="toc" style="margin:5px;padding:5px;border:1px solid #ccc;';
    if ( strtolower($float) == 'right' ) {
        $output .= ' float:right;';
    }
    $output .= '">'
            . '<a name="toc" style="font-weight:bold;">'
            . ( isset($strings[LANGUAGE]) ? $strings[LANGUAGE] : $strings['EN'] )
            . '</a><br /><br />'
            .  implode( '<br />', $toc )
            .  '</div>';
}

// this removes double 'to top' links if CreateToc is called more than once
//<a href="#toc">Back to top</a><br /><a name="toc1"> </a><br /><a href="#toc">Back to top</a><br /><a name="toc1"> </a>
$regex = '('.preg_replace('~\s~','\\s*',preg_quote('<br /><a href="#toc">Back to top</a><br /><a name="toc','~').'\d+'.preg_quote('"> </a>','~')).'){2,}';
$wb_page_data = preg_replace(
    '~'.$regex.'~',
    '$1',
    $wb_page_data
);

if ( $debug ) {
$output .= "<pre>
float   = $float
skip    = $skip
number  = $number
numdrop = $numdrop
toplink = $toplink
topskip = $topskip
</pre>\n";
}

return $output;

Last edited by florian (23.08.2023 19:50:13)

Offline

Liked by:

florian, bernd

#2 23.08.2023 20:08:47

florian
Administrator

Re: Updated CreateToc droplet

Great! Thank you very much, works like a charme.
I've updated the droplet download in the addon repository (and added a ToC with this very droplet there  thumb_up ).
https://addons.wbce.org/pages/droplets.php#toc5


Code allein macht nicht glücklich. Jetzt spenden!

Offline

#3 24.08.2023 00:30:52

grimblefritz
Member

Re: Updated CreateToc droplet

You're welcome and thank you for handling it.

Me (75%) and ChatGPT (25%) are happy to give a little back smile

Offline

Board footer

up