Quellen
Die Felder eines Quelleneintrags, seine Refs, und die Optionen, die die URLs formen.
duxt.sources ist eine Liste von Quelleneinträgen; duxt.sourceOptions sagt,
wie daraus URLs werden. Beide werden zur Build-Zeit gelesen. Was sie erzeugen
und warum, steht in Quellen.
Refs erfordern ein explizites repo, auch für einen anderen Ref dieses
Repositorys. Ohne repo liest eine Quelle den aktuellen lokalen Checkout und
lehnt refs (einschließlich latest) sowie lokale ref-Overrides pro Sprache
ab. origin.repo und origin.ref liefern nur Herkunftslinks; sie wählen keine
Inhalte aus. Eine Sprache mit eigenem explizitem repo darf einen eigenen ref
wählen. Für lokale Versionen dienen version an Quellen mit getrennten Ordnern
oder dateibasierte versions eines generierten Abschnitts.
Ein Quelleneintrag
| Feld | Typ | Anmerkungen |
|---|---|---|
path | string | Ordner mit dem Markdown, relativ zur Repository-Wurzel |
repo | string | owner/name oder eine git-URL. Weggelassen heißt lokaler Checkout |
refs | Ref-Liste | Refs als Versionen; erfordern ein explizites repo |
releases | { select, prereleases? } | Release-Tags als Versionen entdecken — siehe unten |
tagComponent | string | Nur die <name>@vX.Y.Z-Tags eines Pakets veröffentlichen — siehe Komponenten-Tags |
version | string | Die Version, die diese Quelle selbst ist |
label | Text | Im Umschalter gezeigt und in der URL genutzt; standardmäßig der Ref |
name | Text | Wie diese Quelle heißt, wo die Seite sie benennt. Nur Anzeige — siehe unten |
slug | string | Das URL-Segment dieser Quelle. Wer eines nennt, beansprucht es — siehe unten |
status | Status | Lebenszyklus jeder Version, die dieser Eintrag veröffentlicht |
statusDefaults | { latest?, branch?, tag? } | Standard-Lebenszyklus je Ref-Art |
origin | { repo, ref?, path? } | Wo von der Platte gelesene Seiten liegen, für Links zurück |
history | boolean | Die git-Historie dieser Quelle lesen |
content | boolean | false, wenn die Quelle nur generierte Inhalte trägt |
exclude | { drafts?, partials? } | Quellenbezogene Globs für Entwürfe und Partials |
flavor | 'tfplugindocs' | Den Markdown-Baum als unterstützten Quellen-Dialekt lesen |
locales | Locale-Liste | Sprachen, in denen diese Quelle vorliegt — siehe unten |
generated | Sektionsliste | Artefakte, die neben dem Markdown als Seiten veröffentlicht werden — siehe unten |
Zwei Felder sind leicht zu verwechseln und teuer, wenn man sie falsch setzt:
repolädt herunter,originverlinkt nur. Das eigene Repository inrepozu nennen lässt den Build den Checkout klonen, in dem er bereits steht.origin.pathist der Ordner auf der Forge. Setze ihn, wo der Ordner auf der Platte eine Kopie ist – in einen Build-Kontext kopierte Inhalte oder ein über../gelesener Nachbar-Checkout –, damit „Edit this page“docs/…statt des Kopie-Pfads öffnet. Sprachordner werden über denpathder Quelle abgebildet und müssen deshalb darunter liegen.historykostet einen vollständigen Clone. Content klont ein entferntes Repository mit--depth 1, sein Checkout hält also einen Commit und jede Datei sieht aus, als hätte sie die Person geschrieben, die die Spitze gesetzt hat — falsche Daten, keine fehlenden. Das einzuschalten macht den Clone einmal vollständig. Eine von der Platte gelesene Quelle ist ohnehin ein vollständiger Checkout und wird unabhängig davon gelesen.
slug beansprucht ein Segment. Ein Segment bekommt eine Quelle sonst erst,
wenn die Liste mehr als ein Repository nennt — alles oder nichts, für die ganze
Seite. Eine Quelle, die einen eigenen slug schreibt, wird ohnehin darunter
ausgeliefert, und die Quellen ohne bleiben, wo sie sind. Genau das lässt eine
Sache unter /demo neben einer Dokumentation stehen, die die Wurzel behält.
name ist ein Name, label und slug sind Adressen. Der Suchdialog
beschriftet jedes Ergebnis mit der Quelle, aus der es stammt, und vor diesem
Schlüssel konnte er das nur aus der URL ablesen — eine an der Wurzel
ausgelieferte Dokumentation meldete sich also als /, und eine Quelle, deren
Segment eine Abkürzung ist, als tf. name dient nur der Anzeige: Er erreicht
keine Collection, kein Präfix, keine Version und kein Ranking — genau deshalb
darf er Prosa sein und darf übersetzt werden.
sources: [
// Ein Locale-Record, weil der Name ein Substantiv ist, das sich übersetzt.
{
repo: 'acme/docs',
path: 'docs',
name: { 'en-GB': 'Handbook', de: 'Handbuch', fr: 'Manuel' }
},
// Ein einfaches Literal, weil ein Produktname überall dasselbe Wort ist.
{ repo: 'acme/terraform-provider-acme', path: 'docs', slug: 'tf', name: 'Terraform Provider' }
]
Ohne Angabe fällt der Name auf das eigene Segment der Quelle zurück (demo →
Demo) und dann auf duxt.title, das auf einer Seite ohne Titel selbst das
lokalisierte Label Dokumentation ist. Lohnt sich überall dort, wo das
Segment eine Abkürzung ist. Zwei verschiedene Quellen, die auf einem Namen
landen würden, werden automatisch über ihr Repository oder ihren Ordner
unterschieden.
Content, Ausschlüsse und Quellen-Dialekte
content: false veröffentlicht keine gewöhnlichen Markdown-Seiten aus der
Quelle, lässt ihre generated-Deklarationen aber aktiv. exclude.drafts und
exclude.partials ersetzen die jeweiligen quellenbezogenen Globs, wenn ein
Repository andere Konventionen nutzt.
flavor: 'tfplugindocs' liest die Verzeichnis-, Überschriften- und
Kategorieform eines von tfplugindocs erzeugten Markdown-Baums. Die Seiten
bleiben gewöhnliche Content-Seiten für Suche, Versionen, Locales und
Machine-Reader. Siehe
Terraform-Provider-Dokumentation veröffentlichen.
Refs
Eine bloße Zeichenkette ist ein Branch. Ein Tag muss das sagen: git hält
Branches und Tags in getrennten Namensräumen, und einen Tag unter refs/heads
zu verlangen lässt den Build mit Could not find refs/heads/… scheitern.
refs: [
'main', // ein Branch
{ branch: 'next', status: 'upcoming' }, // derselbe, mit einem Lebenszyklus
{ tag: 'v2.0.0', label: 'v2' }, // ein Tag
'latest' // der neueste Semver-Tag, im Build aufgelöst
]
'latest' ist reserviert. Ein Branch, der wirklich latest heißt, braucht die
Form { branch }.
Releases
releases entdeckt Tags, statt eine lange Historie in der Konfiguration zu
pflegen. Die Erkennung ist opt-in und nennt immer ihre Auswahl: Ein implizites
„alle Releases“ gibt es nicht, weil dauerhaft erreichbare URLs eine Entscheidung
der Site sind.
{
repo: 'acme/sdk',
path: 'docs',
releases: { select: 'minor' }
}
select | Veröffentlicht |
|---|---|
'all' | jeden Release |
'minor' | den neuesten Release jeder Minor-Linie |
'major' | den neuesten Release jeder Major-Linie |
Pre-Releases bleiben ausgeschlossen, bis prereleases: true sie bewusst
einschließt. Der neueste ausgewählte Release ist standardmäßig aktiv; ein Ref
mit default: true oder sourceOptions.defaultRef gewinnt weiterhin.
Lebenszyklen ändern sich nicht: Der Status der Quelle oder statusDefaults.tag
gilt für jeden entdeckten Tag. Aus dem Alter eines Releases wird nichts
abgeleitet.
refs bleibt neben releases verfügbar. Ein Eintrag für einen entdeckten Tag
überschreibt dessen Label, Status, Default und Locales; alles andere wird daneben
veröffentlicht.
{
repo: 'acme/sdk',
releases: { select: 'major' },
refs: [
{ tag: 'v1.4.2', label: 'v1', status: 'deprecated' },
{ branch: 'main', status: 'upcoming' }
]
}
Eine Auswahl ohne passenden Tag stoppt den Build und nennt Quelle und Auswahl.
Ein nicht lesbares Repository wird getrennt als Git-Fehler gemeldet. Dieselbe
Unterscheidung gilt für latest.
Komponenten-Tags
Ein Monorepo, das mehrere Pakete getrennt veröffentlicht, taggt jedes nach
seiner Komponente — release-please schreibt duxt@v0.4.0 neben
duxt-typesense@v0.1.0. Beide Formen sind Versionen: latest, releases und
die Reihenfolge im Umschalter lesen <name>@vX.Y.Z genau wie vX.Y.Z, und
Label und URL-Segment zeigen nur die Version — v0.4.0, nie duxt@v0.4.0. Der
Ref behält den vollständigen Tag, denn unter diesem Namen kennt git ihn.
Taggt das Repository mehr als ein Paket, bedeutet „der neueste Tag“ nichts,
solange nicht gesagt ist, wessen. tagComponent nennt das Paket:
{
repo: 'kirchDev/duxt',
path: 'docs',
tagComponent: 'duxt',
refs: [{ tag: 'latest', default: true }] // duxt@v…, nie duxt-typesense@v…
}
Einfache vX.Y.Z-Tags zählen weiterhin: Sie sind die Releases des Pakets
aus der Zeit vor den Komponenten-Tags, und sie wegzulassen würde jedes davon
depublizieren. Tags einer anderen Komponente zählen nie. Ohne tagComponent ist
jeder Tag, der sich als Version liest, ein Kandidat — mit oder ohne Präfix.
Locales
Weggelassen hat die Quelle eine Sprache und eine Collection. Aufgelistet wird jeder Eintrag zu einer eigenen Collection.
locales: [
'en-GB', // der Standard: docs/ selbst
'de', // docs/de/
{ locale: 'fr', path: 'translations/fr' }, // woanders in diesem Repository
{ locale: 'es', repo: 'acme/docs-es', path: 'docs' } // ein anderes Repository
]
Eine Zeichenkette ist ein Ordner innerhalb des path der Quelle. Die
Objektform überschreibt path, repo und ref allein für diese Sprache — und
genau das lässt eine Übersetzung in einem eigenen Repository leben, mit eigenen
Betreuern und eigenem Releaseplan.
Die Standard-Locale ist der Baum in path selbst und nimmt keinen Ordner.
Welche das ist, kommt aus sourceOptions.defaultLocale, und sie muss mit
i18n.defaultLocale übereinstimmen — der Build scheitert, wenn sie abweichen,
denn content.config.ts löst die Collections ohne Zugriff auf die
Nuxt-Konfiguration auf.
Ein Ref darf eigene locales tragen, die die der Quelle überschreiben, genau
wie status. Das ist die übliche Form: Die aktuelle Version ist übersetzt, die
dahinter nicht.
refs: [
{ tag: 'v2.0.0' }, // erbt die Locales der Quelle
{ tag: 'v1.0.0', locales: ['en-GB'] } // nur das Original
]
Benenne einen Ordner nach der Sprache, wo eine Region nichts hinzufügt:
docs/pt/ bedient sowohl pt-PT als auch pt-BR, weil eine Seite über ihre
Basissprache zurückfällt. Dieselbe Regel, der die Locale-Dateien der Ebene
folgen.
Status
statusDefaults setzt einen Lebenszyklus je Ref-Art, wenn der Ref selbst keinen
nennt: latest gilt für den durch den reservierten Eintrag gewählten Tag,
branch für Branches und tag für explizite oder entdeckte Tags. Ein expliziter
Ref-Status gewinnt; der Status der Quelle ist der gemeinsame Fallback.
statusDefaults: {
latest: 'current',
branch: 'upcoming',
tag: 'deprecated'
}
| Wert | Bedeutet |
|---|---|
upcoming | Noch nicht veröffentlicht — kann sich noch ändern |
current | Die Dokumentation, die zu lesen ist |
maintained | Älter, weiterhin unterstützt |
deprecated | Älter, und der Leser sollte aktualisieren |
eol | Tot — wird gewarnt, und aus der Sitemap heraus |
Was jeder Wert eine Seite kostet, steht in URLs und Versionen.
Generierte Sektionen
generated listet Artefakte auf, die kein Markdown sind, und den Typ, der jedes
davon zu Seiten liest. Was der Mechanismus ist und welche zwei Richtlinien ein
Typ beantwortet, steht in
Generierte Sektionen; die Felder unten sind
dieselben, welcher Typ sie auch liest.
| Feld | Typ | Anmerkungen |
|---|---|---|
type | string | Der Registry-Schlüssel des Typs — changelog, openapi, bruno, ein eigener |
path | string | Das Artefakt, relativ zur eigenen Wurzel der Quelle |
label | string | Der Navbar-Eintrag und — slugifiziert — das URL-Segment |
slug | string | Überschreibt das Segment, das das Label ergeben würde |
options | Objekt | Die Knöpfe dieses Typs; jeder Typ prüft seine eigenen |
versions | Versionsliste | Versionen dieses Artefakts — siehe unten |
locales | Record<string, string> | Ein Artefakt pro Locale, nur von einem per-locale-Typ gelesen |
navigation | Platzierung | 'sections' (Standard), 'navigation' oder false |
icon | string | Fällt auf das Icon des Typs zurück |
path ist ein Pfad und nie eine URL. Bei einer Quelle, die Content klont,
ist er relativ zur Wurzel dieses Checkouts — das Artefakt reist also mit der
Version, zu der es gehört, eine Regel in beide Richtungen. Ein beliebiger Ort
würde erlauben, ein Artefakt von überall zu holen, und die Frage nach Netzwerk
zur Build-Zeit wieder öffnen, die sources bereits geschlossen hat.
label ist eine einfache Zeichenkette und kein übersetzter Text, aus
demselben Grund, aus dem das Label einer Version einer ist: Ein übersetzter Text
ist keine stabile URL.
Eine Sektion mit eigenen Versionen
Eine Version ist normalerweise ein Checkout: refs an der Quelle
veröffentlicht jede ihrer Sektionen einmal pro Ref. Eine API liegt dagegen oft
als openapi/v1.yaml neben openapi/v2.yaml im selben Repository und ist nach
Datei versioniert. Ohne versions wären das zwei unabhängige Sektionen und
zwei Einträge in der Navigation.
generated: [
{
type: 'openapi',
label: 'API',
path: 'openapi/v2.yaml',
versions: [
{ version: 'v2', path: 'openapi/v2.yaml' },
{ version: 'v1', path: 'openapi/v1.yaml', status: 'deprecated' }
]
}
]
| Feld | Anmerkungen |
|---|---|
version | Im Umschalter angezeigt und in der URL verwendet |
path | Das Artefakt dieser Version; fällt auf den Pfad der Deklaration zurück |
locales | Artefakte je Locale für diese Version |
status | Lebenszyklus — deprecated, eol, upcoming |
default | Ohne Versionssegment ausgeliefert; standardmäßig der erste Eintrag |
Der Standard liegt unter /api, jede andere Version unter ihrem Segment wie
/v1/api. Der Umschalter bietet sie wie die Refs einer Quelle an, einschließlich
Warnung, noindex und Canonical für eine nicht aktuelle Version.
Sie stehen absichtlich in einer Deklaration statt in zwei Quellen: Nur Varianten aus derselben Deklaration werden als Versionen voneinander angeboten. Eine eigene Quelle je API-Version würde außerdem den Dokumentationsbaum doppelt veröffentlichen.
Verwende sie nie neben refs derselben Quelle. Beide beanspruchen dasselbe
URL-Segment und der Build lehnt die Kombination ab. Ein global-Typ lehnt sie
ebenfalls ab, weil er genau eine Historie unter einer versionsneutralen URL
veröffentlicht. Ein Changelog ist nicht global: Es wird je Version veröffentlicht
und kann wie eine API-Referenz versions tragen.
Welche Version ist welche?
Drei Dinge heißen rund um eine Referenzseite Version, aber nur zwei gehören zu duxt:
- Die Version in URL und Umschalter ist ein Ref oder ein oben deklarierter
version-Wert. Das Badge zeigt, welche Variante gelesen wird. duxt.versionist die Zeichenkette der Site. Sie steht nur dann im Badge, wenn es nichts umzuschalten gibt.info.versioneines OpenAPI-Dokuments ist die eigene Aussage des Dokuments über die beschriebene API. Sie erscheint als API-Version auf der Referenzseite, nie im Umschalter-Badge.
Die Zahlen sind oft ähnlich, bleiben aber verschiedene Fakten; duxt leitet keine aus der anderen ab.
options ist für alles außer dem Typ, der sie liest, undurchsichtig — eine
Granularität bedeutet einem Changelog etwas und einer API-Referenz nichts. Ein
Schlüssel, den der Typ nicht kennt, lässt den Build scheitern, statt ignoriert zu
werden: Eine falsch geschriebene Option ist eine Site, die still nicht bekommt,
was sie konfiguriert hat.
Quellenoptionen
| Feld | Standard | Was es tut |
|---|---|---|
showRepo | aus | Erzwingt ein Repository-Segment bei einem einzelnen Repository |
showVersion | aus | Erzwingt ein Versionssegment bei einer einzelnen Version |
defaultRef | der erste Ref | Der Ref, der ohne Versionspräfix ausgeliefert wird |
defaultLocale | die erste Locale | Die Locale, die aus path selbst ausgeliefert wird, ohne Ordner |
Das aufgelöste Manifest
Der Build macht aus der Liste oben duxt.resolvedSources, und das ist es, was
das Theme liest. useDuxtCollection() legt es offen; jeder Eintrag trägt den
Collection-Namen, das URL-prefix, repo, version, name, isDefault,
locale,
isDefaultLocale, status, das Repository und den Ref, aus denen die Seiten
kamen, und ob seine history gelesen wurde.
Der Locale fehlt bewusst im prefix: i18n stellt ihn dem Pfad ohnehin voran,
jede Sprache einer Quelle teilt sich also ein Präfix und unterscheidet sich nur
durch die Collection.
Dokumentationsmedien
Generierte Dokumentationsbilder gehören nach docs/_assets/. Referenzen sind relativ zur Markdown-Datei: docs/1.guides/1.demo.md verwendet ../_assets/demo.gif. Ein führendes /_assets/ bezeichnet die Dokumentationswurzel der Quelle. Dies gilt auch für das Bildattribut dark.
duxt veröffentlicht PNG-, JPEG-, GIF-, SVG-, WebP-, AVIF-, APNG- und ICO-Ausgaben automatisch, auch aus entfernten Quellen am ausgewählten Ref. Öffentliche URLs trennen Repository, Dokumentationswurzel und Ref; Seitenlinks und Bildanbieter bleiben erhalten. _assets/ wird weder Abschnitt noch Seite. Tapes, Skripte, Dockerfiles und andere Aufnahmequellen werden nicht veröffentlicht.
Sprachneutrale Bilder bleiben im gemeinsamen _assets/-Verzeichnis. Eine Seite unter docs/de/ kann ../_assets/demo.gif verwenden; eine ausdrücklich erzeugte deutsche Variante unter docs/de/_assets/ verwendet _assets/demo.gif. Bilder stammen aus dem Repository und Ref der Seite. Ein Sprach-Repository teilt Bilder innerhalb seines Checkouts, lädt jedoch keine Medien aus einem anderen Repository. Alt-Text und Bildunterschriften werden mit der Seite übersetzt.