====== WvdS.DokuWiki.AcMenu Plugin ====== **Plugin:** wvdsacmenu\\ **Versione:** 1.3.0\\ **Namespace:** ''lib/plugins/wvdsacmenu/''\\ **Base:** [[https://www.dokuwiki.org/plugin:acmenu|AcMenu]] di Torpedo\\ **Estensioni:** Wolfgang van der Stille \\ **Licenza:** GPL 2 ---- ===== Definizione ===== Il plugin **wvdsacmenu** mostra un menu ad accordion per namespace e pagine. Estende l'AcMenu originale con sintassi wiki, rilevamento namespace dinamico, **lazy loading**, **navigazione ACL-aware** e supporto multilingue. ---- ===== Motivazione ===== ==== Il problema con la navigazione standard ==== La navigazione standard DokuWiki e l'AcMenu originale hanno diverse limitazioni in ambienti enterprise: * **Cecità ACL:** Quando ''sneaky_index=1'' è attivo, le cartelle protette sono completamente nascoste - anche se contenuti pubblici esistono **più in profondità** * **Nessun lazy loading:** Con grandi strutture documentali (100+ pagine) la sidebar diventa lenta e confusa * **Isolamento linguistico:** I wiki multilingue richiedono configurazione manuale per namespace * **Nessuna integrazione template:** La selezione sidebar è statica e non conosce la gerarchia namespace ==== Esempio: Percorso pubblico in area protetta ==== Configurazione ACL: de:int:* @ALL 0 (bloccato) de:int:vsce:fpc:p:* @ALL 1 (pubblico) Risultato AcMenu standard: 📂 de 📁 pub ← visibile (vsce manca!) ← PROBLEMA: intero percorso nascosto Risultato wvdsacmenu: 📂 de 📁 pub 📂 int 📂 vsce ← partial (nessun link) 📂 fpc ← partial (nessun link) 📁 p ← visibile e navigabile L'utente vede il percorso verso contenuti pubblici, anche se le cartelle intermedie non sono direttamente leggibili. ---- ===== Obiettivi ===== ==== Navigazione enterprise ==== wvdsacmenu è stato sviluppato per strutture documentali complesse con permessi di accesso differenziati: ^ Requisito ^ Soluzione ^ | Grandi strutture | Lazy loading (''dynamic="N"'') | | ACL differenziati | Partial namespace, ACL-aware "Vai su" | | Multilingue | Rilevamento lingua automatico, ''ns="auto"'' | | Performance | Ripristino cookie lato server | | UX | Modalità Total Commander, icone FontAwesome | ==== Confronto con AcMenu originale ==== ^ Funzione ^ AcMenu originale ^ wvdsacmenu ^ | Supporto ACL | Solo read/hide | Partial namespace, percorsi profondi | | Lazy loading | No | Sì (AJAX) | | Ripristino cookie | Solo client | Server + client | | Multilingue | Manuale | Automatico (''ns="auto"'') | | Icone | No | FontAwesome | | Integrazione template | No | Sidebar namespace-aware | | Navigazione "Vai su" | No | Basata su ACL | | Titolo invisibile | No | ''%%{{wvds:title>...}}%%'' | ==== Principi di design ==== - **Minima divulgazione:** Mostra solo ciò che l'utente può vedere, ma mostra il **percorso** per arrivarci - **Caricamento progressivo:** Carica poco inizialmente, espandi su richiesta - **Ripristino stateless:** Lo stato cookie viene ripristinato lato server (nessun flicker) - **Integrazione profonda:** Il plugin lavora strettamente con template e sistema ACL ---- ===== Casi d'uso ===== * **Navigazione namespace** - Menu automatico per struttura documentazione * **Wiki multilingue** - Menu separati per namespace linguistico * **Documentazione progetti** - Navigazione gerarchica in sotto-namespace * **Integrazione sidebar** - Navigazione compatta nella barra laterale * **Ottimizzazione performance** - Lazy loading per grandi strutture menu * **Navigazione ACL-aware** - Mostra cartelle anche quando solo parti sono leggibili ---- ===== Sintassi ===== ==== Sintassi menu ==== {{wvds:acmenu}} {{wvds:acmenu ns="namespace"}} {{wvds:acmenu dynamic="N"}} {{wvds:acmenu startns="current" icons="fa"}} ==== Sintassi titolo (titolo invisibile) ==== {{wvds:title>Titolo della mia pagina}} Definisce un titolo per la pagina mostrato nel menu, senza apparire visibile sulla pagina. Utile per pagine con hero section o layout speciali. ==== Parametri ==== ^ Parametro ^ Tipo ^ Default ^ Descrizione ^ | ''ns'' | string | //(auto)// | Namespace per il menu (vedi sotto) | | ''dynamic'' | integer | ''1'' | Numero livelli precaricati (lazy loading) | | ''startns'' | string | //(auto)// | ''current'' = Inizia dal namespace corrente con link "Vai su" | | ''icons'' | string | ''none'' | ''fa'' = Icone FontAwesome per cartelle/file | **Valori parametro ns:** ^ Valore ^ Descrizione ^ | ''ns="de:docs"'' | Namespace esplicito | | ''ns="auto"'' | **Smart Auto:** Vista focalizzata + fratelli con contenuto parziale | | //(vuoto)// | Rilevamento automatico via posizione sidebar | ---- ===== Dettagli parametri ===== ==== ns - Namespace esplicito ==== Mostra un namespace specifico indipendentemente dalla pagina corrente: {{wvds:acmenu ns="it:crypto"}} {{wvds:acmenu ns="it:docs:api"}} ==== dynamic - Profondità lazy loading ==== Controlla quanti livelli vengono caricati inizialmente. Livelli più profondi vengono caricati via **AJAX**: ^ Valore ^ Comportamento ^ | ''dynamic="0"'' | Mostra solo pagine (nessuna sottocartella) | | ''dynamic="1"'' | 1 livello precaricato, resto via AJAX (default) | | ''dynamic="2"'' | 2 livelli precaricati, resto via AJAX | | ''dynamic="3"'' | 3 livelli precaricati, resto via AJAX | **Importante:** Il namespace viene sempre calcolato relativamente alla **posizione sidebar**, non alla pagina corrente. ==== startns - Modalità Total Commander ==== Simile a Total Commander: Mostra solo il namespace corrente con link "Vai su": {{wvds:acmenu startns="current"}} {{wvds:acmenu startns="current" dynamic="2"}} ^ Valore ^ Comportamento ^ | ''startns="current"'' | Inizia dal namespace della pagina corrente | | (combinato con dynamic) | Limita la profondità come al solito | **Vantaggi:** * Più chiaro con grandi strutture * Focus sull'area corrente * Link "Vai su" per navigazione ==== icons - Icone FontAwesome ==== Attiva icone visive per cartelle e file: {{wvds:acmenu icons="fa"}} {{wvds:acmenu startns="current" icons="fa"}} ^ Icona ^ Elemento ^ Classe FA ^ | 📁 | Cartella chiusa | ''fa-folder-o'' | | 📂 | Cartella aperta | ''fa-folder-open-o'' | | 📄 | Pagina/Documento | ''fa-file-text-o'' | | ↗ | Namespace esterno | ''fa-external-link'' | | ↑ | Vai su | ''fa-level-up'' | **Prerequisito:** FontAwesome deve essere caricato nel template (già incluso nel template ''flat''). ==== ns="auto" - Modalità Smart Auto ==== La modalità ''auto'' combina **navigazione focalizzata** con **rilevamento fratelli ACL-aware**: {{wvds:acmenu ns="auto" icons="fa" dynamic="1"}} **Funzionamento:** - **Vista focalizzata:** Inizia dal namespace corrente (come ''startns="current"'') - **"Vai su" ACL-aware:** Link al namespace home dell'utente basato su regole ACL - **Fratelli con contenuto parziale:** Mostra altri namespace a livello lingua che hanno contenuto leggibile - Combinabile con ''dynamic'' per lazy loading **Differenza da ''startns="current"'':** ^ Modalità ^ Comportamento ^ | ''startns="current"'' | Solo namespace corrente + "Vai su" al parent | | ''ns="auto"'' | Namespace corrente + "Vai su" a home + **tutti i fratelli con contenuto parziale** | **Caso d'uso:** Una sola ''sidebar1.txt'' per tutti i namespace di una lingua: # it/sidebar1.txt (funziona per it:pub:*, it:int:*, ecc.) ~~NOCACHE~~ {{wvds:acmenu ns="auto" icons="fa" dynamic="1"}} **Esempio 1: Utente anonimo su ''it:pub:start''** ACL: ''it:int:vsce:fpc:p:*'' è pubblico, resto di ''it:int:*'' è bloccato ↑ .. ← Vai su (omesso se già a home) 📂 pub ← namespace corrente (focalizzato) 📄 start 📁 services 📂 int ← fratello con contenuto parziale 📂 vsce ← partial (cliccabile per espandere) 📂 fpc ← partial 📁 p ← leggibile **Esempio 2: Utente anonimo su ''it:int:vsce:fpc:p:start''** ↑ .. ← Vai su a it:pub:start (home per @ALL) 📁 p ← namespace corrente (focalizzato) 📄 start 📄 download **Esempio 3: @user su ''it:int:dwe:start''** ↑ .. ← Vai su a it:int:start (home per @user) 📁 dwe ← namespace corrente (focalizzato) 📄 start 📁 wvdsacmenu 📁 wvdssnippet 📁 vsce ← fratello (completamente leggibile) 📁 pqcrypt ← fratello (completamente leggibile) **Perché Smart Auto?** | Problema | Soluzione | | Grandi strutture sovraccaricano | Vista focalizzata mostra solo area rilevante | | "Vai su" porta a pagine bloccate | ACL-aware: link porta sempre a namespace leggibile | | Percorsi pubblici in aree protette invisibili | Fratelli con contenuto parziale vengono mostrati | | Utente perde orientamento | Sempre visibile: posizione corrente + alternative raggiungibili | ---- ===== Lazy loading ===== ==== Funzionamento ==== - Al caricamento pagina vengono renderizzati solo i primi ''N'' livelli (''dynamic'') - Cartelle al limite di profondità ricevono classe CSS ''lazy'' - Al click su cartella ''lazy'' il contenuto viene caricato via AJAX - Lo stato di caricamento viene indicato dalla classe ''loading'' ==== Ripristino cookie ==== Le cartelle aperte vengono salvate nel cookie. Al prossimo caricamento pagina queste cartelle vengono precaricate **lato server**, anche se sono più profonde di ''dynamic''. Questo impedisce "flicker" al caricamento. ==== Endpoint AJAX ==== GET /lib/exe/ajax.php?call=plugin_wvdsacmenu_load&ns=it:crypto:subfolder **Risposta:** { "success": true, "html": "
  • ...
  • ", "ns": "it:crypto:subfolder" }
    ---- ===== Rilevamento namespace ===== ==== Rilevamento confine sidebar ==== Il plugin riconosce i confini namespace tramite file ''sidebar*'': * ''sidebar.txt'' * ''sidebar1.txt'' * ''sidebar2.txt'' * ''sidebar_name.txt'' ==== Logica di rilevamento ==== 1. Senza parametro └── Cerca verso l'alto file sidebar* └── Avvia menu da quel namespace 2. Con ns="..." └── Usa il namespace specificato direttamente 3. Con dynamic="N" └── Trova namespace sidebar └── Carica N livelli in anticipo, resto via AJAX ---- ===== Navigazione ACL-aware ===== Il plugin considera le regole ACL DokuWiki e mostra le cartelle in modo intelligente, anche se non tutti i contenuti sono leggibili per l'utente. ==== Partial namespace ==== Quando ''sneaky_index'' è attivato e una cartella non è direttamente leggibile (es. ''it:int:vsce:start'' per utenti anonimi), **ma** contenuti leggibili esistono più in profondità nell'albero (es. ''it:int:vsce:fpc:p:*''), la cartella viene comunque mostrata: 📂 vsce ← partial (nessun link, solo etichetta) 📂 fpc ← partial (nessun link, solo etichetta) 📁 p ← normale (link a p:start) 📄 start 📄 download **Comportamento:** * Cartelle con classe ''partial'' mostrano solo un'etichetta (nessun link alla pagina start) * **Cliccabile:** Un click sulla cartella espande/comprime i figli * La cartella è inizialmente aperta per mostrare i figli leggibili * Lo styling può essere personalizzato via CSS ==== "Vai su" basato su ACL ==== Con ''startns="current"'' il link "Vai su" non salta semplicemente al namespace parent, ma al **namespace home** dell'utente basato su regole ACL: ^ Utente ^ Regola ACL ^ Destinazione "Vai su" ^ | Anonimo (@ALL) | ''it:pub:* @ALL 1'' | ''it:pub:start'' | | Gruppo @user | ''it:int:* @user 1'' | ''it:int:start'' | | Gruppo @wvdse | ''it:int:* @wvdse 8'' | ''it:int:start'' | **Priorità:** - Wildcard namespace (es. ''it:pub:*'') hanno precedenza - ACL singole pagine (es. ''it:int:start'') sono secondari - Viene preferito il namespace più corto (più alto) **Esempio:** Un utente anonimo su ''it:int:vsce:fpc:p:start'' vede il link "Vai su" a ''it:pub:start'', non a ''it:int:start''. ---- ===== Integrazione template ===== Il template ''flat'' carica le pagine sidebar **specifiche per namespace**. ==== Caricamento sidebar namespace-aware ==== Il template cerca il file sidebar (es. ''sidebar1.txt'') partendo dal namespace corrente verso l'alto: Pagina: it:int:vsce:fpc:p:start Ricerca sidebar1.txt: 1. it:int:vsce:fpc:p:sidebar1 → non trovato 2. it:int:vsce:fpc:sidebar1 → non trovato 3. it:int:vsce:sidebar1 → non trovato 4. it:int:sidebar1 → TROVATO ✓ **Risultato:** Per pagine ''it:int:*'' viene caricato ''it:int:sidebar1.txt'', per pagine ''it:pub:*'' viene caricato ''it:sidebar1.txt''. ==== ACL per sidebar ==== Le pagine sidebar in namespace protetti devono essere leggibili per @ALL affinché la navigazione funzioni! **Esempio voci ACL:** it:int:sidebar @ALL 1 it:int:sidebar1 @ALL 1 it:int:sidebar2 @ALL 1 ---- ===== Titolo invisibile ===== Per pagine senza titolo visibile (es. landing page con hero section) può essere definito un titolo per il menu: ~~NOTOC~~ {{wvds:title>Verifica conformità NIS2}} {{wvds:snippet>nis2check_hero}} {{wvds:snippet>nis2check_content}} Il titolo viene: * Mostrato nel menu * Salvato nei metadati * **Non** renderizzato sulla pagina ==== Priorità titolo ==== Il menu usa titoli nel seguente ordine: - ''%%{{wvds:title>...}}%%'' (Titolo invisibile) - Primo heading della pagina (se ''useheading'' attivato) - ID pagina come fallback ---- ===== Esempi ===== ==== Esempio 1: Menu automatico ==== **sidebar1.txt:** ~~NOCACHE~~ {{wvds:snippet>go_back}} {{wvds:acmenu}} ==== Esempio 2: Configurazione consigliata (ns="auto") ==== Un solo file sidebar per tutti i namespace di una lingua: **it/sidebar1.txt:** ~~NOCACHE~~ {{wvds:acmenu ns="auto" icons="fa" dynamic="1"}} Questa configurazione: * **Focalizzata:** Mostra principalmente il namespace corrente * **"Vai su" smart:** Link al namespace home basato su ACL * **Rilevamento fratelli:** Mostra altri namespace con contenuto leggibile * **Partial namespace:** Percorsi verso aree pubbliche in zone protette * Usa icone FontAwesome * Carica solo 1 livello inizialmente, resto via AJAX ==== Esempio 3: Configurazione classica ==== **it/sidebar1.txt:** ~~NOCACHE~~ {{wvds:snippet>go_back}} {{wvds:acmenu dynamic="2"}} ==== Esempio 4: Namespace esplicito ==== {{wvds:acmenu ns="it:api"}} ==== Esempio 5: Modalità Total Commander ==== Per grandi strutture - mostra solo l'area corrente con link "Vai su": {{wvds:acmenu startns="current" icons="fa"}} Risultato (per pagina ''it:crypto:openssl:start''): ↑ .. 📂 openssl 📄 start 📁 commands 📄 examples ==== Esempio 6: Menu compatto con icone ==== {{wvds:acmenu startns="current" dynamic="1" icons="fa"}} ---- ===== Classi CSS ===== ^ Classe ^ Descrizione ^ | ''.acmenu'' | Container principale | | ''.acmenu-icons'' | Container con icone FontAwesome | | ''.acmenu-up'' | Link "Vai su" (startns=current) | | ''.open'' | Cartella aperta | | ''.closed'' | Cartella chiusa | | ''.partial'' | Cartella con contenuto solo parzialmente leggibile (ACL) | | ''.ns-label'' | Etichetta senza link (per cartelle partial_ns) | | ''.curid'' | Pagina corrente | | ''.divert'' | Namespace esterno | | ''.lazy'' | Cartella con contenuti non ancora caricati | | ''.loading'' | Cartella in caricamento via AJAX | ==== Styling per partial namespace ==== /* Partial namespace - cliccabile per espandere */ div.acmenu li.partial > div.li { cursor: pointer; } div.acmenu li.partial > div.li .ns-label { color: #666; font-style: italic; } /* Colore icona per cartelle partial */ div.acmenu.acmenu-icons li.partial > div.li .fa { color: #999; } I partial namespace sono **cliccabili** e si espandono/comprimono al click, esattamente come le cartelle normali. L'unica differenza è che non hanno link alla pagina start (perché non è leggibile). ==== Styling per lazy loading ==== /* Indicatore caricamento */ div.acmenu li.loading > div.li:after { content: " ⟳"; animation: spin 1s linear infinite; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } /* Marcatura visiva cartelle lazy */ div.acmenu li.lazy > div.li { cursor: pointer; } ---- ===== Configurazione ===== ^ Impostazione ^ Tipo ^ Default ^ Descrizione ^ | ''startOpen'' | On/Off | Off | Tutte le cartelle aperte di default | | ''sortType'' | Scelta | alpha | Ordinamento | | ''showPageTitle'' | On/Off | On | Titolo pagina invece di ID | | ''maxDepth'' | Numero | 0 | Profondità max (0 = illimitata) | ---- ===== Archiviazione cookie ===== Le cartelle aperte vengono salvate nel cookie ''plugin_wvdsacmenu_open_items''. ==== Formato cookie ==== // Nome cookie plugin_wvdsacmenu_open_items // Valore (Array JSON) ["it:crypto:start","it:docs:api:start"] ==== Ripristino lato server ==== Durante il rendering il plugin legge il cookie e precarica tutte le cartelle salvate - anche se sono più profonde di ''dynamic''. Questo ripristina lo stato menu senza flicker JavaScript. ---- ===== Note sulla versione ===== ^ Versione ^ Data ^ Modifiche ^ | 1.3.0 | 2026-01-29 | **Navigazione ACL-aware:** ''ns="auto"'' modalità Smart Auto (focalizzata + fratelli con contenuto parziale), partial namespace (''partial_ns''), "Vai su" basato su ACL a namespace home, ''_hasPartialChildren()'' per espansione automatica, ''_renderAutoSiblings()'' per rilevamento fratelli | | 1.2.0 | 2026-01-29 | ''startns="current"'' (modalità Total Commander), ''icons="fa"'' (icone FontAwesome) | | 1.1.0 | 2026-01-29 | Lazy loading, ripristino cookie, sintassi ''%%{{wvds:title>...}}%%'' | | 1.0.0 | 2025-01-06 | Estensioni WvdS: sintassi wiki, supporto multilingue | ---- ===== Vedi anche ===== * [[.:wvdssnippet]] - Blocchi HTML * [[.:wvdsi18n]] - Testi multilingue * [[.:flat]] - Template con sidebar ---- ===== Riferimento tecnico ===== ==== Classe: syntax_plugin_wvdsacmenu ==== **File:** ''lib/plugins/wvdsacmenu/syntax.php'' ^ Metodo ^ Descrizione ^ | ''getType()'' | Restituisce ''substition'' | | ''getSort()'' | Restituisce ''320'' | | ''_findSidebar()'' | Cerca file sidebar* | | ''_tree()'' | Costruisce albero menu (con supporto lazy e partial_ns) | | ''_hasReadableContent()'' | Verifica se contenuti leggibili esistono nel namespace | | ''_hasPartialChildren()'' | Verifica se namespace contiene figli partial_ns | | ''_findUserHomeNamespace()'' | Trova namespace home basato su ACL | | ''_renderAutoSiblings()'' | Renderizza namespace fratelli con contenuto parziale (per ns="auto") | | ''_shouldForceLoad()'' | Verifica se namespace deve essere ripristinato via cookie | | ''_getPageTitle()'' | Ottiene titolo pagina (wvds:title > heading > ID) | | ''buildSubTree()'' | Pubblico: Costruisce sotto-albero per AJAX | | ''renderSubTree()'' | Pubblico: Renderizza sotto-albero come HTML | ==== Funzione template: tpl_findSidebarInNamespace() ==== **File:** ''lib/tpl/flat/lang_helper.php'' ^ Parametro ^ Tipo ^ Descrizione ^ | ''$sidebarName'' | string | Nome file sidebar (es. ''sidebar1'') | | **Ritorno** | string/null | Page-ID completo o null se non trovato | Cerca un file sidebar partendo dal namespace corrente verso l'alto. ==== Classe: action_plugin_wvdsacmenu ==== **File:** ''lib/plugins/wvdsacmenu/action.php'' ^ Metodo ^ Descrizione ^ | ''_add_user_conf()'' | Configurazione per JavaScript (JSINFO) | | ''_ajax_load_ns()'' | Handler AJAX per lazy loading | ==== JavaScript: script.js ==== **File:** ''lib/plugins/wvdsacmenu/script.js'' ^ Funzione ^ Descrizione ^ | ''get_cookie()'' | Legge elementi aperti dal cookie | | ''set_cookie()'' | Salva elementi aperti | | ''saveCookie()'' | Aggiorna cookie dopo modifica | | ''trim_url()'' | Estrae Page-ID da URL | | ''handleLazyLoad()'' | Caricamento AJAX contenuti cartella | | ''toggleItem()'' | Apre/chiude una cartella | | ''hasIcons()'' | Verifica se icone sono attivate | | ''updateFolderIcon()'' | Cambia icona cartella all'apertura/chiusura | ---- [x][x][x][x] [x][x][x][x][x] [x][x][x][-][-] ~~DISCUSSION~~