Automatische Verzeichnisse

Beim Entwurf von Webseiten in der Art des ClubComputer-Blogs kommt es zu immer wiederkehrenden Tätigkeiten, die man gerne an ein Programm delegieren würde. Es sind dies

  • automatisch angelegte Inhaltsverzeichnisse,
  • automatisch angelegte Linklisten und
  • fest formatierte Metaangaben

Mit einem Javascript-Programm können diese Aufgaben ähnlich wie mit einem Plugin erledigt werden. Das JavaScript-Programm kann man an einem beliebigen Ort im Internet speichern und danach auf der Webseite einbinden. Da dieses Plugin für alle Beiträge verwendet werden soll, wird es nach einer Testphase fest in das Thema der Seite eingebaut.

Diese Seite ist sowohl die Vorstellung dieses Programms als auch gleichzeitig jene Seite, mit der das Programm getestet wurde, es sind also sowohl das automatisch erstellte Inhaltsverzeichnis als auch die automatisch erstellte Linkliste zu sehen.

Automatische Inhaltsverzeichnisse

Für WordPress gibt es das PlugIn „Easy Table of Content“ für die automatische Erstellung von Inhaltsverzeichnissen auf Seiten und Beiträgen. Aber in der kostenlosen Version kann das Inhaltsverzeichnis nicht ausreichend genau platziert werden, außerdem muss man die Formatierung an das Thema anpassen.

Daher wurde ein Javascript-Programm erstellt, das folgende Funktionen ausführt:

  • Suche aller Überschriften h1, h2, h3... mit der Klasse wp-block-heading. Es gibt nämlich auf der Seite – je nach Konfiguration – eventuell auch weitere Texte, die als Überschriften formatiert sind, die aber nicht im Inhaltsverzeichnis aufscheinen sollen, zum Beispiel die Angaben zum Autor oder Diskussionsbeträge.
  • Jede dieser Überschriften bekommt einen Anker vorangestellt, das ist eine Link-Referenz, die aus dem Inhaltsverzeichnis angesprungen werden kann, in der Form <a name='h123'>, wobei 123 eine fortlaufende Nummer ist.
  • Vor jede Überschrift wird ein Link mit einem grafischen Symbol eingefügt, mit dem man an den Anfang des Dokuments springen kann. <a href="#top"><span class='notranslate material-symbols-outlined'>arrow_drop_up</span></a>
  • Alle Überschriften werden in einer Liste zusammengefasst, wobei die Einrückung die jeweilige Ebene anzeigt. h1 keine Einrückung, h2 eine Einrückung usw.
  • Gleichzeit wird jede Zeile der Liste mit einem Link zum Namen der Überschrift versehen: <a href="#h123">...</a>
  • Diese Liste wird in einem Block „Vorformatiert“ unterhalb des Titels der Seite platziert-

Automatische Linkliste

Wenn wichtige Begriffe im Text erklärt werden sollen, werden sie meist mit einem Link zu dem betreffenden Dokument versehen. Damit kann der Leser bei Unklarheiten gleich weitere Informationen einholen. Meist sind das Links zu Wikipedia-Artikeln oder zu älteren Beiträge auf clubcomputer.at.

Bei längeren Beiträgen können schon einige solcher Links zusammenkommen, und wenn man diese Links sucht, muss man den ganzen Text durchsuchen. Daher wurde die Möglichkeit geschaffen, alle Links eines Beitrags am Ende in einer alphabetisch sortierten Liste zusammenfassend in einem eigenen Abschnitt anzugeben.

Die Arbeitsschritte zur Erstellung der Linkliste sind folgende:

  • Links werden nur gesammelt, wenn auf der Seite folgendes Konstrukt gefunden wird: <div id="pagelinks"><a href="http://links">Links</a></div>. Fehlt dieses Konstrukt, wird die Linkliste nicht angelegt.
  • Suchen aller Links auf einer Seite und Unterdrückung der Links zu Bildern
  • Jeder gefundene Link wird mit einem Linksymbol eingeleitet, das anzeigt, ob sich der Link im selben Web befindet oder ob es ein externer Link ist.
  • Alle Links werden in einem Array gespeichert, das nach dem Ende der Suche alphabetisch sortiert wird und danach doppelte Vorkommen eines Links entfernt werden.
  • Schließlich wird die formatierte Linkliste in den Abschnitt pagelinks eingefügt.
  • Damit man sieht, welche Zielseite der Link hat, wird der URL des Links in einer Klammer nach dem Text angehängt.

Der Abschnitt pagelinks und der darin enthaltene Link haben mehrere Funktionen:

  • Fehlt der Abschnitt, wird keine Linkliste erstellt (zum Beispiel bei kurzen Beiträgen)
  • Der enthaltene Link mit dem Text Link markiert die Stelle, bei der die Suche nach den Links beendet wird. In der Regel wird daher dieser Code am Ende eines Beitrags stehen, er kann aber auch – so wie in diesem Beitrag weiter vorne stehen, um besondere Linklisten oder Programmcode von der Suche auszuschließen.
  • In den Abschnitt pagelinks wird die Linkliste mit einer Überschrift eingefügt.
  • Der eigefügte Abschnitt bekommt die Überschrift „Links auf dieser Seite“

Formatierte Metaangaben

Bei dem fest eingestellten Thema für die Seite von ClubComputer wird das Titelbild für einen Beitrag mit voller Seitenbreite dem Beitrag vorangestellt. Wenn sich nun das Bild im Beitrag wiederholt, ist das riesige Bild störend. Es wurde daher auf ein Fünftel verkleinert. Weiters wurde der Titel der Seite und die Autorenangaben dem Bild vorangestellt.


Die folgenden Texte mit Überschriften dienen als Textobjekt für das Inhaltsverzeichnis dieser Seite. Die Darstellung der Programmcodes erfolgt erst nach der Linkliste. Die Lorem-Ipsum-Texte sind in einem wiederverwendbaren Block Lorem ipsum gespeichert, wobei das Wort cillum mit einem Link zu YouTube formatiert wurde. Da dieser Block mehrfach im Text verwendet wird, wird mit dem Text auch geprüft, ob mehrfache Vorkommen einer Adresse diese nur einmal in der Linkliste vorkommt.

Lorem ipsum 2

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Link zur Wikipedia

Lorem ipsum 2

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Link zu einem Beitrag von ClubComputer

Lorem ipsum 3

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Lorem ipsum 3

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Lorem ipsum 4

Lorem ipsum 2

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

— hier wird die automatisch erstellte Linkliste eingefügt —

Programmierung

Diese Ergänzung besteht aus zwei Dateien: navigation-post.css und navigation-port.js. Diese beiden Dateien müssen in jeder Seite eingefügt werden, die die automatischen Verzeichnisse enthalten soll. Für die farbcodierte Darstellung wird das Javascirpt-Programm PrismJs verwendet, siehe Syntax Highlighting.

Einfügung auf einer einzelnen Seite

Man erstellt einen HTML-Block am Beginn der Seite und fügt folgende Zeilen ein:

<link rel="stylesheet" href="https://buero.clubcomputer.at/navigation-post.css" />
<script src="https://buero.clubcomputer.at/navigation-post.js"></script>

Einfügung auf allen Seiten

Wenn alle Beiträge mit den automatischen Verzeichnissen versehen werden sollen, muss man sie im Header einer jeden Seite einfügen. Wenn man dabei das Thema nicht verändern will, kann man dazu ein Plugin bemühen. Mein Tipp ist das Plugin WPCode von Code Snippets. Die kostenlose Version genügt. Diese beiden Zeilen werden im Menüpunkt Dashboard -> Code Snippets -> Header & Footer eingefügt.

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=2.0, user-scalable=yes">
<script src="https://code.jquery.com/jquery-3.7.0.min.js" integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g=" crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,500,0,200" />
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>

Diese Einfügungen bewirken folgendes;

  • meta charset="UTF-8" legt (zur Sicherheit) den verwendeten Zeichensatz fest
  • meta name="viewport" definiert das Verhalten auf mobilen Geräten bei Verwendung von Elementen aus der bootstrap-Bibliothek
  • jquery-3.7.0.min.js wird nur benötigt, wenn das Thema nicht ebenfalls eine Version von jQuery zur Verfügung stellt
  • bootstrap.min.css und bootstrap.bundle.min.js sind die bootstrap-Bibliothek zur Gestaltung responsiver Webseiten
  • fonts.googleapis.com erlaubt die einfache Anwendung von Icons wie in der nachfolgenden Tabelle gezeigt wird
  • prism.min.js, prism.min.css und prism-autoloader.min.js sind für das Syntax-Highlighting zuständig.

Verwendung von Symbolen

In diesem Programm wird die Symbolbibliothek von Google benutzt.

SymbolCode
open_in_new<span class=’notranslate material-symbols-outlined‘>open_in_new</span>
open_in_new_down<span class=’notranslate material-symbols-outlined sym-rotate‘>open_in_new_down>
arrow_drop_up<span class=’notranslate material-symbols-outlined‘>arrow_drop_up<</span>

navigation-post.css

.entry-title { font-size: 20pt !important; margin-right: 10pt; margin-bottom: 0pt !important;}
.myLink { color:#084c08 !important; text-decoration: none !important; cursor:pointer; }
.sym-rotate { transform: scaleX(-1); cursor:pointer; /* rotate(90deg) */ }
.sym-style {color:#084c08; vertical-align:-17%; cursor:pointer; }
.post-meta {font-size: 10pt !important; margin-right: 10pt !important; margin-top: 0pt !important;}

navigation-post.js

const NAV_EXT = "<span class='notranslate material-symbols-outlined'>open_in_new</span>"
const NAV_INT = "<span class='notranslate material-symbols-outlined sym-rotate'>open_in_new_down</span>"
const NAV_UP = "<span class='notranslate material-symbols-outlined'>arrow_drop_up</span>"
const SHOW_NAV = true
const TXT_LINKS = "Links auf dieser Seite"
const INDENT = "   "

function GetChapters() {
	var s = ""
	var id1=1
	$.each($(":header"), function() {
		var outerHTML = this.outerHTML
		var level = outerHTML[2]*1
		if (outerHTML.includes("wp-block-heading")) {
			var Link = ""
			for (var j=0; j<level; j++) Link += INDENT
			Link += "<a class='myLink' href='#h"+id1+"'>" 
				+ (SHOW_NAV ? "<span class='sym-style'>" + NAV_INT + "</span> " : "")
				+ $(this).text() +"</a></br>"
			$(this).prepend("<a href='#top'>"+NAV_UP+"</a> ")
			$(this).prepend("<a name='h"+ id1 + "'>")
			id1++
			s += Link
		}
	});
	return "<pre>"+s+"</pre>"
}
function HighlightAndCollectLinks() {
	var arr_Links = []
	var end = false
	$.each($(".entry-content a"), function() {
		if (end) return
		if ($(this).text()=="Links") {
			end=true
			return
		}
		const symbol = ( SHOW_NAV 
			? ($(this).attr("data-type")=="page" ? NAV_INT : NAV_EXT)
			: "")
		$(this).addClass("myLink")
		if (symbol!="") $(this).prepend("<span class='sym-style'>" + symbol + "</span> ")
		
		var outerHTML = $(this).prop('outerHTML')
		if ( (outerHTML.includes(".png")) || (outerHTML.includes(".jpg")) 
			|| (outerHTML.includes(".PNG")) || (outerHTML.includes(".JPG"))
		)
			;
		else {
			var href = $(this).attr("href")
			href = href.replace("http://","").replace("https://","")
			href = href.replace("www.","")
			if (href.indexOf("/")>0)
				href = href.substring(0,href.indexOf("/"))
			if (href.includes("wikipedia.org"))
				outerHTML += " (Wikipedia)"
			else if (href.includes("youtube.com"))
				outerHTML += " (YouTube)"
			else if (href.includes("geschichtewiki.wien.gv.at"))
				outerHTML += " (Geschichtewiki Wien)"
			else 
				outerHTML += " ("+href+")"
			outerHTML.replace("sym-style","sym-style-dark")
			arr_Links.push(outerHTML)
		}
	})
	arr_Links.sort(function(a,b){
		var a1 = a.match(/>(.+)</)[0]
		var b1 = b.match(/>(.+)</)[0]
		if (a1>b1) return 1
		if (a1<b1) return -1
		return 0
	})
	var s = ""
	const LIST = false
	var Link_old = "" // Doppelte Links eliminieren
	for (var i=0; i<arr_Links.length; i++) {
		var Link = arr_Links[i]
		if (Link==Link_old) continue
		s += LIST ? "<li style='color:white'>"+Link+"</li>" : Link + "<br/>"
		Link_old = Link
	}
	if (s=="") 
		$("#pagelinks").html("")
	else 
		$("#pagelinks").html(
			"<h2 class='wp-block-heading'>"+TXT_LINKS+"</h2>"
			+ "<div>"
			+ (LIST ? "<ul style='color:white'>"+s+"</ul>" : "<pre>"+s+"</pre>" )
			+ "</div>"
		)
}
$(document).ready(function(){

	if ($("#pagelinks").html() !== undefined) Linklist = HighlightAndCollectLinks()

	$(GetChapters()).insertAfter("h1.wp-block-heading")

	var width = $("p.post-meta").next().prop("width")
	var height = $("p.post-meta").next().prop("height")
	$("p.post-meta").next().prop("width",width/5)
	$("p.post-meta").next().prop("height",height/5)
})

Erweiterung

Bei längeren Artikeln könnte es nützlich sein, wenn die Überschriften mit einer automatischen Nummerierung versehen werden. 1., 1.1, 1.3, 2. …

Zur Werkzeugleiste springen