Smarty Plugin Table of Content

Dieses kleine Smarty-Plugin erzeugt ein automatisches Inhaltsverzeichnis am Beginn des Beitrags.

Inhalt

Smarty Plugin Konventionen

Zu Beginn ein paar Worte zur Namenskonvention der Smarty-Plugins. In diesem Fall handelt es sich um eine Funktion und das Plugin muss mit smarty_function... eingeleitet werden, danach folgt der Name der Funktion, hier toc. Dieser Name kann dann auch im Template mit {toc} eingesetzt werden, um das Plugin auszulösen.

Ich empfehle den Dateinamen immer vollständig klein zu schreiben, das macht das spätere Templating und den Umgang mit den Template-Tokens erheblich einfacher.

Der Code

Die Signatur ist für den Typ der Funktion fest vorgegeben. Im Anschluss daran, holt das Plugin den Content aus der Template-Variablen mit $template->getTemplateVars() und zerlegt diesen mit explode() in ein Array. Das Array ist anhand der Zeilenumbrüche im Beitragstext getrennt, liegt also Zeile für Zeile vor.

function smarty_function_toc($params, Smarty_Internal_Template $template)
{
    $content = explode("\n", $template->getTemplateVars('content'));

    if(preg_match('(<h[1-6])', $template->getTemplateVars('content')))
    {
        $html='<ul class="toc col-sm-5 py-4">';
        foreach($content as $value)
        {
            if (preg_match('(<h[1-6].id=)', $value) && preg_match('(</h[1-6]>)', $value))
            {
                $link    = explode('"',explode('id="', $value)[1])[0];
                $title   = str_replace(array('-','_'),' ',$link);
                $kapitel = strip_tags($value);

                $html .= '<li class="fs-6">';
                $html .= '<a href="#'.$link.'" title="'.$title.'">'.$kapitel.'</a>';
                $html .= '</li>';
            } else {
                if (preg_match('(<h[1-6])', $value) && preg_match('(</h[1-6]>)', $value))
                {
                    $html .= '<li class="fs-6">';
                    $html .= strip_tags($value);
                    $html .= '</li>';
                }
            }
        }
        $html .= '</ul>';
        return $html;
    }
}

Code

Mit preg_match() wird der gesamte Content auf die Existenz einer Überschrift untersucht, denn sind keine Überschriften vorhanden, muss auch kein Inhaltsverzeichnis angelegt werden.

Im nächsten Schritt sucht ein weiterer preg_match() auf das Vorhandensein von Überschriften der Stufen H1 bis H6, zu denen es eine Markdown-ID gibt. Die if-Struktur unterscheidet hierbei in Überschriften mit ID und ohne ID, wenn keine ID zu einem Titel angegeben wurde, dann wird zwar ein Index angezeigt, es gibt dann aber keine anklickbaren Links.

Der preg_match() prüft auf ein öffnendes und eine schliessendes H-Tag, ist dies der Fall, wird der Text und die ID mittels explode() extrahiert.

Eine Überschrift im Text anlegen

in Form von:

<H3 id="das-ist-ueberschrift-3">Titel</H3>

Code

gibt. Die ID wird im ursprünglichen MD-Beitragstext durch den Autor und Redakteur in form von:

### Titel ### {#das-ist-ueberschrift-3}

Code

erzeugt.

Das Plugin ist allgemeingültig und kann an jedes andere Content Management System angepasst werden, um dort ein automatisches Inhaltsverzeichnis aufzubauen. Die Variable $template->getTemplateVars('content') muss dabei durch den realen HTML-Inhalt ersetzt werden.


Oliver Lohse
2024-02-22
Smarty Plugin Table of Content
post
4