Přeskočit obsah

Zensical — poznámky pro Claude Code

Interní poznámka k nástroji (spíš pro Claude Code než pro čtenáře CMS dokumentace), zařazená v nav pod „Ostatní → Zensical".

Jak Zensical funguje

  • Nástupce MkDocs + mkdocs-material (autoři tématu s vývojem MkDocs po roce 2024 nejsou spokojení, Zensical je jejich nový projekt).
  • Instalace do .venv (stejně jako předtím MkDocs): pip install zensical.
  • Config: zensical.toml místo mkdocs.yml — TOML místo YAML.
  • Příkazy (viz zensical-install / zensical-build / zensical-serve v rootu):
  • zensical build — build podle docs_dir/site_dir v configu (u nás docsvar/docs-site, /var/* je v .gitignore)
  • zensical serve -a 127.0.0.1:8088 — dev server s live reloadem
  • Build cache: .cache/ v rootu — Zensical si tam sám vytvoří .gitignore s *, nic není třeba ručně ignorovat.
  • Markdown extensions mají bohaté defaulty (celá pymdownx sada) — není nutné je vypisovat všechny ručně jako v mkdocs.yml, stačí přidat jen to, co chceš změnit.

Validace odkazů — důležitý rozdíl oproti MkDocs

MkDocs rozbité [text](#anchor) odkazy uvnitř dokumentů tiše ignoroval. Zensical při buildu warnuje (anchor does not exist), build ale i tak projde (exit 0). Ber to vážně — je to reálný broken link v obsahu, ne false positive.

Slugify nadpisů

Default: ASCII bez diakritiky (Popis Cache třídy#popis-cache-tridy). V tomto projektu to tak necháváme. Pokud by bylo někdy potřeba diakritiku zachovat (kompatibilita se starými odkazy), jde to přepsat v zensical.toml:

[project.markdown_extensions.toc]
permalink = true
slugify = { object = "pymdownx.slugs.slugify", kwds = { case = "lower" } }

(markdown.extensions.toc.slugify jako object nefunguje — resolver v Zensicalu očekává tovární funkci typu pymdownx.slugs.slugify(**kwds) -> callable, ne přímo slugify funkci.)

TOML nav — jak na to (a proč je otravnější než YAML)

Zensical nepoužívá nav: seznam z YAML, ale pole tabulek pod [project.nav].

Plochá položka:

[[project.nav]]
"Úvod" = "index.md"

Sekce s podstránkami (bez dalšího zanoření) — inline array je OK:

[[project.nav]]
"Ostatní" = [
    { "Refaktor modulů" = "REFACTOR_ADMIN_MODULES.md" },
    { "Architektura kostek" = "cubes-architecture.md" },
]

Sekce, která sama obsahuje další sekce (zanoření o úroveň víc) — inline array tady nejde zapsat čitelně, musí se na to dotted array-of-tables syntax:

[[project.nav]]

[[project.nav.App]]
"Přehled" = "app/index.md"

[[project.nav.App]]
"Admin Auth (Passkey)" = [
    { "Přehled" = "app/admin/auth-passkey.md" },
    { Autorita = "app/admin/auth-passkey-authority.md" },
]

Ten prázdný [[project.nav]] řádek před [[project.nav.App]] musí být — vytváří kontejnerovou položku pole nav, do které se pak klíč App doplňuje. Bez něj to nejde naparsovat do stejné struktury jako plochý zápis.

Nepiš to ručně — generuj to skriptem

Ruční psaní vnořeného TOML nav je zdroj chyb (kombinace inline arrays a array-of-tables se snadno popletou). Osvědčený postup z migrace mkdocs.ymlzensical.toml:

import yaml, tomli_w, tomllib

with open('mkdocs.yml') as f:
    data = yaml.safe_load(f)

def conv_nav(items):
    out = []
    for item in items:
        (k, v), = item.items()
        out.append({k: v} if isinstance(v, str) else {k: conv_nav(v)})
    return out

nav = conv_nav(data['nav'])
toml_str = tomli_w.dumps({"project": {"nav": nav}})

# ověř round-trip, než to vlepíš do zensical.toml
with open('/tmp/nav_check.toml', 'w') as f:
    f.write(toml_str)
with open('/tmp/nav_check.toml', 'rb') as f:
    parsed = tomllib.load(f)
assert parsed['project']['nav'] == nav

tomli_w formátuje výstup „divně" (prázdné [[project.nav]] bloky, ploché klíče místo hezky odsazených objektů) — to je v pořádku, je to sémanticky validní TOML. Neuprošovat ručně, jen zkontrolovat round-trip a vložit.

tomli_w/tomllib nejsou v projektovém .venv defaultně — pip install tomli_w (tomllib je stdlib od Pythonu 3.11).

Update — projekt je 0.0.x, hlídej breaking changes

Aktuální verze (červenec 2026): 0.0.51. Zensical je pre-1.0 (0.0.x), vydává nové verze často a bez záruky zpětné kompatibility configu (zensical.toml formát i chování defaultů se může měnit mezi patch verzemi).

Kdy updatovat: - Ne automaticky/slepě. Jen když je konkrétní důvod (bugfix, nová feature, kterou chceš použít) — ne "jen proto že je nová verze". - Neinstaluj do CI/produkčního buildu bez pinned verze — viz níže.

Jak updatovat:

source .venv/bin/activate
pip install --upgrade zensical
zensical --version

Po každém update: 1. ./zensical-build — zkontroluj, že build projde bez nových warningů/chyb. 2. Projdi pár klíčových stránek vizuálně (./zensical-serve) — u pre-1.0 nástroje se může tiše změnit chování (např. jiný default slugify, jiná struktura nav). 3. Pokud něco selže, zkontroluj changelog/release notes na https://github.com/zensical/zensical/releases než začneš ladit zensical.toml.

Pinning verze: Pokud chceš verzi zafixovat (doporučeno až projekt stabilizuje API), uprav zensical-install:

pip install zensical==0.0.51
Zatím necháno bez pinu záměrně — projekt je nový, chceme dostávat bugfixy.

Workflow při úpravě nav

  1. Uprav zensical.toml.
  2. ./zensical-build — musí hlásit No issues found.
  3. Pokud hlásí anchor does not exist, oprav skutečný odkaz v .md souboru (ne config) — viz sekce výše o validaci odkazů.