Wikis
W / Dokumentace

Wikit

Šablona, na které běží všechny tyhle wiki.

Vezme GitHub wiki nebo markdown v repozitáři, jednou ho vykreslí a servíruje jako rychlý web s vyhledáváním — přesně takový, jaký vidíš tady. Jedna složka, jeden config.php, žádná databáze.

Stáhnout Wikit .zip
Verze
2026-10-15
Velikost
1,4 MB rozbaleno · 478 souborů
Potřebuje
PHP 8.5 · git · intl, mbstring
Za pět minut
  1. 01

    Stáhni a rozbal

    Jedna složka, všechno uvnitř — i knihovny.

    unzip wikit-2026-10-15.zip
    mv wikit wiki.example.com
  2. 02

    Nastav config.php

    Repozitář, název, jedna barva. Zbytek se dopočítá.

    repo.owner   = 'you'
    repo.name    = 'notes'
    brand.accent = '#2F6F8F'
  3. 03

    První crawl

    Naklonuje wiki, vykreslí stránky, postaví index.

    php bin/sync.php
  4. 04

    Drž čerstvé

    Cron po patnácti minutách, nebo GitHub webhook.

    sudo ./bin/cron.sh install --host
Dokumentace

PHP front-end pro GitHub wiki — nebo pro markdown uvnitř libovolného GitHub repozitáře. Naklonuje git repozitář, každou stránku jednou vykreslí, zaindexuje ji pro vyhledávání a servíruje výsledek jako web, který působí staticky, v duchu mezinárodního typografického stylu — ve světlém i tmavém režimu.

Je stavěný tak, aby se forkoval pro každý repozitář: zkopíruj složku, uprav config.php, spusť synchronizaci. Na nic dalšího sahat nemusíš.


Co umí

Crawluje git clone/pull wiki (<repo>.wiki.git) nebo přímo repozitáře
Vykresluje CommonMark + GFM (tabulky, úkolové seznamy, přeškrtnutí, autolinky, poznámky pod čarou) a diagramy ```mermaid
Rozumí wiki navigace z _Sidebar.md, _Footer.md, [[Gollum odkazy]], relativní odkazy na stránky, holé <img src="diagram.svg">, GitHub upozornění (> [!NOTE])
Indexuje sekce po nadpisech → JSON index na disku (nebo MySQL FULLTEXT)
Servíruje stránky, úvod, obsah, stránku hledání, paletu příkazů ⌘K, JSON API pro hledání, sitemap, média
Prochází soubory /files — vlastní strom repozitáře: složky, velikosti, data, prohlížeč souborů s označenou syntaxí a čísly řádků, náhledy obrázků, odkazy na GitHub blob/raw
Zná git každá stránka ukazuje skutečné datum poslední úpravy a autora z historie wiki

HTML stránek se vykresluje při synchronizaci, takže zobrazení stránky je jeden řádek z indexu a nula parsování markdownu.


Fork

cp -r wikit wiki.myproject.com        # wikit/ = rozbalené stažení
cd wiki.myproject.com
cp config.local.example.php config.local.php
  1. config.php — jediný soubor, který musíš upravit:
    • site.* — název, podtitul, popis, locale, časové pásmo
    • repo.* — owner, name, mode (wiki nebo repo), volitelně path, branch, home_page
    • brand.* — jedna barva accent řídí celou paletu; logo_icon je libovolný název z Iconify, nebo nasměruj logo_svg na vlastní soubor
    • type.* — rodiny písem + specifikace Google Fonts (nebo '' jen pro lokální písma)
    • theme.* — výchozí režim, zrnitost, zaoblení rohů
    • features.* — zapíná/vypíná hledání, obsah stránky, zpětné odkazy, předchozí/další, marquee, sitemap…
    • site.language — v lang/ jsou cs, en a de; i18n v config.php přepíše jednotlivé texty
  2. config.local.php — heslo k DB, sync token, tajemství webhooku, PAT pro soukromé wiki.
  3. Úložiště — ve výchozím stavu není co nastavovat (db.driver = 'file'). Na 'mysql' přepni, jen když ho opravdu chceš; viz Potřebuje databázi? níže.
  4. První crawl:
    docker exec php-server php /var/www/wiki.myproject.com/bin/sync.php
    

Režim wiki vs. režim repozitáře

repo.mode = 'wiki' (výchozí) crawluje github.com/<owner>/<repo>.wiki.git: ploché stránky, navigace z _Sidebar.md, odkazy na úpravy ve wiki.

repo.mode = 'repo' crawluje markdown uvnitř repozitáře, včetně vnořených složek. repo.path ho zúží ('docs'), prázdná hodnota znamená všechno.

režim wiki režim repozitáře
Soubory ploché, kořen repozitáře rekurzivně; přeskakuje node_modules, vendor, dist, build, .github, test(s)
Slugy Cesta-paketu system/docker; README.md/index.md složky se stane složkou samotnou
Navigace _Sidebar.md jedna skupina na složku nejvyšší úrovně, úvodní stránka první
Odkazy názvy wiki stránek řešené vůči složce dokumentu, který odkazuje, včetně ../
Odkaz na úpravu /wiki/<Page>/_edit /edit/<branch>/<path>

Prohlížeč souborů (features.file_browser) funguje v obou režimech — ve wiki ukazuje přílohy, v repozitáři je hlavní věcí. Strom se zachytí při synchronizaci, spolu s datem poslední změny každé cesty, které pochází z jednoho omezeného průchodu git log, ne z jednoho procesu na soubor. Textové soubory se vykreslí přímo s čísly řádků až do velikosti content.file_max_bytes (512 KB); obrázky mají náhled; cokoli binárního nebo většího odkazuje na GitHub. Stránka, jejíž slug je doslova files, má přednost před prohlížečem.

Všechno se otevírá uvnitř aplikace: výpisy, prohlížeč i /raw/<path>, které posílá soubor rovnou z klonu jako přílohu (neutrální content type, nosniff, cesta hlídaná přes realpath) — stahování tedy nezávisí na tom, jestli je GitHub dostupný nebo repozitář veřejný. Příliš velké a binární soubory, které nejde zobrazit, nabídnou místo slepé uličky právě tohle stažení.

Dva detaily kolem proxy, oba naučené tvrdou cestou:

Vlastní vhost: pravidlo, které blokuje přípony, musí být ukotvené na jeden segment cesty (^/[^/]+\.(md|json|lock|…)$). Neukotvené chytí i /files/portainer_apps.json a prohlížeč pak vrací 403 právě na souborech, kvůli kterým tam lidé přišli.

Cizí proxy: zabezpečené okrajové servery běžně odmítají každý požadavek, jehož cesta končí na .yml, .sh, .conf, .env, .md, .ini, .log, .sql. To prohlížeč souborů úplně zabije, a ten server ti nemusí patřit. Proto URL souborů nesou název souboru v query — /files/docker/compose/adguard?f=docker-compose.yml — a cesta zůstává bez přípony. Složky mají obyčejné cesty, nemají o co zakopnout. Když ti žádné takové pravidlo nestojí v cestě, nastav content.safe_file_urls = false pro hezké holé cesty. Změna potřebuje novou synchronizaci, protože odkazy uvnitř článků se zapékají při crawlu.

Mermaid

GitHub vykresluje bloky ```mermaid jako diagramy, takže tohle taky. Knihovna se načte jen na stránkách, které nějaký obsahují, a při přepnutí motivu se překreslí, aby diagram nikdy nezůstal ve špatné paletě. Když je CDN zablokované nebo je diagram vadný, vrátí se původní blok kódu místo prázdného rámečku. features.mermaid to zapíná; mermaid.cdn / mermaid.light / mermaid.dark volí zdroj a motivy.

Článek ve složce ukazuje složku

V režimu repozitáře končí článek, který leží ve složce, tím, co dalšího v té složce je — soubory a podsložky; sousední markdown se vynechá, protože to jsou stránky a už jsou v navigaci. system/docker/README.md je šest slov textu a za nimi dva skripty, o kterých mluví; kořenové README následuje nejvyšší úroveň repozitáře. V markdownu se nic psát nemusí a zůstává to správně, i když soubory přibývají a mizí. Přepíná se přes features.folder_contents.

Soubory uvnitř článků

Článek si může vtáhnout skutečný soubor místo kopie, která zastará:

![[docker/compose/adguard/docker-compose.yml]]      celý soubor
![[docker/compose/adguard/docker-compose.yml#L10-L12]]   výňatek, skutečná čísla řádků zůstanou
![[docker/compose/adguard/]]                        výpis složky

Cesty se řeší vůči složce článku (včetně ../). Obrázky se vloží jako obrázky, binární a příliš velké soubory ukážou upozornění, chybějící cíl to řekne místo tichého selhání a direktiva uvnitř bloku kódu zůstane nedotčená, takže můžeš dokumentovat samotnou syntaxi. Rozbalení proběhne při synchronizaci, takže zobrazení stránky je pořád jeden uložený řádek.

Obyčejný markdown odkaz na ne-markdownový soubor, který v repozitáři existuje — [compose soubor](docker/compose/adguard/docker-compose.yml) — se stane štítkem souboru odkazujícím do prohlížeče místo mrtvého odkazu na stránku, která nikdy neexistovala. Přepíná se přes content.embeds.

Jazyky

Jeden web mluví jedním jazykem. Každý text rozhraní žije v lang/<kód>.json a site.language vybírá soubor:

cp lang/en.json lang/fr.json      # přelož hodnoty, klíče nech
# config.php:  'language' => 'fr'

Přiložené jsou cs, en a de. Neznámý kód spadne na en a data používají site.locale (ICU) — prázdná hodnota znamená „stejně jako jazyk“. Pro změnu jediného textu bez sahání do souboru ho uveď pod i18n v config.php; má přednost před JSON.

Připojení pod rozcestník (<hub>/<name>/)

Víc wiki může sdílet jednu doménu: každý fork leží v <hub>/wikis/<name> a nginx vhost rozcestníku ho připojí na /<name>/ (z disku jen assets/, všechno ostatní do index.php daného forku). Pro novou wiki:

  1. cp -a šablonu do <hub>/wikis/<name> a v jejím config.php nastav site.base_url na origin rozcestníku a site.base_path na /<name>/ (synchronizace s ním předvykresluje odkazy, takže po změně spusť sync znovu).
  2. Nastav hub.url => '/', hub.label na název rozcestníku a hub.source => dirname(__DIR__, 2) . '/config.php'. Tím nad horní lištou přibude tenký pruh v barvě akcentu s podtitulem rozcestníku a tlačítkem, které vyroluje malé menu se všemi wiki na rozcestníku (název a podtitul). Text v něm je černý nebo bílý, podle toho, co má s brand.accent vyšší kontrast.
  3. Přidej do vhostu rozcestníku location blok pro /<name>/ (zkopíruj existující) a přidej wiki do pole wikis rozcestníku ('url' => '/<name>/', 'data' => __DIR__ . '/wikis/<name>').
  4. bin/cron.sh install --container-root /var/www/<hub>/wikis/<name>. Stejný přepínač předej i bin/cron.sh run, protože výchozí cesta v kontejneru počítá s vhostem na nejvyšší úrovni.

Jak crawl funguje

Je to zrcadlo gitu, ne škrabka HTML. První synchronizace spustí git clone https://github.com/<owner>/<repo>.wiki.git do data/repo; každá další je git fetch + git reset --hard, takže přenáší jen to, co se změnilo. Pak se každá stránka znovu vykreslí a index se nahradí v jedné transakci. Při zobrazení stránky se neděje nic — požadavky se nikdy nedotknou gitu ani parseru markdownu.

Potřebuje databázi?

Ne. Výchozí ovladač file drží celou wiki v data/index jako JSON a hledá v ní skórovaným průchodem. Pro wiki o 22 stránkách a zhruba 15 000 slovech to je index o 692 KB a 2,7 ms na celý požadavek hledání, a pohodlně to vydrží až do nižších tisíců stránek. Porovnávání ignoruje diakritiku, takže prepinani najde „MAC, ARP a přepínání“ a sit najde „Kdo je kdo v síti“.

Na 'mysql' přepni db.driver, když SQL opravdu chceš: hodně velká wiki, nebo dotazování indexu odjinud. Tabulky se vytvoří při první synchronizaci; oba ovladače jsou za jedním rozhraním, takže se nic jiného nemění. Když je MySQL nastavené, ale v době požadavku nedostupné, web potichu servíruje souborový index místo chyby.

Jak to držet čerstvé

Plán řídí bin/cron.sh — jeden soubor v /etc/cron.d na web, pojmenovaný podle složky, takže se forky nikdy nesrazí:

sudo ./bin/cron.sh install --interval 15   # každých 15 minut
sudo ./bin/cron.sh status                  # je naplánovaný a kde je log
     ./bin/cron.sh run                     # crawl teď hned, přesně jako z cronu
     ./bin/cron.sh logs -n 40
sudo ./bin/cron.sh remove

Volby: --interval <minuty>, --container <název> (výchozí php-server), --user <jméno> (výchozí www-data), nebo --host pro volání PHP přímo bez dockeru.

Místo dotazování push: nasměruj GitHub webhook pro událost gollum na https://<domain>/sync se sync.webhook_secret, nebo ho šťouchni ručně přes curl "https://<domain>/sync?token=<sync.token>".


Struktura kódu

config.php              veškerý branding, funkce a texty
config.local.php        tajné hodnoty (git-ignored)
index.php               front controller: /, /<Page>, /search, /contents, /files,
                        /raw/<file>, /api/search, /media/<file>, /sync, /sitemap.xml
includes/
  Sync.php              crawler: git → vykreslení → index
  Git.php               bezobslužný wrapper git CLI
  Navigation.php        _Sidebar.md → skupiny, pořadí, titulky, sekce
  Markdown/             prostředí CommonMark
    Renderer.php        HTML + obsah + sekce + perex + počet slov
    LinkRewriter.php    wiki odkazy, obrázky, src/href v holém HTML → URL webu
    CalloutExtension.php  > [!NOTE] → označené upozornění
    WikiLinkParser.php  [[Gollum]] odkazy
    AsciiSlugger.php    kotvy nadpisů bezpečné vůči diakritice
  Store/                FileStore | MysqlStore za jedním rozhraním
  Text.php              odstranění diakritiky pro hledání bez ohledu na ni
  Site.php              fasáda pro čtení, kterou používají views
  Theme.php             config → CSS custom properties
views/                  layout, home, page, contents, search, 404, setup
assets/css/wiki.css     design systém (veškerá barva přes custom properties)
assets/js/wiki.js       motiv, sbalitelné sloupce, paleta, scrollspy, kopírování
bin/cron.sh             install / status / run / logs / remove plánu crawlu
lang/                   cs.json, en.json, de.json — každý text rozhraní
data/                   git klon + souborový index (nikdy se neservíruje přímo)

Poznámky

  • Hledání: průchod bez diakritiky (souborový ovladač) nebo FULLTEXT v boolean režimu se záložním LIKE pro krátké dotazy (MySQL). V obou případech jsou výsledky po stránkách a skočí na nejlépe odpovídající nadpis.
  • Přejmenované úvodní stránky: GitHub wiki přejmenovávají Home.md bez obalu. Synchronizace najde úvodní stránku (config → běžné názvy → první položka postranního panelu) a starý název ponechá jako alias, takže existující odkazy dál fungují.
  • Úložiště má zálohu: když je MySQL v době požadavku nedostupné, web servíruje ze souborového indexu místo chyby.
  • nginx: viz nginx.conf.example; spustitelný je jen index.php a data/, includes/, views/, vendor/, bin/ jsou zakázané.