Sources
Les champs d’une entrée de source, ses refs, et les options qui façonnent les URL.
duxt.sources est une liste d’entrées de source ; duxt.sourceOptions dit
comment elles deviennent des URL. Les deux sont lues à la compilation. Ce
qu’elles génèrent, et pourquoi, est dans Sources.
Les refs exigent un repo explicite, même pour publier un autre ref de ce
dépôt. Sans repo, une source lit le checkout local actuel et refuse refs (y
compris latest) ainsi que les substitutions locales de ref par langue.
origin.repo et origin.ref fournissent uniquement des liens de provenance ;
ils ne sélectionnent aucun contenu. Une langue ayant son propre repo explicite
peut choisir son propre ref. Pour les versions locales, utilisez version sur
des sources avec des dossiers distincts ou les versions par fichier d’une
section générée.
Une entrée de source
| Champ | Type | Remarques |
|---|---|---|
path | string | Dossier contenant le Markdown, relatif à la racine du dépôt |
repo | string | owner/name ou une URL git. Omis signifie le checkout local |
refs | liste de refs | Refs à publier comme versions ; exigent un repo explicite |
releases | { select, prereleases? } | Découvrir les tags de version à publier — voir plus bas |
tagComponent | string | Ne publier que les tags <name>@vX.Y.Z d’un paquet — voir Tags par composant |
version | string | La version que cette source représente elle-même |
label | texte | Affiché dans le sélecteur et utilisé dans l’URL ; par défaut la ref |
name | texte | Comment cette source s’appelle là où le site la nomme. Affichage seul — voir plus bas |
slug | string | Le segment d’URL de cette source. La déclarer, c’est la réclamer — voir plus bas |
status | statut | Cycle de vie de chaque version que cette entrée publie |
statusDefaults | { latest?, branch?, tag? } | Cycle de vie par défaut selon le type de ref |
origin | { repo, ref?, path? } | Où vivent les pages lues sur le disque, pour les liens de retour |
history | boolean | Lire l’historique git de cette source |
content | boolean | false si la source ne porte que du contenu généré |
exclude | { drafts?, partials? } | Globs propres à la source pour brouillons et fragments |
flavor | 'tfplugindocs' | Interpréter l’arbre Markdown comme un dialecte pris en charge |
locales | liste de locales | Langues dans lesquelles cette source existe — voir ci-dessous |
generated | liste de sections | Artefacts publiés en pages à côté du Markdown — voir plus bas |
Deux champs se confondent facilement et coûtent cher quand on se trompe :
repotélécharge,originne fait que lier. Nommer votre propre dépôt dansrepofait cloner à la compilation le checkout dans lequel elle se trouve déjà.origin.pathest le dossier sur la forge. Renseignez-le lorsque le dossier sur le disque est une copie — contenu copié dans un contexte de build, checkout voisin lu via../— afin que « Edit this page » ouvredocs/…et non le chemin de la copie. Les dossiers de langue sont mappés à travers lepathde la source et doivent donc se trouver dessous.historycoûte un clone complet. Content clone un dépôt distant avec--depth 1: son checkout ne contient qu’un commit et chaque fichier paraît écrit par la personne qui a coupé la pointe — données fausses, pas données manquantes. L’activer complète le clone une fois. Une source lue sur le disque est déjà un checkout complet et est lue quoi qu’il arrive.
slug réclame un segment. Une source n’en reçoit normalement un que lorsque
la liste nomme plus d’un dépôt — tout ou rien, pour le site entier. Une source
qui écrit son propre slug est servie dessous de toute façon, et celles qui n’en
écrivent aucun ne bougent pas : c’est ce qui permet à une chose de vivre sous
/demo à côté d’une documentation qui garde la racine.
name est un nom, label et slug sont des adresses. La boîte de dialogue
de recherche légende chaque résultat avec la source dont il provient, et avant
cette clé elle ne pouvait la lire que dans l’URL : une documentation servie à la
racine s’annonçait donc comme /, et une source dont le segment est une
abréviation comme tf. name sert uniquement à l’affichage : il n’atteint
aucune collection, aucun préfixe, aucune version ni le classement — c’est
précisément pour cela qu’il peut être de la prose et peut être traduit.
sources: [
// Un enregistrement de locales, car le nom est un substantif qui se traduit.
{
repo: 'acme/docs',
path: 'docs',
name: { 'en-GB': 'Handbook', de: 'Handbuch', fr: 'Manuel' }
},
// Un littéral simple, car un nom de produit est le même mot partout.
{ repo: 'acme/terraform-provider-acme', path: 'docs', slug: 'tf', name: 'Terraform Provider' }
]
Non renseigné, le nom retombe sur le segment de la source (demo → Demo)
puis sur duxt.title, qui est lui-même le libellé localisé Documentation
sur un site sans titre. À renseigner partout où le segment est une abréviation.
Deux sources différentes qui aboutiraient à un seul nom sont distinguées
automatiquement, par leur dépôt ou leur dossier.
Contenu, exclusions et dialectes de source
content: false évite de publier les pages Markdown ordinaires de la source,
mais conserve ses déclarations generated. exclude.drafts et
exclude.partials remplacent les globs propres à cette source lorsqu’un dépôt
suit d’autres conventions.
flavor: 'tfplugindocs' interprète les dossiers, titres et catégories d’un
arbre Markdown produit par tfplugindocs. Les pages restent des pages Content
ordinaires pour la recherche, les versions, les locales et les lecteurs
machines. Voir
Publier la documentation d’un provider Terraform.
Refs
Une chaîne nue est une branche. Un tag doit le dire : git garde les branches
et les tags dans des espaces de noms séparés, et demander un tag sous
refs/heads fait échouer la compilation avec Could not find refs/heads/….
refs: [
'main', // une branche
{ branch: 'next', status: 'upcoming' }, // la même, avec un cycle de vie
{ tag: 'v2.0.0', label: 'v2' }, // un tag
'latest' // le tag semver le plus récent, résolu à la compilation
]
'latest' est réservé. Une branche réellement nommée latest exige la forme
{ branch }.
Releases
releases découvre les tags au lieu d’entretenir un long historique dans la
configuration. La découverte est opt-in et indique toujours sa sélection : il
n’existe pas de « toutes les versions » implicite, car les URL qui restent
accessibles relèvent d’une décision du site.
{
repo: 'acme/sdk',
path: 'docs',
releases: { select: 'minor' }
}
select | Publie |
|---|---|
'all' | chaque version |
'minor' | la version la plus récente de chaque ligne mineure |
'major' | la version la plus récente de chaque ligne majeure |
Les préversions restent exclues sauf avec prereleases: true. La version
sélectionnée la plus récente est utilisée par défaut ; une ref avec
default: true ou sourceOptions.defaultRef reste prioritaire.
Le cycle de vie ne change pas : le statut de la source ou statusDefaults.tag
s’applique à chaque tag découvert. Rien n’est déduit de l’âge d’une version.
refs reste disponible avec releases. Une entrée visant un tag découvert
remplace son libellé, son statut, sa valeur par défaut et ses locales ; les autres
sont publiées à côté.
{
repo: 'acme/sdk',
releases: { select: 'major' },
refs: [
{ tag: 'v1.4.2', label: 'v1', status: 'deprecated' },
{ branch: 'main', status: 'upcoming' }
]
}
Une sélection sans tag correspondant arrête le build en nommant la source et la
sélection. Un dépôt illisible est signalé séparément comme une erreur Git. La
même distinction vaut pour latest.
Tags par composant
Un monorepo qui publie plusieurs paquets séparément étiquette chacun par son
composant — release-please écrit duxt@v0.4.0 à côté de
duxt-typesense@v0.1.0. Les deux formes sont des versions : latest,
releases et l’ordre du sélecteur lisent <name>@vX.Y.Z exactement comme
vX.Y.Z, et le libellé comme le segment d’URL n’affichent que la version —
v0.4.0, jamais duxt@v0.4.0. La ref garde le tag complet, car c’est le nom que
git connaît.
Quand le dépôt étiquette plus d’un paquet, « le tag le plus récent » ne veut rien
dire tant qu’il ne précise pas lequel. tagComponent nomme le paquet :
{
repo: 'kirchDev/duxt',
path: 'docs',
tagComponent: 'duxt',
refs: [{ tag: 'latest', default: true }] // duxt@v…, jamais duxt-typesense@v…
}
Les tags vX.Y.Z simples comptent toujours : ce sont les versions du paquet
antérieures aux tags par composant, et les écarter les dépublierait toutes. Les
tags d’un autre composant ne comptent jamais. Sans tagComponent, tout tag qui
se lit comme une version est candidat, préfixé ou non.
Locales
Omis, la source a une langue et une collection. Listées, chaque entrée devient une collection à part.
locales: [
'en-GB', // la valeur par défaut : docs/ lui-même
'de', // docs/de/
{ locale: 'fr', path: 'translations/fr' }, // ailleurs dans ce dépôt
{ locale: 'es', repo: 'acme/docs-es', path: 'docs' } // un autre dépôt
]
Une chaîne est un dossier à l’intérieur du path de la source. La forme objet
remplace path, repo et ref pour cette langue seule — et c’est ce qui
permet à une traduction de vivre dans son propre dépôt, avec ses mainteneurs et
son calendrier de publication.
La locale par défaut est l’arbre de path lui-même et ne prend aucun
dossier. Laquelle c’est vient de sourceOptions.defaultLocale, et elle doit
concorder avec i18n.defaultLocale — la compilation échoue si elles diffèrent,
car content.config.ts résout les collections sans accès à la configuration
Nuxt.
Une ref peut porter ses propres locales, remplaçant ceux de la source
exactement comme le fait status. C’est la forme habituelle : la version
courante est traduite, les précédentes non.
refs: [
{ tag: 'v2.0.0' }, // hérite des locales de la source
{ tag: 'v1.0.0', locales: ['en-GB'] } // l’original seulement
]
Nommez un dossier par langue là où la région n’ajoute rien : docs/pt/ sert
à la fois pt-PT et pt-BR, parce qu’une page retombe sur sa langue de base.
La même règle que suivent les fichiers de locale de la couche.
Statut
statusDefaults fournit un cycle de vie par type de ref lorsque la ref ne le
précise pas : latest pour le tag choisi par l’entrée réservée, branch pour les
branches et tag pour les tags explicites ou découverts. Un statut explicite sur
la ref prévaut ; celui de la source sert de fallback commun.
statusDefaults: {
latest: 'current',
branch: 'upcoming',
tag: 'deprecated'
}
| Valeur | Signifie |
|---|---|
upcoming | Pas encore publiée — peut encore changer |
current | La documentation à lire |
maintained | Plus ancienne, toujours prise en charge |
deprecated | Plus ancienne, et le lecteur devrait mettre à jour |
eol | Morte — signalée, et hors du sitemap |
Ce que chacune coûte à une page est dans URL et versions.
Sections générées
generated liste les artefacts qui ne sont pas du Markdown et le type qui lit
chacun d’eux en pages. Ce qu’est le mécanisme, et les deux politiques auxquelles
un type répond, se trouve dans
Sections générées ; les champs ci-dessous sont
les mêmes quel que soit le type qui les lit.
| Champ | Type | Notes |
|---|---|---|
type | string | La clé de registre du type — changelog, openapi, bruno, le vôtre |
path | string | L’artefact, relatif à la racine propre de la source |
label | string | L’entrée de la barre et — slugifiée — le segment d’URL |
slug | string | Remplace le segment que le libellé produirait |
options | objet | Les réglages qu’offre ce type ; chaque type valide les siens |
versions | liste de versions | Les versions de cet artefact — voir ci-dessous |
locales | Record<string, string> | Un artefact par langue, lu par un type per-locale seulement |
navigation | placement | 'sections' (par défaut), 'navigation' ou false |
icon | string | Retombe sur l’icône propre du type |
path est un chemin et jamais une URL. Pour une source que Content clone, il
est relatif à la racine de ce checkout, donc l’artefact voyage avec la version à
laquelle il appartient — une règle dans les deux sens. Un emplacement arbitraire
permettrait d’aller chercher un artefact n’importe où et rouvrirait la question du
réseau au moment du build, que sources a déjà refermée.
label est une chaîne simple et non un texte traduit, pour la même raison que
le libellé d’une version en est une : un texte traduit n’est pas une URL stable.
Une section avec ses propres versions
Une version est normalement un checkout : refs sur la source publie chaque
section une fois par ref. Une API conserve en revanche souvent
openapi/v1.yaml à côté de openapi/v2.yaml dans le même dépôt et se versionne
par fichier. Sans versions, ce seraient deux sections indépendantes et deux
entrées de 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' }
]
}
]
| Champ | Notes |
|---|---|
version | Affichée dans le sélecteur et utilisée dans l’URL |
path | L’artefact de cette version ; par défaut, celui de la déclaration |
locales | Les artefacts par locale pour cette version |
status | Cycle de vie — deprecated, eol, upcoming |
default | Servie sans segment de version ; première entrée par défaut |
La version par défaut est servie sous /api, les autres sous leur propre
segment comme /v1/api. Le sélecteur les propose comme les refs d’une source,
avec le bandeau, noindex et le canonical d’une version non courante.
Elles sont réunies dans une déclaration plutôt que deux sources à dessein : seules les variantes produites par une même déclaration sont proposées comme versions l’une de l’autre. Une source par version d’API publierait aussi deux fois l’arbre documentaire.
Ne les placez jamais à côté de refs sur la même source. Les deux réclament
le même segment d’URL et le build refuse la combinaison. Un type global les
refuse également puisqu’il publie une histoire unique sous une URL neutre. Un
changelog n’est pas global : il est publié par version et accepte versions
comme une référence d’API.
Quelle version est laquelle ?
Trois choses portent le nom de version autour d’une page de référence, mais deux seulement appartiennent à duxt :
- La version dans l’URL et le sélecteur est une ref ou une valeur
versiondéclarée ci-dessus. Le badge indique la variante lue. duxt.versionest la chaîne propre au site. Elle n’apparaît dans le badge que lorsqu’il n’y a rien à sélectionner.info.versiond’un document OpenAPI est la déclaration du document sur l’API décrite. Elle apparaît comme Version d’API sur la page de référence, jamais dans le badge du sélecteur.
Les nombres se ressemblent souvent mais restent des faits distincts ; duxt ne déduit aucun de l’autre.
options est opaque à tout sauf au type qui les lit — une granularité veut dire
quelque chose pour un journal des versions et rien pour une référence d’API. Une
clé que le type ne connaît pas fait échouer le build au lieu d’être ignorée, parce
qu’une option mal orthographiée est un site qui n’obtient silencieusement pas ce
qu’il a configuré.
Options de source
| Champ | Par défaut | Ce qu’il fait |
|---|---|---|
showRepo | désactivé | Force un segment de dépôt avec un dépôt unique |
showVersion | désactivé | Force un segment de version avec une version unique |
defaultRef | la première ref | La ref servie sans préfixe de version |
defaultLocale | la première locale | La locale servie depuis path lui-même, sans dossier |
Le manifeste résolu
La compilation transforme la liste ci-dessus en duxt.resolvedSources, et c’est
ce que lit le thème. useDuxtCollection() l’expose ; chaque entrée porte le nom
de la collection, le prefix d’URL, repo, version, name, isDefault,
locale,
isDefaultLocale, status, le dépôt et la ref d’où viennent les pages, et si
son history a été lu.
La locale est délibérément absente de prefix : i18n la place déjà devant le
chemin, si bien que toutes les langues d’une source partagent un préfixe et ne
diffèrent que par la collection.
Médias de documentation
Les images générées se placent dans docs/_assets/. Les références sont relatives au fichier Markdown : docs/1.guides/1.demo.md utilise ../_assets/demo.gif. Le préfixe /_assets/ désigne la racine de documentation de la source. La même règle vaut pour l'attribut d'image dark.
duxt publie automatiquement les images PNG, JPEG, GIF, SVG, WebP, AVIF, APNG et ICO, y compris les sources distantes à leur ref sélectionnée. Les URL séparent dépôt, racine de documentation et ref ; les liens de page et le fournisseur d'images sont conservés. _assets/ ne devient ni section ni page. Les tapes, scripts, Dockerfiles et autres sources de capture ne sont pas publiés.
Les images sans texte localisé restent dans _assets/ partagé. Une page dans docs/de/ peut utiliser ../_assets/demo.gif ; une variante allemande produite explicitement dans docs/de/_assets/ utilise _assets/demo.gif. Les images viennent du dépôt et de la ref de la page. Un dépôt de traduction peut partager les images de son checkout, sans récupérer implicitement celles d'un autre dépôt. Traduisez les textes alternatifs et légendes avec la page.