From a3d293b8ff6aa2579dae824aa207fbcc041897f8 Mon Sep 17 00:00:00 2001 From: PythonWoods Date: Wed, 1 Apr 2026 18:31:51 +0200 Subject: [PATCH] docs: fix technical inaccuracies regarding extras, installation, and static limits --- LICENSE | 2 +- SECURITY.md | 5 +- docs/about/index.md | 2 +- docs/about/philosophy.md | 7 +- docs/architecture.md | 19 +++- docs/guide/engines.md | 18 ++++ docs/guide/migration.md | 195 ++++++++++++++++++++++++++++--------- docs/it/about/index.md | 2 +- docs/it/guide/engines.md | 19 ++++ docs/it/guide/migration.md | 191 ++++++++++++++++++++++++++++-------- docs/it/usage/index.md | 53 +++++----- docs/usage/index.md | 55 +++++------ 12 files changed, 414 insertions(+), 154 deletions(-) diff --git a/LICENSE b/LICENSE index 624eb6a..ffd6322 100644 --- a/LICENSE +++ b/LICENSE @@ -175,7 +175,7 @@ END OF TERMS AND CONDITIONS - Copyright 2025 Cell Location Analyzer Contributors + Copyright 2026 PythonWoods Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/SECURITY.md b/SECURITY.md index f1e87f1..7cc9a54 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -55,9 +55,8 @@ other build tool during `check`, `score`, or `diff`. The attack surface is limit | Version | Support status | | :------ | :------------- | -| `0.4.x` (current) | ✅ Security fixes backported | -| `0.3.x` | ⚠️ Critical fixes only | -| `< 0.3` | ❌ End of life — upgrade recommended | +| `0.4.x` (current) | ✅ All security fixes | +| `< 0.4` | ❌ Not publicly released — no support | ## Disclosure policy diff --git a/docs/about/index.md b/docs/about/index.md index 06aa736..bf6aa71 100644 --- a/docs/about/index.md +++ b/docs/about/index.md @@ -7,7 +7,7 @@ icon: lucide/info # About Zenzic -Zenzic is an engineering-grade documentation linter and quality gate for MkDocs and Zensical projects. +Zenzic is an engineering-grade documentation linter and quality gate for any Markdown-based project. Built by [PythonWoods](https://github.com/PythonWoods), it is designed to run in CI/CD pipelines and catch documentation issues before they reach users. diff --git a/docs/about/philosophy.md b/docs/about/philosophy.md index 51c7c29..88c5f6e 100644 --- a/docs/about/philosophy.md +++ b/docs/about/philosophy.md @@ -41,9 +41,10 @@ The implementation of this commitment is **absolute engine-agnosticism**: - Third-party adapters install as Python packages and are discovered at runtime via entry-points. Adding support for a new engine (Hugo, Docusaurus, Sphinx) requires no Zenzic release. -The practical consequence: a project migrating from MkDocs to Zensical can run `zenzic check all` -continuously against both configurations simultaneously. A project that has not yet decided on a -build engine can still validate its documentation quality today. +The practical consequence: a project migrating from MkDocs to Zensical — or to Hugo, Docusaurus, +or any future generator — can run `zenzic check all` continuously against both configurations +simultaneously. A project that has not yet decided on a build engine can still validate its +documentation quality today, using Vanilla mode with zero configuration. --- diff --git a/docs/architecture.md b/docs/architecture.md index 8431f58..92e3741 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -32,16 +32,20 @@ Every Zenzic run follows the same four-stage pipeline, regardless of the documen flowchart LR classDef source fill:#0f172a,stroke:#38bdf8,stroke-width:2px,color:#e2e8f0 classDef adapter fill:#0f172a,stroke:#7c3aed,stroke-width:2px,color:#e2e8f0 + classDef vsm fill:#0f172a,stroke:#f59e0b,stroke-width:2px,color:#e2e8f0 classDef engine fill:#0f172a,stroke:#10b981,stroke-width:2px,color:#e2e8f0 - classDef output fill:#0f172a,stroke:#f59e0b,stroke-width:2px,color:#e2e8f0 + classDef output fill:#0f172a,stroke:#dc2626,stroke-width:2px,color:#e2e8f0 S["📄 Source\n.md files\nzenzic.toml"]:::source A["🔌 Adapter\nMkDocsAdapter\nZensicalAdapter\nVanillaAdapter"]:::adapter + V["🗺️ Virtual Site Map\nURL → Route\n(status · anchors)"]:::vsm R["⚙️ Rule Engine\nBuilt-in checks\nCustom Rules DSL\nPlugin rules"]:::engine F["📋 Findings\nIntegrityReport\nRuleFindings\nExit code"]:::output S -->|"get_adapter()"| A - A -->|"nav_paths\nlocale_dirs\nasset_fallback"| R + A -->|"nav_paths\nlocale_dirs\nasset_fallback"| V + S -->|"raw Markdown text"| V + V -->|"routing state\nGhost Routes\nanchor index"| R S -->|"raw Markdown text"| R R --> F ``` @@ -85,6 +89,17 @@ flowchart TD CAC --> VIO ``` +### Terminology: Route vs Path + +**Path** — the filesystem location of a source file, relative to `docs/` +(e.g. `guide/index.md`). + +**Route** — the canonical URL the build engine will serve for that file +(e.g. `/guide/`). The same source Path can resolve to different Routes under +different engines. The VSM maps every known Path to exactly one Route and +assigns it a status. All link validation and orphan detection operate on +Routes, never on raw Paths — this is what makes Zenzic engine-agnostic. + ### Route status values | Status | Set by | Meaning | diff --git a/docs/guide/engines.md b/docs/guide/engines.md index 57bf41e..6b739ab 100644 --- a/docs/guide/engines.md +++ b/docs/guide/engines.md @@ -69,6 +69,24 @@ It reads `mkdocs.yml` using a permissive YAML loader that silently ignores unkno (such as MkDocs `!ENV` interpolation), so environment-variable-heavy configs work without any preprocessing. +### Static analysis limits + +`MkDocsAdapter` parses `mkdocs.yml` as **static data**. It does not execute the MkDocs +build pipeline. This means: + +- **`!ENV` tags** — silently treated as `null`. If your nav relies on environment variable + interpolation at build time, the nav entries that depend on those values will be absent + from Zenzic's view. +- **Plugin-generated nav** — plugins that mutate the nav at runtime (e.g. `mkdocs-awesome-pages`, + `mkdocs-literate-nav`) produce a navigation tree that Zenzic never sees. Pages included + only by these plugins will be reported as orphans. +- **Macros** — `mkdocs-macros-plugin` (Jinja2 templates in Markdown) is not evaluated. + Links inside macro expressions are not validated. + +For projects that rely heavily on dynamic nav generation, add the plugin-generated paths to +`excluded_dirs` in `zenzic.toml` to suppress false orphan reports until a native adapter +is available. + ### Minimal configuration ```toml diff --git a/docs/guide/migration.md b/docs/guide/migration.md index 4518038..5d43075 100644 --- a/docs/guide/migration.md +++ b/docs/guide/migration.md @@ -5,23 +5,108 @@ icon: lucide/arrow-right-left -# Migrating from MkDocs to Zensical +# Migrating to Zensical -Zenzic acts as a continuous integrity guard during your migration. Because it lints the -**source files** and reads configuration as plain data — never by importing or executing the -build framework — it works correctly against both engines simultaneously and can validate your -documentation before, during, and after the switch. +!!! note "Zenzic vs Zensical" + **Zenzic** is the documentation linter described in this documentation site — the tool + you run with `zenzic check all`. + + **Zensical** is a separate build engine (a compatible successor to MkDocs 1.x). This page + describes how to use Zenzic as a safety net while switching your *build engine* from MkDocs + to Zensical. + + You do not need to use Zensical to use Zenzic. Zenzic works with MkDocs, Zensical, + Vanilla Markdown folders, and any engine that has an adapter. --- -## What stays the same +## Your source files outlive your build engine + +Build engines evolve. They change configuration formats, drop plugin systems, merge with +commercial platforms, or simply stop being maintained. When that happens, the assets at risk +are not your Markdown files — those are plain text and will always be readable. What is at +risk is your **investment in structure**: the navigation, the i18n conventions, the link +graph, the asset organisation you have built over years. + +Zenzic's role in a migration is not to make the switch faster. It is to make the switch +**provably safe** — by guaranteeing that every structural invariant you care about is +measured before, during, and after the move, and that any regression is visible immediately +and attributed precisely. + +This guarantee rests on a single architectural principle: **Zenzic lints the source, never +the build**. It reads `mkdocs.yml`, `zensical.toml`, and your Markdown files as plain data. +It never imports or executes a build framework. This means: + +- Zenzic understands your documentation structure even if the build binary that used to + interpret it no longer works. +- Running `zenzic check all` on a project in the middle of a migration produces the same + analysis as on a fully operational project — because the source files have not changed. +- Switching `engine` in `zenzic.toml` (one line) is all it takes to validate whether your + content is structurally compatible with a new engine, without touching a single Markdown + file. + +This is the Safe Harbor: **a fixed validation layer that remains valid before, during, and +after any build engine change**. + +--- + +## The MkDocsAdapter: plain-data preservation + +The `MkDocsAdapter` treats `mkdocs.yml` as a pure data structure — a set of nav paths, +plugin declarations, and locale settings. It extracts what it needs (nav tree, i18n +configuration, plugin flags like `reconfigure_material`) and hands the result to the Rule +Engine as typed Python objects. It never calls `mkdocs build`, never imports `mkdocs`, and +never depends on any plugin being installed or functional. -Zensical is a compatible successor to MkDocs. It reads `mkdocs.yml` natively, so many projects can switch -the build binary without touching a single documentation file. From Zenzic's perspective: +The practical consequence is that `MkDocsAdapter` is a **custodian of the classic pluggable +ecosystem standard**. As long as your `mkdocs.yml` describes a valid MkDocs 1.x-style +structure, Zenzic will understand and validate it — regardless of what any build binary +does or does not support. If you run `zenzic check all` with `engine = "mkdocs"`, you are +testing your content against the documented MkDocs 1.x structural contract, not against any +particular binary version. + +This makes Zenzic's output a portable quality certificate: if Zenzic says your +documentation is structurally sound, that claim is true independently of which engine you +use to render it tomorrow. + +--- + +## i18n: validating structure independently of rendering + +The MkDocs `i18n` plugin (folder-mode and suffix-mode conventions) defines a well-specified +content structure: locale directories, fallback chains, per-locale nav shadowing. Zenzic +encodes this specification in `MkDocsAdapter` and the Virtual Site Map independently of any +rendering implementation. + +This matters during engine transitions. When a build engine is still maturing its i18n +support, there is a window where the *structural rules* of your i18n setup are well-defined +but the *rendering capability* of the engine may not yet be complete. Zenzic operates +entirely in the structural domain: + +- **Cross-locale link resolution** — a link from an Italian page to an English-only asset + is resolved against the fallback chain defined in `mkdocs.yml`, not against the build + output. +- **Ghost Route detection** — locale entry points generated at build time (e.g. `/it/`) + are marked `REACHABLE` in the VSM so they are never reported as orphans, even if they + have never been rendered. +- **Locale directory suppression** — files under `docs/it/`, `docs/fr/`, etc. are + classified as locale shadows, not orphans. + +You can therefore validate a complex i18n structure with Zenzic and be confident in its +internal consistency — the link graph is correct, the fallback chains are intact, the nav +is complete — before committing to any rendering engine. + +--- + +## What stays the same when switching to Zensical + +Zensical reads `mkdocs.yml` natively. Many projects can switch the build binary without +touching a single documentation file. From Zenzic's perspective: - The `docs/` directory layout is unchanged. -- `mkdocs.yml` remains the primary navigation and plugin configuration file. -- i18n folder-mode and suffix-mode conventions are identical. +- `mkdocs.yml` remains valid as the primary navigation and configuration source; Zensical + reads it directly. +- i18n folder-mode and suffix-mode conventions are structurally identical. - `[build_context]` in `zenzic.toml` can stay as `engine = "mkdocs"` until you are ready to create `zensical.toml`. @@ -29,12 +114,12 @@ the build binary without touching a single documentation file. From Zenzic's per ## MkDocs Material best practices -### Language switcher optimisation +### Language switcher configuration When using `mkdocs-material` with the `i18n` plugin and multiple locales, the language -switcher in the site header can be controlled by two different mechanisms. Mixing them -causes routing conflicts that Zenzic — a source linter — cannot detect automatically, -but that silently break the user experience at build time. +switcher can be controlled by two different mechanisms. Mixing them causes routing conflicts +that Zenzic — a source linter — cannot detect automatically, but that silently break the +user experience at build time. **Recommended configuration:** @@ -57,9 +142,9 @@ plugins: ``` **Do not** add an `extra.alternate` block alongside `reconfigure_material: true`. -When both are present, the Material theme receives two competing switcher -definitions; depending on the plugin version the result is either a duplicated -switcher or no switcher at all: +When both are present, the Material theme receives two competing switcher definitions; +depending on the plugin version the result is either a duplicated switcher or no switcher +at all: ```yaml # ✗ — remove this block when reconfigure_material: true is set @@ -74,30 +159,31 @@ extra: ``` **Why Zenzic handles this correctly:** -When `reconfigure_material: true` is present in `mkdocs.yml`, Zenzic recognises -that the Material theme will auto-generate locale entry points (e.g. `/it/`) at -build time. These pages are never listed in `nav:` — they are synthetic routes -produced by the plugin. Zenzic marks them as **auto-generated REACHABLE** in the -Virtual Site Map so they are never reported as orphans. +When `reconfigure_material: true` is present in `mkdocs.yml`, Zenzic recognises that the +Material theme will auto-generate locale entry points (e.g. `/it/`) at build time. These +pages are never listed in `nav:` — they are synthetic routes produced by the plugin. Zenzic +marks them as **auto-generated REACHABLE** in the Virtual Site Map so they are never +reported as orphans. --- -## Phase 1 — Validate before switching +## Migration playbook + +### Phase 1 — Establish a baseline -Run the full check suite against your MkDocs project and establish a baseline: +Run the full check suite and lock in a quality baseline before changing anything: ```bash -# Make sure the docs are clean before you touch anything +# Confirm the documentation is structurally sound before touching the build layer zenzic check all zenzic score --save # persist baseline to .zenzic-score.json ``` -A clean baseline means any regression introduced during the migration is immediately visible -with `zenzic diff`. - ---- +A saved baseline means that any regression introduced during the migration is immediately +measurable with `zenzic diff`. The baseline is a snapshot of your source state — it does +not depend on any build engine being functional. -## Phase 2 — Switch the build binary +### Phase 2 — Switch the build binary Install Zensical alongside (or instead of) MkDocs: @@ -106,25 +192,24 @@ uv add --dev zensical # recommended # or: pip install zensical ``` -Run your documentation build to verify it produces identical output: +Run the documentation build to verify it produces correct output: ```bash zensical build ``` -Zenzic's checks are engine-neutral — run them after the build to confirm nothing broke: +Zenzic's checks are engine-neutral — run them after the build to confirm the source +structure is intact: ```bash zenzic check all zenzic diff # should report zero delta against the pre-migration baseline ``` ---- - -## Phase 3 — Declare Zensical identity (optional) +### Phase 3 — Declare Zensical identity (optional) -If you want Zenzic to enforce the Zensical identity contract — requiring `zensical.toml` to -be present and using the `ZensicalAdapter` for nav extraction — update `zenzic.toml`: +If you want Zenzic to enforce the Zensical structural contract — requiring `zensical.toml` +to be present and using `ZensicalAdapter` for nav extraction — update `zenzic.toml`: ```toml # zenzic.toml @@ -149,16 +234,14 @@ nav = [ ``` !!! warning "Enforcement contract" - Once `engine = "zensical"` is declared in `zenzic.toml`, `zensical.toml` **must** exist. Zenzic raises a `ConfigurationError` immediately if it is absent — there is no silent fallback to `mkdocs.yml`. This is intentional: engine identity must be provable. ---- - -## Phase 4 — Verify link integrity +### Phase 4 — Verify link integrity -The link check is your most important validation step. Run it against the completed migration: +The link check is your most important validation step. Run it against the completed +migration: ```bash # Internal links + i18n fallback resolution @@ -176,11 +259,34 @@ If the score matches the pre-migration baseline, the migration is complete. --- +## Your migration options + +Switching to Zensical is one of several paths available to a project on MkDocs. Zenzic +supports all of them with the same quality guarantee: + +| Path | `engine` in `zenzic.toml` | What Zenzic validates | +| :--- | :--- | :--- | +| Stay on MkDocs 1.x | `"mkdocs"` | Full MkDocs 1.x structural contract | +| Switch to Zensical | `"zensical"` | Zensical nav + TOML identity contract | +| Migrate to another engine | `"mkdocs"` during transition, then adapter | Source integrity throughout | +| Evaluate without committing | `--engine mkdocs` or `--engine zensical` (CLI flag) | Dry-run compatibility check | + +The `--engine` CLI flag lets you run a single check against a different engine adapter +without touching `zenzic.toml`: + +```bash +# Test whether your current source is structurally compatible with Zensical +# without declaring the switch in zenzic.toml +zenzic check all --engine zensical +``` + +--- + ## Keeping custom rules during migration `[[custom_rules]]` in `zenzic.toml` are **adapter-independent** — they fire identically -regardless of the engine. Any rules you had in place for your MkDocs project continue to work -without modification after switching to Zensical: +regardless of the engine. Any rules you had in place for your MkDocs project continue to +work without modification after switching to Zensical: ```toml # These rules work with both engines @@ -201,6 +307,7 @@ engine = "zensical" | Step | Command | Expected result | | :--- | :--- | :--- | | Baseline | `zenzic score --save` | Score saved to `.zenzic-score.json` | +| Compatibility dry-run | `zenzic check all --engine zensical` | Structural issues with Zensical adapter | | After build switch | `zenzic check all` | Same issues as before | | Regression check | `zenzic diff` | Delta = 0 | | Identity enforcement | `engine = "zensical"` in `zenzic.toml` | Requires `zensical.toml` | diff --git a/docs/it/about/index.md b/docs/it/about/index.md index 9850bd4..7047639 100644 --- a/docs/it/about/index.md +++ b/docs/it/about/index.md @@ -7,7 +7,7 @@ icon: lucide/info # Informazioni su Zenzic -Zenzic è un linter di documentazione di livello ingegneristico e un quality gate per progetti MkDocs e Zensical. +Zenzic è un linter di documentazione di livello ingegneristico e un quality gate per qualsiasi progetto basato su Markdown. Sviluppato da [PythonWoods](https://github.com/PythonWoods), è progettato per essere eseguito nelle pipeline CI/CD e rilevare i problemi nella documentazione prima che raggiungano gli utenti. diff --git a/docs/it/guide/engines.md b/docs/it/guide/engines.md index a1b2dbb..e84556e 100644 --- a/docs/it/guide/engines.md +++ b/docs/it/guide/engines.md @@ -72,6 +72,25 @@ non riconosciuta). Legge `mkdocs.yml` usando un loader YAML permissivo che ignor silenziosamente i tag sconosciuti (come l'interpolazione `!ENV` di MkDocs), quindi le configurazioni con molte variabili d'ambiente funzionano senza alcuna pre-elaborazione. +### Limiti dell'analisi statica + +`MkDocsAdapter` analizza `mkdocs.yml` come **dati statici**. Non esegue la pipeline di +build di MkDocs. Questo significa: + +- **Tag `!ENV`** — trattati silenziosamente come `null`. Se la nav dipende da + interpolazione di variabili d'ambiente a runtime, le voci nav che dipendono da quei + valori saranno assenti dalla visione di Zenzic. +- **Nav generata dai plugin** — plugin che mutano la nav a runtime (es. + `mkdocs-awesome-pages`, `mkdocs-literate-nav`) producono un albero di navigazione + che Zenzic non vede mai. Le pagine incluse solo da questi plugin vengono segnalate + come orfane. +- **Macro** — `mkdocs-macros-plugin` (template Jinja2 in Markdown) non viene + valutato. I link all'interno di espressioni macro non vengono validati. + +Per progetti che dipendono fortemente dalla generazione dinamica della nav, aggiungi i +percorsi generati dai plugin a `excluded_dirs` in `zenzic.toml` per sopprimere i falsi +positivi sugli orfani finché non sarà disponibile un adapter nativo. + ### Configurazione minima ```toml diff --git a/docs/it/guide/migration.md b/docs/it/guide/migration.md index fb9626a..f4de94c 100644 --- a/docs/it/guide/migration.md +++ b/docs/it/guide/migration.md @@ -5,24 +5,109 @@ icon: lucide/arrow-right-left -# Migrazione da MkDocs a Zensical +# Migrazione a Zensical -Zenzic funge da guardia di integrità continua durante la migrazione. Poiché analizza i **file -sorgente** e legge la configurazione come dati semplici — senza mai importare o eseguire il -framework di build — funziona correttamente con entrambi gli engine contemporaneamente e può -validare la documentazione prima, durante e dopo il passaggio. +!!! note "Zenzic vs Zensical" + **Zenzic** è il linter di documentazione descritto in questo sito — lo strumento + che esegui con `zenzic check all`. + + **Zensical** è un motore di build separato (successore compatibile di MkDocs 1.x). Questa + pagina descrive come usare Zenzic come rete di sicurezza mentre passi il tuo *motore di + build* da MkDocs a Zensical. + + Non è necessario usare Zensical per usare Zenzic. Zenzic funziona con MkDocs, Zensical, + cartelle Markdown Vanilla e qualsiasi motore che abbia un adapter. --- -## Cosa rimane invariato +## I tuoi file sorgente sopravvivono al motore di build + +I motori di build evolvono. Cambiano formato di configurazione, abbandonano i sistemi di +plugin, si integrano con piattaforme commerciali o semplicemente smettono di essere +manutenuti. Quando succede, le risorse a rischio non sono i tuoi file Markdown — quelli +sono testo semplice e saranno sempre leggibili. Ciò che è a rischio è il tuo **investimento +in struttura**: la navigazione, le convenzioni i18n, il grafo dei link, l'organizzazione +degli asset costruita in anni di lavoro. + +Il ruolo di Zenzic in una migrazione non è rendere il passaggio più veloce. È rendere il +passaggio **provabilmente sicuro** — garantendo che ogni invariante strutturale a cui tieni +sia misurato prima, durante e dopo il cambio, e che qualsiasi regressione sia immediatamente +visibile e attribuita con precisione. + +Questa garanzia poggia su un unico principio architetturale: **Zenzic analizza i sorgenti, +non il build**. Legge `mkdocs.yml`, `zensical.toml` e i tuoi file Markdown come dati semplici. +Non importa né esegue mai un framework di build. Questo significa: + +- Zenzic comprende la struttura della tua documentazione anche se il binario di build che la + interpretava non funziona più. +- Eseguire `zenzic check all` su un progetto nel mezzo di una migrazione produce la stessa + analisi di un progetto pienamente operativo — perché i file sorgente non sono cambiati. +- Cambiare `engine` in `zenzic.toml` (una sola riga) è tutto ciò che serve per validare se + il contenuto è strutturalmente compatibile con un nuovo motore, senza toccare un singolo + file Markdown. + +Questo è il Porto Sicuro (Safe Harbor): **uno strato di validazione fisso che rimane valido +prima, durante e dopo qualsiasi cambio di motore di build**. + +--- + +## Il MkDocsAdapter: preservazione dei dati come plain data + +Il `MkDocsAdapter` tratta `mkdocs.yml` come una struttura dati pura — un insieme di percorsi +nav, dichiarazioni di plugin e impostazioni locale. Estrae ciò di cui ha bisogno (albero nav, +configurazione i18n, flag di plugin come `reconfigure_material`) e passa il risultato al Rule +Engine come oggetti Python tipizzati. Non chiama mai `mkdocs build`, non importa mai `mkdocs`, +e non dipende mai dall'installazione o dal funzionamento di alcun plugin. -Zensical è un successore compatibile di MkDocs. Legge `mkdocs.yml` nativamente, quindi molti progetti possono -cambiare il binario di build senza toccare un singolo file di documentazione. Dal punto di vista -di Zenzic: +La conseguenza pratica è che `MkDocsAdapter` è il **custode dello standard dell'ecosistema +classico pluggable**. Finché il tuo `mkdocs.yml` descrive una struttura MkDocs 1.x valida, +Zenzic la comprenderà e la validerà — indipendentemente da ciò che qualsiasi binario di build +supporti o meno. Se esegui `zenzic check all` con `engine = "mkdocs"`, stai testando il tuo +contenuto rispetto al contratto strutturale documentato di MkDocs 1.x, non rispetto a nessuna +versione binaria specifica. + +Questo rende l'output di Zenzic un **certificato di qualità portabile**: se Zenzic dice che la +tua documentazione è strutturalmente corretta, questa affermazione è vera indipendentemente da +quale motore userai per renderizzarla domani. + +--- + +## i18n: validare la struttura indipendentemente dal rendering + +Il plugin `i18n` di MkDocs (convenzioni folder-mode e suffix-mode) definisce una struttura di +contenuto ben specificata: directory locale, catene di fallback, shadowing della nav per locale. +Zenzic codifica questa specifica in `MkDocsAdapter` e nella Virtual Site Map indipendentemente +da qualsiasi implementazione di rendering. + +Questo è importante durante le transizioni tra motori. Quando un motore di build sta ancora +maturando il suo supporto i18n, esiste una finestra in cui le *regole strutturali* del tuo +setup i18n sono ben definite, ma la *capacità di rendering* del motore potrebbe non essere +ancora completa. Zenzic opera interamente nel dominio strutturale: + +- **Risoluzione dei link cross-locale** — un link da una pagina italiana a un asset + disponibile solo in inglese viene risolto rispetto alla catena di fallback definita in + `mkdocs.yml`, non rispetto all'output del build. +- **Rilevamento Ghost Routes** — i punti di ingresso locale generati al momento del build + (es. `/it/`) vengono marcati `REACHABLE` nella VSM in modo da non essere mai segnalati + come orfani, anche se non sono mai stati renderizzati. +- **Soppressione delle directory locale** — i file in `docs/it/`, `docs/fr/`, ecc. vengono + classificati come shadow locale, non come orfani. + +Puoi quindi validare una struttura i18n complessa con Zenzic e avere la certezza della sua +coerenza interna — il grafo dei link è corretto, le catene di fallback sono intatte, la nav +è completa — prima di impegnarti con qualsiasi motore di rendering. + +--- + +## Cosa rimane invariato passando a Zensical + +Zensical legge `mkdocs.yml` nativamente. Molti progetti possono cambiare il binario di build +senza toccare un singolo file di documentazione. Dal punto di vista di Zenzic: - La struttura della directory `docs/` rimane invariata. -- `mkdocs.yml` rimane il file principale di configurazione di navigazione e plugin. -- Le convenzioni i18n in folder-mode e suffix-mode sono identiche. +- `mkdocs.yml` rimane valido come sorgente principale di navigazione e configurazione; + Zensical lo legge direttamente. +- Le convenzioni i18n in folder-mode e suffix-mode sono strutturalmente identiche. - `[build_context]` in `zenzic.toml` può rimanere `engine = "mkdocs"` fino a quando non sei pronto a creare `zensical.toml`. @@ -30,12 +115,12 @@ di Zenzic: ## Best practice per MkDocs Material -### Ottimizzazione dello switcher di lingua +### Configurazione dello switcher di lingua Quando si usa `mkdocs-material` con il plugin `i18n` e più lingue, lo switcher di lingua -nell'intestazione del sito può essere controllato da due meccanismi distinti. Mescolarli -produce conflitti di routing che Zenzic — in quanto linter dei sorgenti — non può rilevare -automaticamente, ma che rompono silenziosamente l'esperienza utente in fase di build. +può essere controllato da due meccanismi distinti. Mescolarli produce conflitti di routing +che Zenzic — in quanto linter dei sorgenti — non può rilevare automaticamente, ma che +rompono silenziosamente l'esperienza utente in fase di build. **Configurazione raccomandata:** @@ -75,30 +160,32 @@ extra: ``` **Perché Zenzic gestisce questo correttamente:** -Quando `reconfigure_material: true` è presente in `mkdocs.yml`, Zenzic riconosce -che il tema Material genererà automaticamente i punti di ingresso per le lingue (es. `/it/`) -in fase di build. Queste pagine non sono mai elencate in `nav:` — sono rotte sintetiche -prodotte dal plugin. Zenzic le marca come **REACHABLE auto-generate** nella -Virtual Site Map in modo che non vengano mai segnalate come orfane. +Quando `reconfigure_material: true` è presente in `mkdocs.yml`, Zenzic riconosce che il +tema Material genererà automaticamente i punti di ingresso per le lingue (es. `/it/`) in +fase di build. Queste pagine non sono mai elencate in `nav:` — sono rotte sintetiche +prodotte dal plugin. Zenzic le marca come **REACHABLE auto-generate** nella Virtual Site +Map in modo che non vengano mai segnalate come orfane. --- -## Fase 1 — Valida prima di cambiare +## Piano di migrazione + +### Fase 1 — Stabilisci un baseline -Esegui la suite completa di controlli sul tuo progetto MkDocs e stabilisci un baseline: +Esegui la suite completa di controlli e registra un baseline (punto di riferimento) di +qualità prima di cambiare qualsiasi cosa: ```bash -# Assicurati che i docs siano puliti prima di toccare qualcosa +# Conferma che la documentazione sia strutturalmente corretta prima di toccare il layer di build zenzic check all zenzic score --save # persisti il baseline in .zenzic-score.json ``` -Un baseline pulito rende immediatamente visibile qualsiasi regressione introdotta durante la -migrazione con `zenzic diff`. - ---- +Un baseline salvato significa che qualsiasi regressione introdotta durante la migrazione è +immediatamente misurabile con `zenzic diff`. Il baseline è uno snapshot dello stato dei +sorgenti — non dipende dal funzionamento di alcun motore di build. -## Fase 2 — Cambia il binario di build +### Fase 2 — Cambia il binario di build Installa Zensical insieme a (o al posto di) MkDocs: @@ -107,26 +194,25 @@ uv add --dev zensical # raccomandato # oppure: pip install zensical ``` -Esegui la build della documentazione per verificare che produca output identico: +Esegui la build della documentazione per verificare che produca output corretto: ```bash zensical build ``` -I controlli di Zenzic sono engine-neutral — eseguili dopo la build per confermare che nulla si -sia rotto: +I controlli di Zenzic sono engine-neutral (indipendenti dal motore di build) — eseguili +dopo la build per confermare che la struttura dei sorgenti sia intatta: ```bash zenzic check all zenzic diff # dovrebbe riportare zero delta rispetto al baseline pre-migrazione ``` ---- - -## Fase 3 — Dichiara l'identità Zensical (opzionale) +### Fase 3 — Dichiara l'identità Zensical (opzionale) -Se vuoi che Zenzic imponga il contratto di identità Zensical — richiedendo la presenza di -`zensical.toml` e usando `ZensicalAdapter` per l'estrazione della nav — aggiorna `zenzic.toml`: +Se vuoi che Zenzic imponga il contratto strutturale di Zensical — richiedendo la presenza +di `zensical.toml` e usando `ZensicalAdapter` per l'estrazione della nav — aggiorna +`zenzic.toml`: ```toml # zenzic.toml @@ -151,15 +237,12 @@ nav = [ ``` !!! warning "Contratto di enforcement" - Una volta dichiarato `engine = "zensical"` in `zenzic.toml`, `zensical.toml` **deve** esistere. Zenzic solleva un `ConfigurationError` immediatamente se è assente — non c'è fallback silenzioso a `mkdocs.yml`. Questo è intenzionale: l'identità dell'engine deve essere provabile. ---- - -## Fase 4 — Verifica l'integrità dei link +### Fase 4 — Verifica l'integrità dei link Il controllo dei link è il passo di validazione più importante. Eseguilo sulla migrazione completata: @@ -180,11 +263,34 @@ Se il punteggio corrisponde al baseline pre-migrazione, la migrazione è complet --- +## Le tue opzioni di migrazione + +Passare a Zensical è una delle diverse strade disponibili a un progetto su MkDocs. Zenzic +le supporta tutte con la stessa garanzia di qualità: + +| Percorso | `engine` in `zenzic.toml` | Cosa valida Zenzic | +| :--- | :--- | :--- | +| Rimane su MkDocs 1.x | `"mkdocs"` | Contratto strutturale completo MkDocs 1.x | +| Passa a Zensical | `"zensical"` | Nav Zensical + contratto identità TOML | +| Migra a un altro motore | `"mkdocs"` durante transizione, poi adapter | Integrità sorgenti durante il cambio | +| Valuta senza impegnarsi | flag CLI `--engine mkdocs` o `--engine zensical` | Controllo compatibilità dry-run | + +Il flag CLI `--engine` permette di eseguire un singolo controllo contro un adapter diverso +senza toccare `zenzic.toml`: + +```bash +# Testa se i tuoi sorgenti attuali sono strutturalmente compatibili con Zensical +# senza dichiarare il passaggio in zenzic.toml +zenzic check all --engine zensical +``` + +--- + ## Mantenere le regole custom durante la migrazione Le `[[custom_rules]]` in `zenzic.toml` sono **indipendenti dall'adapter** — si attivano -identicamente indipendentemente dall'engine. Qualsiasi regola in vigore per il tuo progetto MkDocs -continua a funzionare senza modifiche dopo il passaggio a Zensical: +identicamente indipendentemente dall'engine. Qualsiasi regola in vigore per il tuo progetto +MkDocs continua a funzionare senza modifiche dopo il passaggio a Zensical: ```toml # Queste regole funzionano con entrambi gli engine @@ -205,6 +311,7 @@ engine = "zensical" | Passo | Comando | Risultato atteso | | :--- | :--- | :--- | | Baseline | `zenzic score --save` | Score salvato in `.zenzic-score.json` | +| Dry-run compatibilità | `zenzic check all --engine zensical` | Problemi strutturali con adapter Zensical | | Dopo il cambio di build | `zenzic check all` | Stessi problemi di prima | | Controllo regressioni | `zenzic diff` | Delta = 0 | | Enforcement identità | `engine = "zensical"` in `zenzic.toml` | Richiede `zensical.toml` | diff --git a/docs/it/usage/index.md b/docs/it/usage/index.md index 5ee9620..b4cbc7e 100644 --- a/docs/it/usage/index.md +++ b/docs/it/usage/index.md @@ -90,39 +90,33 @@ Usalo in locale, come hook di pre-commit, nelle pipeline CI o per audit una-tant Pattern standard da dipendenza dev con virtual environment locale al progetto. -### Validazione MkDocs — extra `zenzic[docs]` +### L'extra `zenzic[docs]` — per il rendering, non per il linting -Il core engine di Zenzic è privo di dipendenze per design: validare link, snippet, riferimenti -e Shield richiede solo `zenzic`. Lo stack MkDocs (tema Material, plugin, ecc.) è necessario -solo per **renderizzare** la documentazione — non per validarla. +Zenzic legge `mkdocs.yml` come YAML semplice tramite il proprio `_PermissiveYamlLoader` +(una sottoclasse di `yaml.SafeLoader` che ignora silenziosamente i tag specifici degli +engine come `!ENV`). **Non importa `mkdocs`, `mkdocs-material` né alcun pacchetto plugin** +per analizzare la configurazione. PyYAML è una dipendenza core — nessun extra necessario. -Se il tuo progetto usa `mkdocs.yml` e vuoi che Zenzic lo validi come parte dei controlli, -installa l'extra opzionale: +L'extra `[docs]` (`mkdocs-material`, `mkdocstrings`, `mkdocs-minify-plugin`, +`mkdocs-static-i18n`) è lo stack di build usato per **renderizzare il sito di +documentazione di Zenzic stesso**. È una dipendenza per i contributori, non per gli utenti: -=== ":simple-astral: uv" - - ```bash - # Aggiungi l'extra [docs] insieme a Zenzic - uv add --dev "zenzic[docs]" +- **Fare il lint del tuo progetto MkDocs:** installa solo `zenzic`. +- **Buildare il sito di documentazione di Zenzic localmente:** installa `zenzic[docs]`. - # Oppure come esecuzione temporanea: - uvx "zenzic[docs]" check all - ``` - -=== ":simple-pypi: pip" - - ```bash - pip install "zenzic[docs]" - ``` +```bash +# Fare il lint di qualsiasi progetto MkDocs — nessun extra necessario +uvx zenzic check all -L'extra `[docs]` installa `mkdocs-material`, `mkdocstrings`, `mkdocs-minify-plugin` e -`mkdocs-static-i18n` — lo stesso stack usato per costruire il sito di documentazione di -Zenzic. Se esegui solo `zenzic check all` senza renderizzare il sito, ometti l'extra. +# Buildare il sito docs di Zenzic (solo workflow contributori) +uv add --dev "zenzic[docs]" +mkdocs serve +``` -!!! note "Hugo, Zensical e altri engine" - L'extra `[docs]` è specifico per MkDocs. Per Zensical e altri adapter, installa il - pacchetto adapter di terze parti corrispondente (es. `pip install zenzic-hugo-adapter`). - Nessun extra è richiesto per `VanillaAdapter` (cartelle Markdown semplici). +!!! note "Adapter di terze parti" + Gli adapter di terze parti (es. un ipotetico `zenzic-hugo-adapter`) sono pacchetti + installabili separati — non extra di `zenzic` stesso. Nessun extra è richiesto per + `VanillaAdapter` (cartelle Markdown semplici). --- @@ -186,12 +180,13 @@ Con il baseline stabilito, esegui Zenzic su ogni commit e pull request: ```bash # Hook pre-commit o step CI +# --strict: valida URL esterni + tratta i warning come errori zenzic check all --strict -# Salva il baseline qualità sul branch main +# Salva il baseline (punto di riferimento) qualità sul branch main zenzic score --save -# Blocca le PR che regrediscono il baseline +# Blocca le PR che regrediscono il baseline di più di 5 punti zenzic diff --threshold 5 ``` diff --git a/docs/usage/index.md b/docs/usage/index.md index 5182571..286edf4 100644 --- a/docs/usage/index.md +++ b/docs/usage/index.md @@ -90,39 +90,33 @@ in local development, as a pre-commit hook, in CI pipelines, or for one-off audi Standard dev-dependency pattern with a project-local virtual environment. -### MkDocs validation — `zenzic[docs]` extra +### The `zenzic[docs]` extra — for rendering, not linting -Zenzic's core engine is dependency-free by design: validating links, snippets, references, -and the Shield requires nothing beyond `zenzic` itself. The MkDocs stack (Material theme, -plugins, etc.) is only needed to **render** your documentation — not to lint it. +Zenzic reads `mkdocs.yml` as plain YAML using its own `_PermissiveYamlLoader` (a +`yaml.SafeLoader` subclass that silently ignores engine-specific tags like `!ENV`). It +**does not import `mkdocs`, `mkdocs-material`, or any plugin package** to parse your +configuration. PyYAML is a core dependency — no extra required. -If your project uses `mkdocs.yml` and you want to validate it as part of the Zenzic checks, -install the optional extra: +The `[docs]` extra (`mkdocs-material`, `mkdocstrings`, `mkdocs-minify-plugin`, +`mkdocs-static-i18n`) is the build stack used to **render Zenzic's own documentation +site**. It is a contributor dependency, not a user dependency: -=== ":simple-astral: uv" - - ```bash - # Add the [docs] extra alongside Zenzic - uv add --dev "zenzic[docs]" +- **Linting your MkDocs project:** install `zenzic` only. +- **Building Zenzic's documentation site locally:** install `zenzic[docs]`. - # Or as an ephemeral run: - uvx "zenzic[docs]" check all - ``` - -=== ":simple-pypi: pip" - - ```bash - pip install "zenzic[docs]" - ``` +```bash +# Lint any MkDocs project — no extras needed +uvx zenzic check all -The `[docs]` extra installs `mkdocs-material`, `mkdocstrings`, `mkdocs-minify-plugin`, and -`mkdocs-static-i18n` — the same stack used to build Zenzic's own documentation site. If you -**only** run `zenzic check all` without rendering the site, skip the extra entirely. +# Build Zenzic's own docs site (contributor workflow only) +uv add --dev "zenzic[docs]" +mkdocs serve +``` -!!! note "Hugo, Zensical, and other engines" - The `[docs]` extra is specific to MkDocs. For Zensical and other engine adapters, install - the corresponding third-party adapter package (e.g. `pip install zenzic-hugo-adapter`). - No extra is required for `VanillaAdapter` (plain Markdown folders). +!!! note "Third-party engine adapters" + Third-party adapters (e.g. a hypothetical `zenzic-hugo-adapter`) are separate + installable packages — not extras of `zenzic` itself. No extra is required for + `VanillaAdapter` (plain Markdown folders). --- @@ -186,12 +180,13 @@ With the baseline established, run Zenzic on every commit and pull request: ```bash # Pre-commit hook or CI step +# --strict: validate external URLs + treat warnings as errors zenzic check all --strict # Save a quality baseline on main zenzic score --save -# Block PRs that regress the baseline +# Block PRs that regress the baseline by more than 5 points zenzic diff --threshold 5 ``` @@ -212,6 +207,10 @@ root, Zenzic loads the corresponding **adapter** which provides: - **i18n fallback** — cross-locale links are resolved correctly instead of being flagged as broken. - **Locale directory suppression** — files under `docs/it/`, `docs/fr/`, etc. are not reported as orphans. +- **Ghost Routes** — when `mkdocs-material` with `reconfigure_material: true` generates locale + entry points (e.g. `/it/`) at build time, those pages never appear in `nav:`. Zenzic + marks them `REACHABLE` automatically in the [Virtual Site Map](../architecture.md#virtual-site-map-vsm) + so they are never reported as false orphans — with no manual exclusion list required. ### Vanilla mode