WvdS.DokuWiki.AcMenu Plugin

Plugin: wvdsacmenu
Version: 1.4.0
Namespace: lib/plugins/wvdsacmenu/
Basis: AcMenu von Torpedo
Erweiterungen: Wolfgang van der Stille zeljko.petrusic@outlook.de
Lizenz: GPL 2


Definition

Das wvdsacmenu Plugin zeigt ein Akkordeon-Menü für Namespaces und Seiten. Es erweitert das Original-AcMenu um Wiki-Syntax, dynamische Namespace-Erkennung, Lazy Loading, ACL-aware Navigation und mehrsprachige Unterstützung.


Motivation

Das Problem mit Standard-Navigation

DokuWiki-Standardnavigation und das Original-AcMenu haben in Enterprise-Umgebungen mehrere Einschränkungen:

  • ACL-Blindheit: Wenn sneaky_index=1 aktiv ist, werden geschützte Ordner komplett ausgeblendet - auch wenn tiefer öffentliche Inhalte existieren
  • Keine Lazy Loading: Bei großen Dokumentationsstrukturen (100+ Seiten) wird die Sidebar langsam und unübersichtlich
  • Sprach-Isolation: Mehrsprachige Wikis benötigen manuelle Konfiguration pro Namespace
  • Keine Template-Integration: Die Sidebar-Auswahl ist statisch und kennt keine Namespace-Hierarchie

Beispiel: Öffentlicher Pfad in geschütztem Bereich

ACL-Konfiguration:
  de:int:*                @ALL  0   (gesperrt)
  de:int:vsce:fpc:p:*     @ALL  1   (öffentlich)

Standard-AcMenu Ergebnis:
  📂 de
     📁 pub          ← sichtbar
     (vsce fehlt!)   ← PROBLEM: gesamter Pfad ist versteckt

wvdsacmenu Ergebnis:
  📂 de
     📁 pub
     📂 int
        📂 vsce      ← partial (kein Link)
           📂 fpc    ← partial (kein Link)
              📁 p   ← sichtbar und navigierbar

Der Benutzer sieht den Pfad zu öffentlichen Inhalten, auch wenn dazwischenliegende Ordner nicht direkt lesbar sind.


Ziele

Enterprise-Navigation

wvdsacmenu wurde für komplexe Dokumentationsstrukturen mit differenzierten Zugriffsrechten entwickelt:

Anforderung Lösung
Große Strukturen Lazy Loading (dynamic=„N“)
Differenzierte ACLs Partial Namespaces, ACL-aware „Go Up“
Mehrsprachigkeit Automatische Sprach-Erkennung, ns=„auto“
Performance Server-seitige Cookie-Wiederherstellung
UX Total Commander Modus, FontAwesome Icons

Vergleich mit Original-AcMenu

Feature Original AcMenu wvdsacmenu
ACL-Unterstützung Nur read/hide Partial Namespaces, tiefe Pfade
Lazy Loading Nein Ja (AJAX)
Cookie-Wiederherstellung Nur Client Server + Client
Mehrsprachigkeit Manuell Automatisch (ns=„auto“)
Icons Nein FontAwesome
Template-Integration Nein Namespace-aware Sidebar
„Go Up“ Navigation Nein ACL-basiert
Unsichtbarer Titel Nein {{wvds:title>...}}

Design-Prinzipien

  1. Minimal Disclosure: Zeige nur was der Benutzer sehen darf, aber zeige den Pfad dorthin
  2. Progressive Loading: Lade initial wenig, erweitere bei Bedarf
  3. Stateless Recovery: Cookie-Zustand wird Server-seitig wiederhergestellt (kein Flackern)
  4. Deep Integration: Das Plugin arbeitet eng mit Template und ACL-System zusammen

Anwendungsfälle

  • Namespace-Navigation - Automatisches Menü für Dokumentationsstruktur
  • Mehrsprachige Wikis - Separate Menüs pro Sprach-Namespace
  • Projektdokumentation - Hierarchische Navigation in Unter-Namespaces
  • Sidebar-Integration - Kompakte Navigation in der Seitenleiste
  • Performance-Optimierung - Lazy Loading für große Menüstrukturen
  • ACL-aware Navigation - Zeigt Ordner auch wenn nur Teile lesbar sind

Syntax

{{wvds:acmenu>}}
{{wvds:acmenu>ns=namespace}}
{{wvds:acmenu>dynamic=N}}
{{wvds:acmenu>startns=current|icons=fa}}

Syntax-Änderung (v1.4): Das > nach wvds:acmenu ist pflicht, um Konflikte mit DokuWikis Media-Syntax zu vermeiden. Parameter werden mit | getrennt.

Titel-Syntax (Unsichtbarer Titel)

{{wvds:title>Mein Seitentitel}}

Definiert einen Titel für die Seite, der im Menü angezeigt wird, ohne sichtbar auf der Seite zu erscheinen. Nützlich für Seiten mit Hero-Sections oder speziellen Layouts.

Parameter

Parameter Typ Standard Beschreibung
ns string (auto) Namespace für das Menü (siehe unten)
dynamic integer 1 Anzahl der vorgeladenen Ebenen (Lazy Loading)
startns string (auto) current = Start beim aktuellen Namespace mit „Nach oben“-Link
icons string none fa = FontAwesome Icons für Ordner/Dateien

ns-Parameter Werte:

Wert Beschreibung
ns=„de:docs“ Expliziter Namespace
ns=„auto“ Smart Auto: Fokussierte Ansicht + Geschwister mit Partial Content
(leer) Automatische Erkennung via Sidebar-Position

Parameter-Details

ns - Expliziter Namespace

Zeigt einen bestimmten Namespace unabhängig von der aktuellen Seite:

{{wvds:acmenu>ns=de:crypto}}
{{wvds:acmenu>ns=de:docs:api}}

dynamic - Lazy Loading Tiefe

Steuert wie viele Ebenen initial geladen werden. Tiefere Ebenen werden per AJAX nachgeladen:

Wert Verhalten
dynamic=„0“ Nur Seiten anzeigen (keine Unterordner)
dynamic=„1“ 1 Ebene vorgeladen, Rest per AJAX (Standard)
dynamic=„2“ 2 Ebenen vorgeladen, Rest per AJAX
dynamic=„3“ 3 Ebenen vorgeladen, Rest per AJAX

Wichtig: Der Namespace wird immer relativ zur Sidebar-Position berechnet, nicht zur aktuellen Seite.

startns - Total Commander Modus

Ähnlich wie Total Commander: Zeigt nur den aktuellen Namespace mit einem „Nach oben“-Link:

{{wvds:acmenu>startns=current}}
{{wvds:acmenu>startns=current|dynamic=2}}
Wert Verhalten
startns=„current“ Startet beim Namespace der aktuellen Seite
(kombiniert mit dynamic) Begrenzt die Tiefe wie gewohnt

Vorteile:

  • Übersichtlicher bei großen Strukturen
  • Fokus auf den aktuellen Bereich
  • „Nach oben“-Link zur Navigation

icons - FontAwesome Icons

Aktiviert visuelle Icons für Ordner und Dateien:

{{wvds:acmenu>icons=fa}}
{{wvds:acmenu>startns=current|icons=fa}}
Icon Element FA-Klasse
📁 Geschlossener Ordner fa-folder-o
📂 Geöffneter Ordner fa-folder-open-o
📄 Seite/Dokument fa-file-text-o
Externer Namespace fa-external-link
Nach oben fa-level-up

Voraussetzung: FontAwesome muss im Template geladen sein (im flat Template bereits enthalten).

ns="auto" - Smart Auto Modus

Der auto-Modus kombiniert fokussierte Navigation mit ACL-aware Geschwister-Erkennung:

{{wvds:acmenu>ns=auto|icons=fa|dynamic=1}}

Funktionsweise:

  1. Fokussierte Ansicht: Startet beim aktuellen Namespace (wie startns=„current“)
  2. ACL-aware „Go Up“: Link zum Home-Namespace des Benutzers basierend auf ACL-Regeln
  3. Geschwister mit Partial Content: Zeigt andere Namespaces auf Sprach-Ebene, die lesbaren Inhalt haben
  4. Kombinierbar mit dynamic für Lazy Loading

Unterschied zu startns=„current“:

Modus Verhalten
startns=„current“ Nur aktueller Namespace + „Go Up“ zum Parent
ns=„auto“ Aktueller Namespace + „Go Up“ zum Home + alle Geschwister mit Partial Content

Anwendungsfall: Eine einzige sidebar1.txt für alle Namespaces einer Sprache:

# de/sidebar1.txt (funktioniert für de:pub:*, de:int:*, etc.)
~~NOCACHE~~
{{wvds:acmenu>ns=auto|icons=fa|dynamic=1}}

Beispiel 1: Anonymer Benutzer auf de:pub:start

ACL: de:int:vsce:fpc:p:* ist öffentlich, Rest von de:int:* ist gesperrt

↑ ..                    ← Go Up (entfällt wenn schon am Home)
📂 pub                  ← aktueller Namespace (fokussiert)
   📄 start
   📁 services
📂 int                  ← Geschwister mit Partial Content
   📂 vsce              ← partial (klickbar zum Expandieren)
      📂 fpc            ← partial
         📁 p           ← lesbar

Beispiel 2: Anonymer Benutzer auf de:int:vsce:fpc:p:start

↑ ..                    ← Go Up zu de:pub:start (Home für @ALL)
📁 p                    ← aktueller Namespace (fokussiert)
   📄 start
   📄 download

Beispiel 3: @user auf de:int:dwe:start

↑ ..                    ← Go Up zu de:int:start (Home für @user)
📁 dwe                  ← aktueller Namespace (fokussiert)
   📄 start
   📁 wvdsacmenu
   📁 wvdssnippet
📁 vsce                 ← Geschwister (vollständig lesbar)
📁 pqcrypt              ← Geschwister (vollständig lesbar)

Warum Smart Auto?

Problem Lösung
Große Strukturen überfordern Fokussierte Ansicht zeigt nur relevanten Bereich
„Go Up“ führt zu gesperrten Seiten ACL-aware: Link führt immer zu lesbarem Namespace
Öffentliche Pfade in geschützten Bereichen unsichtbar Geschwister mit Partial Content werden angezeigt
Benutzer verliert Orientierung Immer sichtbar: aktueller Ort + erreichbare Alternativen

Lazy Loading

Funktionsweise

  1. Beim Laden der Seite werden nur die ersten N Ebenen (dynamic) gerendert
  2. Ordner am Tiefenlimit erhalten die CSS-Klasse lazy
  3. Beim Klick auf einen lazy-Ordner wird der Inhalt per AJAX geladen
  4. Der Ladezustand wird durch die Klasse loading angezeigt

Geöffnete Ordner werden im Cookie gespeichert. Beim nächsten Seitenaufruf werden diese Ordner server-seitig vorgeladen, auch wenn sie tiefer als dynamic liegen. Dies verhindert ein „Flackern“ beim Laden.

AJAX-Endpoint

GET /lib/exe/ajax.php?call=plugin_wvdsacmenu_load&ns=de:crypto:subfolder

Response:

{
  "success": true,
  "html": "<li>...</li>",
  "ns": "de:crypto:subfolder"
}

Namespace-Erkennung

Das Plugin erkennt Namespace-Grenzen durch sidebar* Dateien:

  • sidebar.txt
  • sidebar1.txt
  • sidebar2.txt
  • sidebar_name.txt

Erkennungs-Logik

1. Ohne Parameter
   └── Sucht aufwärts nach sidebar* Datei
   └── Startet Menü ab diesem Namespace

2. Mit ns="..."
   └── Verwendet den angegebenen Namespace direkt

3. Mit dynamic="N"
   └── Findet Sidebar-Namespace
   └── Lädt N Ebenen vor, Rest per AJAX

ACL-aware Navigation

Das Plugin berücksichtigt DokuWiki-ACL-Regeln und zeigt Ordner intelligent an, auch wenn nicht alle Inhalte für den Benutzer lesbar sind.

Partial Namespaces

Wenn sneaky_index aktiviert ist und ein Ordner nicht direkt lesbar ist (z.B. de:int:vsce:start für anonyme Benutzer), aber lesbare Inhalte tiefer im Baum existieren (z.B. de:int:vsce:fpc:p:*), wird der Ordner trotzdem angezeigt:

📂 vsce          ← partial (kein Link, nur Label)
   📂 fpc        ← partial (kein Link, nur Label)
      📁 p       ← normal (Link zu p:start)
         📄 start
         📄 download

Verhalten:

  • Ordner mit partial Klasse zeigen nur ein Label (kein Link zur Start-Seite)
  • Klickbar: Ein Klick auf den Ordner expandiert/kollabiert die Kinder
  • Der Ordner ist initial geöffnet, um lesbare Kinder zu zeigen
  • Styling kann per CSS angepasst werden

ACL-basiertes "Go Up"

Bei startns=„current“ springt der „Nach oben“-Link nicht einfach zum Parent-Namespace, sondern zum Home-Namespace des Benutzers basierend auf ACL-Regeln:

Benutzer ACL-Regel „Go Up“ Ziel
Anonym (@ALL) de:pub:* @ALL 1 de:pub:start
@user Gruppe de:int:* @user 1 de:int:start
@wvdse Gruppe de:int:* @wvdse 8 de:int:start

Priorität:

  1. Namespace-Wildcards (z.B. de:pub:*) haben Vorrang
  2. Einzelne Seiten-ACLs (z.B. de:int:start) sind nachrangig
  3. Der kürzeste (höchste) Namespace wird bevorzugt

Beispiel: Ein anonymer Benutzer auf de:int:vsce:fpc:p:start sieht den „Go Up“-Link zu de:pub:start, nicht zu de:int:start.


Template-Integration

Das flat Template lädt Sidebar-Seiten namespace-spezifisch.

Namespace-aware Sidebar Loading

Das Template sucht die Sidebar-Datei (z.B. sidebar1.txt) ausgehend vom aktuellen Namespace aufwärts:

Seite: de:int:vsce:fpc:p:start

Suche nach sidebar1.txt:
1. de:int:vsce:fpc:p:sidebar1 → nicht gefunden
2. de:int:vsce:fpc:sidebar1   → nicht gefunden
3. de:int:vsce:sidebar1       → nicht gefunden
4. de:int:sidebar1            → GEFUNDEN ✓

Ergebnis: Für de:int:* Seiten wird de:int:sidebar1.txt geladen, für de:pub:* Seiten wird de:sidebar1.txt geladen.

ACL für Sidebars

Sidebar-Seiten in geschützten Namespaces müssen für @ALL lesbar sein, damit die Navigation funktioniert!

Beispiel ACL-Einträge:

de:int:sidebar         @ALL    1
de:int:sidebar1        @ALL    1
de:int:sidebar2        @ALL    1

Unsichtbarer Titel

Für Seiten ohne sichtbaren Titel (z.B. Landing Pages mit Hero-Section) kann ein Menü-Titel definiert werden:

~~NOTOC~~
{{wvds:title>NIS2 Compliance Check}}

{{wvds:snippet>nis2check_hero}}
{{wvds:snippet>nis2check_content}}

Der Titel wird:

  • Im Menü angezeigt
  • In den Metadaten gespeichert
  • Nicht auf der Seite gerendert

Titel-Priorität

Das Menü verwendet Titel in folgender Reihenfolge:

  1. {{wvds:title>...}} (Unsichtbarer Titel)
  2. Erste Überschrift der Seite (wenn useheading aktiviert)
  3. Seiten-ID als Fallback

Beispiele

Beispiel 1: Automatisches Menü

sidebar1.txt:

~~NOCACHE~~
{{wvds:snippet>go_back}}
{{wvds:acmenu>}}

Beispiel 2: Empfohlene Konfiguration (ns="auto")

Eine einzige Sidebar-Datei für alle Namespaces einer Sprache:

de/sidebar1.txt:

~~NOCACHE~~
{{wvds:acmenu>ns=auto|icons=fa|dynamic=1}}

Diese Konfiguration:

  • Fokussiert: Zeigt primär den aktuellen Namespace
  • Smart „Go Up“: Link zum ACL-basierten Home-Namespace
  • Geschwister-Erkennung: Zeigt andere Namespaces mit lesbarem Content
  • Partial Namespaces: Pfade zu öffentlichen Bereichen in geschützten Zonen
  • Nutzt FontAwesome Icons
  • Lädt nur 1 Ebene initial, Rest per AJAX

Beispiel 3: Klassische Konfiguration

de/sidebar1.txt:

~~NOCACHE~~
{{wvds:snippet>go_back}}
{{wvds:acmenu>dynamic=2}}

Beispiel 4: Expliziter Namespace

{{wvds:acmenu>ns=de:api}}

Beispiel 5: Total Commander Modus

Für große Strukturen - zeigt nur den aktuellen Bereich mit „Nach oben“-Link:

{{wvds:acmenu>startns=current|icons=fa}}

Ergebnis (bei Seite de:crypto:openssl:start):

↑ ..
📂 openssl
   📄 start
   📁 commands
   📄 examples

Beispiel 6: Kompaktes Icon-Menü

{{wvds:acmenu>startns=current|dynamic=1|icons=fa}}

CSS-Klassen

Klasse Beschreibung
.acmenu Haupt-Container
.acmenu-icons Container mit FontAwesome Icons
.acmenu-up „Nach oben“-Link (startns=current)
.open Geöffneter Ordner
.closed Geschlossener Ordner
.partial Ordner mit nur teilweise lesbarem Inhalt (ACL)
.ns-label Label ohne Link (für partial_ns Ordner)
.curid Aktuelle Seite
.divert Externer Namespace
.lazy Ordner mit noch nicht geladenen Inhalten
.loading Ordner wird gerade per AJAX geladen

Styling für Partial Namespaces

/* Partial Namespaces - klickbar zum Expandieren */
div.acmenu li.partial > div.li {
    cursor: pointer;
}
 
div.acmenu li.partial > div.li .ns-label {
    color: #666;
    font-style: italic;
}
 
/* Icon-Farbe für partial Ordner */
div.acmenu.acmenu-icons li.partial > div.li .fa {
    color: #999;
}

Partial Namespaces sind klickbar und expandieren/kollabieren beim Anklicken, genau wie normale Ordner. Der Unterschied ist nur, dass sie keinen Link zur Start-Seite haben (weil diese nicht lesbar ist).

Styling für Lazy Loading

/* Lade-Indikator */
div.acmenu li.loading > div.li:after {
    content: " ⟳";
    animation: spin 1s linear infinite;
}
 
@keyframes spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}
 
/* Lazy-Ordner visuell markieren */
div.acmenu li.lazy > div.li {
    cursor: pointer;
}

Konfiguration

Einstellung Typ Standard Beschreibung
startOpen An/Aus Aus Alle Ordner standardmäßig öffnen
sortType Auswahl alpha Sortierung
showPageTitle An/Aus An Seitentitel statt ID
maxDepth Zahl 0 Max. Tiefe (0 = unbegrenzt)

Geöffnete Ordner werden im Cookie plugin_wvdsacmenu_open_items gespeichert.

// Cookie-Name
plugin_wvdsacmenu_open_items
 
// Wert (JSON-Array)
["de:crypto:start","de:docs:api:start"]

Server-seitige Wiederherstellung

Beim Rendern liest das Plugin den Cookie und lädt alle dort gespeicherten Ordner vor - auch wenn sie tiefer als dynamic liegen. Dies stellt den Menüzustand ohne JavaScript-Flackern wieder her.


Versionshinweise

Version Datum Änderungen
1.4.0 2026-01-30 Syntax-Änderung: > nach wvds:acmenu pflicht (vermeidet Media-Syntax-Konflikt), pipe-separierte Parameter
1.3.0 2026-01-29 ACL-aware Navigation: ns=„auto“ Smart Auto Modus (fokussiert + Geschwister mit Partial Content), Partial Namespaces (partial_ns), ACL-basiertes „Go Up“ zu Home-Namespace, _hasPartialChildren() für automatische Expansion, _renderAutoSiblings() für Geschwister-Erkennung
1.2.0 2026-01-29 startns=„current“ (Total Commander Modus), icons=„fa“ (FontAwesome Icons)
1.1.0 2026-01-29 Lazy Loading, Cookie-Wiederherstellung, {{wvds:title>...}} Syntax
1.0.0 2025-01-06 WvdS-Erweiterungen: Wiki-Syntax, mehrsprachige Unterstützung

Siehe auch


Technische Referenz

Klasse: syntax_plugin_wvdsacmenu

Datei: lib/plugins/wvdsacmenu/syntax.php

Methode Beschreibung
getType() Gibt substitution zurück
getSort() Gibt 320 zurück
_findSidebar() Sucht sidebar* Datei
_tree() Baut Menü-Baum (mit Lazy-Support und partial_ns)
_hasReadableContent() Prüft ob lesbare Inhalte im Namespace existieren
_hasPartialChildren() Prüft ob Namespace partial_ns Kinder enthält
_findUserHomeNamespace() Findet Home-Namespace basierend auf ACL
_renderAutoSiblings() Rendert Geschwister-Namespaces mit Partial Content (für ns=„auto“)
_shouldForceLoad() Prüft ob Namespace per Cookie wiederhergestellt werden soll
_getPageTitle() Holt Seitentitel (wvds:title > heading > ID)
buildSubTree() Öffentlich: Baut Unter-Baum für AJAX
renderSubTree() Öffentlich: Rendert Unter-Baum als HTML

Template-Funktion: tpl_findSidebarInNamespace()

Datei: lib/tpl/flat/lang_helper.php

Parameter Typ Beschreibung
$sidebarName string Name der Sidebar-Datei (z.B. sidebar1)
Return string/null Volle Page-ID oder null wenn nicht gefunden

Sucht eine Sidebar-Datei ausgehend vom aktuellen Namespace aufwärts.

Klasse: action_plugin_wvdsacmenu

Datei: lib/plugins/wvdsacmenu/action.php

Methode Beschreibung
_add_user_conf() Konfiguration für JavaScript (JSINFO)
_ajax_load_ns() AJAX-Handler für Lazy Loading

JavaScript: script.js

Datei: lib/plugins/wvdsacmenu/script.js

Funktion Beschreibung
get_cookie() Liest geöffnete Items aus Cookie
set_cookie() Speichert geöffnete Items
saveCookie() Aktualisiert Cookie nach Änderung
trim_url() Extrahiert Page-ID aus URL
handleLazyLoad() AJAX-Laden von Ordnerinhalten
toggleItem() Öffnet/schließt einen Ordner
hasIcons() Prüft ob Icons aktiviert sind
updateFolderIcon() Wechselt Ordner-Icon beim Öffnen/Schließen

wvdsacmenu PluginAudit bestanden • 2026-03-30

Diskussion

Geben Sie Ihren Kommentar ein. Wiki-Syntax ist zugelassen:
 
Zuletzt geändert: den 30.01.2026 um 11:30