Zum Inhalt springen
duxt

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

FeldTypAnmerkungen
pathstringOrdner mit dem Markdown, relativ zur Repository-Wurzel
repostringowner/name oder eine git-URL. Weggelassen heißt lokaler Checkout
refsRef-ListeRefs als Versionen; erfordern ein explizites repo
releases{ select, prereleases? }Release-Tags als Versionen entdecken — siehe unten
tagComponentstringNur die <name>@vX.Y.Z-Tags eines Pakets veröffentlichen — siehe Komponenten-Tags
versionstringDie Version, die diese Quelle selbst ist
labelTextIm Umschalter gezeigt und in der URL genutzt; standardmäßig der Ref
nameTextWie diese Quelle heißt, wo die Seite sie benennt. Nur Anzeige — siehe unten
slugstringDas URL-Segment dieser Quelle. Wer eines nennt, beansprucht es — siehe unten
statusStatusLebenszyklus 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
historybooleanDie git-Historie dieser Quelle lesen
contentbooleanfalse, 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
localesLocale-ListeSprachen, in denen diese Quelle vorliegt — siehe unten
generatedSektionslisteArtefakte, die neben dem Markdown als Seiten veröffentlicht werden — siehe unten

Zwei Felder sind leicht zu verwechseln und teuer, wenn man sie falsch setzt:

  • repo lädt herunter, origin verlinkt nur. Das eigene Repository in repo zu nennen lässt den Build den Checkout klonen, in dem er bereits steht.
  • origin.path ist 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 den path der Quelle abgebildet und müssen deshalb darunter liegen.
  • history kostet 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' }
}
selectVerö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'
}
WertBedeutet
upcomingNoch nicht veröffentlicht — kann sich noch ändern
currentDie Dokumentation, die zu lesen ist
maintainedÄlter, weiterhin unterstützt
deprecatedÄlter, und der Leser sollte aktualisieren
eolTot — 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.

FeldTypAnmerkungen
typestringDer Registry-Schlüssel des Typs — changelog, openapi, bruno, ein eigener
pathstringDas Artefakt, relativ zur eigenen Wurzel der Quelle
labelstringDer Navbar-Eintrag und — slugifiziert — das URL-Segment
slugstringÜberschreibt das Segment, das das Label ergeben würde
optionsObjektDie Knöpfe dieses Typs; jeder Typ prüft seine eigenen
versionsVersionslisteVersionen dieses Artefakts — siehe unten
localesRecord<string, string>Ein Artefakt pro Locale, nur von einem per-locale-Typ gelesen
navigationPlatzierung'sections' (Standard), 'navigation' oder false
iconstringFä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' }
    ]
  }
]
FeldAnmerkungen
versionIm Umschalter angezeigt und in der URL verwendet
pathDas Artefakt dieser Version; fällt auf den Pfad der Deklaration zurück
localesArtefakte je Locale für diese Version
statusLebenszyklus — deprecated, eol, upcoming
defaultOhne 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.version ist die Zeichenkette der Site. Sie steht nur dann im Badge, wenn es nichts umzuschalten gibt.
  • info.version eines 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

FeldStandardWas es tut
showRepoausErzwingt ein Repository-Segment bei einem einzelnen Repository
showVersionausErzwingt ein Versionssegment bei einer einzelnen Version
defaultRefder erste RefDer Ref, der ohne Versionspräfix ausgeliefert wird
defaultLocaledie erste LocaleDie 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.

War diese Seite hilfreich?