@hgdc/docs 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs.schema.json +21 -0
- package/package.json +3 -1
- package/src/build/auto-import.ts +5 -24
- package/src/build/content.ts +82 -0
- package/src/build/markdown.ts +10 -5
- package/src/components/Accordion.astro +3 -1
- package/src/components/Callout.astro +31 -0
- package/src/components/Card.astro +3 -1
- package/src/components/Check.astro +2 -3
- package/src/components/CodeGroup.astro +9 -1
- package/src/components/Danger.astro +2 -3
- package/src/components/Info.astro +2 -3
- package/src/components/Note.astro +2 -3
- package/src/components/Tip.astro +2 -3
- package/src/components/Warning.astro +2 -3
- package/src/core/components.ts +166 -0
- package/src/core/config.ts +42 -0
- package/src/core/feedback-api.ts +27 -0
- package/src/core/theme.ts +6 -3
- package/src/core/validate.ts +276 -0
- package/src/integration.ts +102 -30
- package/src/overrides/Assistant.astro +17 -39
- package/src/overrides/Footer.astro +107 -0
- package/src/overrides/Head.astro +14 -14
- package/src/overrides/Header.astro +92 -0
- package/src/overrides/Icon.astro +65 -0
- package/src/overrides/PageFrame.astro +55 -8
- package/src/overrides/PageSidebar.astro +7 -0
- package/src/overrides/PageTitle.astro +126 -95
- package/src/overrides/Search.astro +54 -0
- package/src/overrides/Sidebar.astro +105 -60
- package/src/overrides/SidebarList.astro +52 -0
- package/src/overrides/SiteFooter.astro +51 -0
- package/src/overrides/ThemeProvider.astro +23 -0
- package/src/overrides/ThemeToggle.astro +90 -0
- package/src/overrides/TwoColumnContent.astro +45 -0
- package/src/overrides/sections.ts +29 -0
- package/src/styles/theme.css +2137 -511
- package/src/widget/client.ts +51 -19
- package/src/widget/code.ts +218 -0
- package/src/widget/excerpt.ts +5 -0
- package/src/widget/search.ts +222 -0
- package/template/.astro/collections/docs.schema.json +3 -0
- package/template/.astro/content-modules.mjs +35 -15
- package/template/.astro/data-store.json +1 -0
- package/template/.astro/settings.json +5 -0
- package/template/.build/.well-known/llms.txt +51 -34
- package/template/.build/404.html +16 -42
- package/template/.build/_astro/Assistant.astro_astro_type_script_index_0_lang.C1pz7yK1.js +4 -0
- package/template/.build/_astro/CodeGroup.astro_astro_type_script_index_0_lang.-eM8maAX.js +1 -0
- package/template/.build/_astro/Footer.astro_astro_type_script_index_0_lang.DzCnn3OT.js +1 -0
- package/template/.build/_astro/Search.astro_astro_type_script_index_0_lang.D7EcezBU.js +1 -0
- package/template/.build/_astro/code.smqv0zhe.js +9 -0
- package/template/.build/_astro/common.Dx3aBIS0.css +3 -0
- package/template/.build/_astro/{ec.8nqtp.css → ec.t9qpe.css} +1 -1
- package/template/.build/_astro/logo.BPu921Tp.svg +1 -0
- package/template/.build/_hgdc/corpus.json +1 -1
- package/template/.build/concepts/confidentialite/index.html +50 -0
- package/template/.build/concepts/confidentialite.md +38 -0
- package/template/.build/concepts/deploiements/index.html +106 -0
- package/template/.build/concepts/deploiements.md +70 -0
- package/template/.build/concepts/organisations-et-roles/index.html +83 -0
- package/template/.build/concepts/organisations-et-roles.md +39 -0
- package/template/.build/concepts/preversion/index.html +49 -0
- package/template/.build/concepts/preversion.md +52 -0
- package/template/.build/concepts/secrets-et-coffre/index.html +70 -0
- package/template/.build/concepts/secrets-et-coffre.md +54 -0
- package/template/.build/demarrer/depuis-github/index.html +34 -0
- package/template/.build/demarrer/depuis-github.md +68 -0
- package/template/.build/demarrer/premier-site/index.html +28 -0
- package/template/.build/demarrer/premier-site.md +94 -0
- package/template/.build/guides/brancher-un-domaine/index.html +91 -0
- package/template/.build/guides/brancher-un-domaine.md +81 -0
- package/template/.build/guides/cle-d-api/index.html +62 -0
- package/template/.build/guides/cle-d-api.md +78 -0
- package/template/.build/guides/depannage/index.html +64 -0
- package/template/.build/guides/depannage.md +69 -0
- package/template/.build/guides/deployer-depuis-github/index.html +45 -0
- package/template/.build/guides/deployer-depuis-github.md +70 -0
- package/template/.build/guides/deployer-un-framework/index.html +81 -0
- package/template/.build/guides/deployer-un-framework.md +74 -0
- package/template/.build/guides/github-actions-sans-application/index.html +53 -0
- package/template/.build/guides/github-actions-sans-application.md +95 -0
- package/template/.build/guides/inviter-une-personne/index.html +28 -0
- package/template/.build/guides/inviter-une-personne.md +38 -0
- package/template/.build/guides/lire-les-logs/index.html +37 -0
- package/template/.build/guides/lire-les-logs.md +48 -0
- package/template/.build/guides/migrer-depuis-vercel/index.html +25 -0
- package/template/.build/guides/migrer-depuis-vercel.md +51 -0
- package/template/.build/guides/monorepo/index.html +40 -0
- package/template/.build/guides/monorepo.md +42 -0
- package/template/.build/guides/revenir-en-arriere/index.html +39 -0
- package/template/.build/guides/revenir-en-arriere.md +50 -0
- package/template/.build/guides/site-statique/index.html +41 -0
- package/template/.build/guides/site-statique.md +59 -0
- package/template/.build/guides/synchroniser-doppler/index.html +46 -0
- package/template/.build/guides/synchroniser-doppler.md +63 -0
- package/template/.build/guides/variables-d-environnement/index.html +73 -0
- package/template/.build/guides/variables-d-environnement.md +92 -0
- package/template/.build/images/famille/account.svg +1 -0
- package/template/.build/images/famille/analytics.svg +1 -0
- package/template/.build/images/famille/docs.svg +1 -0
- package/template/.build/images/famille/host.svg +1 -0
- package/template/.build/images/famille/mail.svg +1 -0
- package/template/.build/images/famille/portal.svg +1 -0
- package/template/.build/images/famille/status.svg +1 -0
- package/template/.build/images/logo.svg +1 -0
- package/template/.build/index.html +30 -86
- package/template/.build/index.md +59 -21
- package/template/.build/llms-full.txt +2330 -518
- package/template/.build/llms.txt +51 -34
- package/template/.build/pagefind/fragment/fr-ch_16987e2.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_2b4c97b.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_3294a5c.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_34858c9.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_39ddba1.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_4ab1899.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_4d3a52a.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_506c187.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_5aa255a.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_6841c7d.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_6dc7a2d.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_847edff.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_8745af7.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_8aac5e6.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_916b233.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_9fd014a.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_a0808f8.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_a4e1f69.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_a80a53d.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_a9e725b.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_ac3f64c.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_af292f1.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_af3e716.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_b0689a4.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_baed996.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_c89e27a.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_cd6ca13.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_d09af09.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_d4bcea8.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_dc2a134.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_ded7ddc.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_e2528cb.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_e3cbb4e.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_e7902d9.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_f48ca47.pf_fragment +0 -0
- package/template/.build/pagefind/index/fr-ch_8a5f905.pf_index +0 -0
- package/template/.build/pagefind/index/fr-ch_fbd9c96.pf_index +0 -0
- package/template/.build/pagefind/pagefind-entry.json +1 -1
- package/template/.build/pagefind/pagefind.fr-ch_211aacbfa7f0e.pf_meta +0 -0
- package/template/.build/reference/api/deploiements/index.html +326 -0
- package/template/.build/reference/api/deploiements.md +170 -0
- package/template/.build/reference/api/erreurs/index.html +102 -0
- package/template/.build/reference/api/erreurs.md +50 -0
- package/template/.build/reference/api/fichiers/index.html +82 -0
- package/template/.build/reference/api/fichiers.md +62 -0
- package/template/.build/reference/api/introduction/index.html +126 -0
- package/template/.build/reference/api/introduction.md +84 -0
- package/template/.build/reference/api/projets/index.html +184 -0
- package/template/.build/reference/api/projets.md +102 -0
- package/template/.build/reference/api/utilisateur/index.html +96 -0
- package/template/.build/reference/api/utilisateur.md +89 -0
- package/template/.build/reference/api/variables/index.html +75 -0
- package/template/.build/reference/api/variables.md +58 -0
- package/template/.build/reference/cli/index.html +165 -82
- package/template/.build/reference/cli.md +159 -23
- package/template/.build/reference/compatibilite/index.html +196 -0
- package/template/.build/reference/compatibilite.md +64 -0
- package/template/.build/reference/domaines/index.html +171 -0
- package/template/.build/reference/domaines.md +76 -0
- package/template/.build/reference/limites/index.html +159 -0
- package/template/.build/reference/limites.md +56 -0
- package/template/.build/reference/variables/index.html +164 -0
- package/template/.build/reference/variables.md +63 -0
- package/template/.build/reference/vercel-json/index.html +65 -0
- package/template/.build/reference/vercel-json.md +51 -0
- package/template/node_modules/.vite/deps/_metadata.json +8 -8
- package/template/src/content.config.ts +8 -2
- package/template/.build/_astro/Assistant.astro_astro_type_script_index_0_lang.DWgmlr85.js +0 -4
- package/template/.build/_astro/MobileTableOfContents.astro_astro_type_script_index_0_lang.C3fM4Kra.js +0 -1
- package/template/.build/_astro/Search.astro_astro_type_script_index_0_lang.Cn3-p701.js +0 -1
- package/template/.build/_astro/TableOfContents.astro_astro_type_script_index_0_lang.BpJaGz7G.js +0 -1
- package/template/.build/_astro/common.C-MpX45O.css +0 -3
- package/template/.build/_astro/logo-clair.BqNh6JNi.svg +0 -1
- package/template/.build/_astro/logo-sombre.BkgsFXxh.svg +0 -1
- package/template/.build/_astro/starlight-toc.D4UDIxQL.js +0 -1
- package/template/.build/_astro/ui-core.CrG20ya_.js +0 -2
- package/template/.build/demarrer/premiere-doc/index.html +0 -84
- package/template/.build/demarrer/premiere-doc.md +0 -65
- package/template/.build/explications/donnees/index.html +0 -114
- package/template/.build/explications/donnees.md +0 -28
- package/template/.build/explications/fonctionnement/index.html +0 -93
- package/template/.build/explications/fonctionnement.md +0 -32
- package/template/.build/guides/agents/index.html +0 -118
- package/template/.build/guides/agents.md +0 -54
- package/template/.build/guides/assistant/index.html +0 -119
- package/template/.build/guides/assistant.md +0 -46
- package/template/.build/guides/composants/index.html +0 -97
- package/template/.build/guides/composants.md +0 -101
- package/template/.build/guides/ecrire/index.html +0 -116
- package/template/.build/guides/ecrire.md +0 -63
- package/template/.build/guides/navigation/index.html +0 -90
- package/template/.build/guides/navigation.md +0 -63
- package/template/.build/guides/publier/index.html +0 -95
- package/template/.build/guides/publier.md +0 -65
- package/template/.build/guides/theme/index.html +0 -87
- package/template/.build/guides/theme.md +0 -33
- package/template/.build/images/favicon.svg +0 -1
- package/template/.build/images/logo-clair.svg +0 -1
- package/template/.build/images/logo-sombre.svg +0 -1
- package/template/.build/pagefind/fragment/fr-ch_2a431a9.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_456586a.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_4f8575c.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_68e734b.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_72b91f4.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_8f256dd.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_95a15cc.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_aa80c55.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_ab79738.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_cfa4336.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_dab8f5e.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_de60b43.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_e02aa49.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_e254a54.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_e2c46e3.pf_fragment +0 -0
- package/template/.build/pagefind/index/fr-ch_a71411b.pf_index +0 -0
- package/template/.build/pagefind/pagefind.fr-ch_2f3ea8fccf961.pf_meta +0 -0
- package/template/.build/reference/api-assistant/index.html +0 -161
- package/template/.build/reference/api-assistant.md +0 -70
- package/template/.build/reference/docs-json/index.html +0 -192
- package/template/.build/reference/docs-json.md +0 -43
- package/template/.build/reference/mcp/index.html +0 -151
- package/template/.build/reference/mcp.md +0 -49
package/docs.schema.json
CHANGED
|
@@ -248,6 +248,27 @@
|
|
|
248
248
|
}
|
|
249
249
|
}
|
|
250
250
|
},
|
|
251
|
+
"redirects": {
|
|
252
|
+
"maxItems": 500,
|
|
253
|
+
"type": "array",
|
|
254
|
+
"items": {
|
|
255
|
+
"type": "object",
|
|
256
|
+
"properties": {
|
|
257
|
+
"source": {
|
|
258
|
+
"type": "string",
|
|
259
|
+
"pattern": "^\\/(?!\\/)[A-Za-z0-9._~\\-/%]*$"
|
|
260
|
+
},
|
|
261
|
+
"destination": {
|
|
262
|
+
"type": "string",
|
|
263
|
+
"minLength": 1
|
|
264
|
+
},
|
|
265
|
+
"permanent": {
|
|
266
|
+
"type": "boolean"
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
"required": ["source", "destination"]
|
|
270
|
+
}
|
|
271
|
+
},
|
|
251
272
|
"assistant": {
|
|
252
273
|
"type": "object",
|
|
253
274
|
"properties": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hgdc/docs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Modèle de site de HGDC Docs : documentation MDX (docs.json) construite avec Astro Starlight, recherche, versions, llms.txt et assistant.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"@astrojs/starlight": "0.42.6",
|
|
32
32
|
"@fontsource-variable/geist": "5.3.0",
|
|
33
33
|
"@fontsource-variable/inter": "5.3.0",
|
|
34
|
+
"@mdx-js/mdx": "3.1.1",
|
|
34
35
|
"astro": "7.3.8",
|
|
35
36
|
"github-slugger": "2.0.0",
|
|
36
37
|
"hast-util-select": "6.0.4",
|
|
@@ -41,6 +42,7 @@
|
|
|
41
42
|
"remark-stringify": "11.0.0",
|
|
42
43
|
"unified": "11.0.5",
|
|
43
44
|
"vfile": "6.0.3",
|
|
45
|
+
"yaml": "2.9.1",
|
|
44
46
|
"zod": "4.6.5"
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
package/src/build/auto-import.ts
CHANGED
|
@@ -1,30 +1,7 @@
|
|
|
1
1
|
import type { Root } from "mdast"
|
|
2
2
|
import type { VFile } from "vfile"
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
* Composants disponibles dans chaque page MDX sans `import`, comme chez Mintlify
|
|
6
|
-
* (`<Note>`, `<Steps>`, `<Card>`…). Le plugin ajoute en tête du fichier l'import des
|
|
7
|
-
* composants que la page n'importe pas déjà elle-même.
|
|
8
|
-
*/
|
|
9
|
-
export const MDX_COMPONENTS = [
|
|
10
|
-
"Accordion",
|
|
11
|
-
"AccordionGroup",
|
|
12
|
-
"Card",
|
|
13
|
-
"CardGroup",
|
|
14
|
-
"Check",
|
|
15
|
-
"CodeGroup",
|
|
16
|
-
"Columns",
|
|
17
|
-
"Danger",
|
|
18
|
-
"Frame",
|
|
19
|
-
"Info",
|
|
20
|
-
"Note",
|
|
21
|
-
"Step",
|
|
22
|
-
"Steps",
|
|
23
|
-
"Tab",
|
|
24
|
-
"Tabs",
|
|
25
|
-
"Tip",
|
|
26
|
-
"Warning",
|
|
27
|
-
] as const
|
|
4
|
+
import { MDX_COMPONENTS } from "../core/components.ts"
|
|
28
5
|
|
|
29
6
|
const SOURCE = "@hgdc/docs/components"
|
|
30
7
|
|
|
@@ -64,6 +41,10 @@ function importNode(name: string): EsmNode {
|
|
|
64
41
|
}
|
|
65
42
|
}
|
|
66
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Ajoute en tête de chaque page MDX l'import des composants (`core/components.ts`) que la
|
|
46
|
+
* page n'importe pas déjà elle-même : `<Note>`, `<Steps>`… s'écrivent sans `import`.
|
|
47
|
+
*/
|
|
67
48
|
export function remarkAutoImport() {
|
|
68
49
|
return (tree: Root, file: VFile) => {
|
|
69
50
|
if (!String(file.path ?? file.history.at(-1) ?? "").endsWith(".mdx")) return
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { Element, ElementContent, Root, RootContent } from "hast"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mise en forme du contenu, au build.
|
|
5
|
+
*
|
|
6
|
+
* Titre d'endpoint (`## GET /v9/projects`) en barre de méthode : la méthode en pastille
|
|
7
|
+
* colorée, le chemin en police mono, ses paramètres (`:id`, `{id}`) soulignés. Le texte du
|
|
8
|
+
* titre ne change pas : l'ancre, la table des matières et la recherche restent les mêmes.
|
|
9
|
+
* Tableau : enveloppé dans `.hd-table`, qui défile en largeur sans déborder de la colonne.
|
|
10
|
+
*/
|
|
11
|
+
const ENDPOINT = /^(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\s+(\/\S*)$/
|
|
12
|
+
const PARAM = /(:[A-Za-z_][\w]*|\{[^}/]+\})/
|
|
13
|
+
|
|
14
|
+
export function parseEndpoint(text: string): { method: string; path: string } | null {
|
|
15
|
+
const match = ENDPOINT.exec(text.trim())
|
|
16
|
+
return match ? { method: match[1]!, path: match[2]! } : null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function textOf(node: Element): string | null {
|
|
20
|
+
let text = ""
|
|
21
|
+
for (const child of node.children) {
|
|
22
|
+
if (child.type === "text") text += child.value
|
|
23
|
+
else if (child.type === "element" && child.tagName === "code") {
|
|
24
|
+
for (const inner of child.children) if (inner.type === "text") text += inner.value
|
|
25
|
+
} else return null
|
|
26
|
+
}
|
|
27
|
+
return text
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function pathChildren(path: string): Array<ElementContent> {
|
|
31
|
+
return path
|
|
32
|
+
.split(PARAM)
|
|
33
|
+
.filter(Boolean)
|
|
34
|
+
.map((part) =>
|
|
35
|
+
PARAM.test(part)
|
|
36
|
+
? {
|
|
37
|
+
type: "element",
|
|
38
|
+
tagName: "span",
|
|
39
|
+
properties: { className: ["hd-path__param"] },
|
|
40
|
+
children: [{ type: "text", value: part }],
|
|
41
|
+
}
|
|
42
|
+
: { type: "text", value: part },
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function rehypeDocsContent() {
|
|
47
|
+
const walk = (nodes: Array<RootContent | ElementContent>) => {
|
|
48
|
+
for (const [index, node] of nodes.entries()) {
|
|
49
|
+
if (node.type !== "element") continue
|
|
50
|
+
// Tableau : un cadre qui défile seul en largeur, le tableau garde toute la largeur.
|
|
51
|
+
if (node.tagName === "table") {
|
|
52
|
+
nodes[index] = { type: "element", tagName: "div", properties: { className: ["hd-table"] }, children: [node] }
|
|
53
|
+
continue
|
|
54
|
+
}
|
|
55
|
+
if (node.tagName !== "h2" && node.tagName !== "h3") {
|
|
56
|
+
walk(node.children)
|
|
57
|
+
continue
|
|
58
|
+
}
|
|
59
|
+
const text = textOf(node)
|
|
60
|
+
const endpoint = text ? parseEndpoint(text) : null
|
|
61
|
+
if (!endpoint) continue
|
|
62
|
+
node.properties.className = [...((node.properties.className as Array<string>) ?? []), "hd-endpoint"]
|
|
63
|
+
node.children = [
|
|
64
|
+
{
|
|
65
|
+
type: "element",
|
|
66
|
+
tagName: "span",
|
|
67
|
+
properties: { className: ["hd-method"], dataMethod: endpoint.method.toLowerCase() },
|
|
68
|
+
children: [{ type: "text", value: endpoint.method }],
|
|
69
|
+
},
|
|
70
|
+
{ type: "text", value: " " },
|
|
71
|
+
{
|
|
72
|
+
type: "element",
|
|
73
|
+
tagName: "code",
|
|
74
|
+
properties: { className: ["hd-path"] },
|
|
75
|
+
children: pathChildren(endpoint.path),
|
|
76
|
+
},
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Typé en `unknown` : Astro et ce paquet ne résolvent pas toujours le même @types/hast.
|
|
81
|
+
return (tree: unknown) => walk((tree as Root).children)
|
|
82
|
+
}
|
package/src/build/markdown.ts
CHANGED
|
@@ -70,12 +70,17 @@ function replaceCodeBlocks(content: Element): void {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* Encadré → citation dont la première ligne porte le titre en gras : `> **Note**`. Le titre
|
|
75
|
+
* est celui de la page, sinon le nom du type (`aria-label` de `.hd-callout`).
|
|
76
|
+
*/
|
|
74
77
|
function replaceAsides(content: Element): void {
|
|
75
|
-
for (const aside of selectAll("aside.starlight-aside", content)) {
|
|
76
|
-
const title = select(".starlight-aside__title", aside)
|
|
77
|
-
const body = select(".starlight-aside__content", aside)
|
|
78
|
-
|
|
78
|
+
for (const aside of selectAll("aside.starlight-aside, aside.hd-callout", content)) {
|
|
79
|
+
const title = select(".starlight-aside__title, .hd-callout__title", aside)
|
|
80
|
+
const body = select(".starlight-aside__content, .hd-callout__body", aside)
|
|
81
|
+
if (body && title) body.children = body.children.filter((child) => child !== title)
|
|
82
|
+
const named = typeof aside.properties["ariaLabel"] === "string" ? aside.properties["ariaLabel"] : ""
|
|
83
|
+
const label = title ? toString(title as Parameters<typeof toString>[0]).trim() : named
|
|
79
84
|
const quote: Element = {
|
|
80
85
|
type: "element",
|
|
81
86
|
tagName: "blockquote",
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
+
import Icon from "../overrides/Icon.astro"
|
|
3
|
+
|
|
2
4
|
interface Props {
|
|
3
5
|
title: string
|
|
4
6
|
defaultOpen?: boolean
|
|
@@ -7,6 +9,6 @@ const { title, defaultOpen = false } = Astro.props
|
|
|
7
9
|
---
|
|
8
10
|
|
|
9
11
|
<details class="hgdc-accordion" open={defaultOpen}>
|
|
10
|
-
<summary>{title}</summary>
|
|
12
|
+
<summary><Icon name="chevron-right" size={16} class="hgdc-accordion__chevron" /><span>{title}</span></summary>
|
|
11
13
|
<div class="hgdc-accordion__body"><slot /></div>
|
|
12
14
|
</details>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Icon from "../overrides/Icon.astro"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Encadré commun à Note, Info, Tip, Check, Warning et Danger : un lavis de sa couleur, un
|
|
6
|
+
* filet de la même teinte et son icône. Le type est dit au lecteur d'écran.
|
|
7
|
+
*/
|
|
8
|
+
export type CalloutTone = "note" | "info" | "tip" | "check" | "warning" | "danger"
|
|
9
|
+
interface Props {
|
|
10
|
+
tone: CalloutTone
|
|
11
|
+
title?: string | undefined
|
|
12
|
+
}
|
|
13
|
+
const LABELS: Record<CalloutTone, string> = {
|
|
14
|
+
note: "Note",
|
|
15
|
+
info: "Info",
|
|
16
|
+
tip: "Astuce",
|
|
17
|
+
check: "Validé",
|
|
18
|
+
warning: "Attention",
|
|
19
|
+
danger: "Danger",
|
|
20
|
+
}
|
|
21
|
+
const ICONS = { note: "note", info: "info", tip: "tip", check: "circle-check", warning: "warning", danger: "danger" } as const
|
|
22
|
+
const { tone, title } = Astro.props
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
<aside class="hd-callout" data-tone={tone} aria-label={title ?? LABELS[tone]}>
|
|
26
|
+
<Icon name={ICONS[tone]} class="hd-callout__icon" />
|
|
27
|
+
<div class="hd-callout__body">
|
|
28
|
+
{title && <p class="hd-callout__title">{title}</p>}
|
|
29
|
+
<slot />
|
|
30
|
+
</div>
|
|
31
|
+
</aside>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
+
import Icon from "../overrides/Icon.astro"
|
|
3
|
+
|
|
2
4
|
interface Props {
|
|
3
5
|
title: string
|
|
4
6
|
href?: string
|
|
@@ -10,6 +12,6 @@ const Tag = href ? "a" : "div"
|
|
|
10
12
|
---
|
|
11
13
|
|
|
12
14
|
<Tag class:list={["hgdc-card", { "hgdc-card--link": href }]} href={href}>
|
|
13
|
-
<span class="hgdc-card__title">{title}</span>
|
|
15
|
+
<span class="hgdc-card__title">{title}{href && <Icon name="arrow-right" size={16} class="hgdc-card__arrow" />}</span>
|
|
14
16
|
<div class="hgdc-card__body"><slot /></div>
|
|
15
17
|
</Tag>
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
import
|
|
2
|
+
import Callout from "./Callout.astro"
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
title?: string
|
|
6
6
|
}
|
|
7
|
-
const { title } = Astro.props
|
|
8
7
|
---
|
|
9
8
|
|
|
10
|
-
<
|
|
9
|
+
<Callout tone="check" title={Astro.props.title}><slot /></Callout>
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
+
// Plusieurs blocs de code en onglets, nommés d'après le titre de chaque bloc (```bash npm).
|
|
3
|
+
// Sans JavaScript, seul le premier bloc s'affiche ; le script ajoute les onglets.
|
|
2
4
|
---
|
|
3
5
|
|
|
4
|
-
<
|
|
6
|
+
<hd-code-group class="hgdc-code-group not-content"><slot /></hd-code-group>
|
|
7
|
+
|
|
8
|
+
<script>
|
|
9
|
+
import { defineCodeGroup } from "../widget/code.ts"
|
|
10
|
+
|
|
11
|
+
defineCodeGroup()
|
|
12
|
+
</script>
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
import
|
|
2
|
+
import Callout from "./Callout.astro"
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
title?: string
|
|
6
6
|
}
|
|
7
|
-
const { title } = Astro.props
|
|
8
7
|
---
|
|
9
8
|
|
|
10
|
-
<
|
|
9
|
+
<Callout tone="danger" title={Astro.props.title}><slot /></Callout>
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
import
|
|
2
|
+
import Callout from "./Callout.astro"
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
title?: string
|
|
6
6
|
}
|
|
7
|
-
const { title = "Info" } = Astro.props
|
|
8
7
|
---
|
|
9
8
|
|
|
10
|
-
<
|
|
9
|
+
<Callout tone="info" title={Astro.props.title}><slot /></Callout>
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
import
|
|
2
|
+
import Callout from "./Callout.astro"
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
title?: string
|
|
6
6
|
}
|
|
7
|
-
const { title } = Astro.props
|
|
8
7
|
---
|
|
9
8
|
|
|
10
|
-
<
|
|
9
|
+
<Callout tone="note" title={Astro.props.title}><slot /></Callout>
|
package/src/components/Tip.astro
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
import
|
|
2
|
+
import Callout from "./Callout.astro"
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
title?: string
|
|
6
6
|
}
|
|
7
|
-
const { title } = Astro.props
|
|
8
7
|
---
|
|
9
8
|
|
|
10
|
-
<
|
|
9
|
+
<Callout tone="tip" title={Astro.props.title}><slot /></Callout>
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
import
|
|
2
|
+
import Callout from "./Callout.astro"
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
title?: string
|
|
6
6
|
}
|
|
7
|
-
const { title } = Astro.props
|
|
8
7
|
---
|
|
9
8
|
|
|
10
|
-
<
|
|
9
|
+
<Callout tone="warning" title={Astro.props.title}><slot /></Callout>
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composants disponibles dans chaque page MDX sans `import`, comme chez Mintlify
|
|
3
|
+
* (`<Note>`, `<Steps>`, `<Card>`…). Lus par le build (`build/auto-import.ts`) et par
|
|
4
|
+
* l'éditeur de la console (validation, insertion par « / » ou « < », mode visuel).
|
|
5
|
+
* Les props décrites ici sont celles des fichiers `src/components/*.astro`.
|
|
6
|
+
*/
|
|
7
|
+
export const MDX_COMPONENTS = [
|
|
8
|
+
"Accordion",
|
|
9
|
+
"AccordionGroup",
|
|
10
|
+
"Card",
|
|
11
|
+
"CardGroup",
|
|
12
|
+
"Check",
|
|
13
|
+
"CodeGroup",
|
|
14
|
+
"Columns",
|
|
15
|
+
"Danger",
|
|
16
|
+
"Frame",
|
|
17
|
+
"Info",
|
|
18
|
+
"Note",
|
|
19
|
+
"Step",
|
|
20
|
+
"Steps",
|
|
21
|
+
"Tab",
|
|
22
|
+
"Tabs",
|
|
23
|
+
"Tip",
|
|
24
|
+
"Warning",
|
|
25
|
+
] as const
|
|
26
|
+
|
|
27
|
+
export type MdxComponent = (typeof MDX_COMPONENTS)[number]
|
|
28
|
+
|
|
29
|
+
export function isMdxComponent(name: string): name is MdxComponent {
|
|
30
|
+
return (MDX_COMPONENTS as ReadonlyArray<string>).includes(name)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type ComponentProp = {
|
|
34
|
+
name: string
|
|
35
|
+
label: string
|
|
36
|
+
type: "string" | "number" | "boolean"
|
|
37
|
+
required?: boolean
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Props de chaque composant, pour les formulaires du mode visuel. */
|
|
41
|
+
export const COMPONENT_PROPS: Record<MdxComponent, ReadonlyArray<ComponentProp>> = {
|
|
42
|
+
Accordion: [
|
|
43
|
+
{ name: "title", label: "Titre", type: "string", required: true },
|
|
44
|
+
{ name: "defaultOpen", label: "Ouvert au départ", type: "boolean" },
|
|
45
|
+
],
|
|
46
|
+
AccordionGroup: [],
|
|
47
|
+
Card: [
|
|
48
|
+
{ name: "title", label: "Titre", type: "string", required: true },
|
|
49
|
+
{ name: "href", label: "Lien", type: "string" },
|
|
50
|
+
],
|
|
51
|
+
CardGroup: [{ name: "cols", label: "Colonnes", type: "number" }],
|
|
52
|
+
Check: [{ name: "title", label: "Titre", type: "string" }],
|
|
53
|
+
CodeGroup: [],
|
|
54
|
+
Columns: [{ name: "cols", label: "Colonnes", type: "number" }],
|
|
55
|
+
Danger: [{ name: "title", label: "Titre", type: "string" }],
|
|
56
|
+
Frame: [{ name: "caption", label: "Légende", type: "string" }],
|
|
57
|
+
Info: [{ name: "title", label: "Titre", type: "string" }],
|
|
58
|
+
Note: [{ name: "title", label: "Titre", type: "string" }],
|
|
59
|
+
Step: [{ name: "title", label: "Titre", type: "string", required: true }],
|
|
60
|
+
Steps: [],
|
|
61
|
+
Tab: [{ name: "title", label: "Titre", type: "string", required: true }],
|
|
62
|
+
Tabs: [{ name: "syncKey", label: "Clé de synchronisation", type: "string" }],
|
|
63
|
+
Tip: [{ name: "title", label: "Titre", type: "string" }],
|
|
64
|
+
Warning: [{ name: "title", label: "Titre", type: "string" }],
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type BlockCategory = "Encadrés" | "Mise en page" | "Contenu"
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Blocs proposés à l'insertion, dans l'ordre du menu. `snippet` est le MDX inséré ; `$|`
|
|
71
|
+
* marque l'endroit où placer le curseur. Plusieurs blocs peuvent produire le même
|
|
72
|
+
* composant (colonnes à 2, 3 ou 4).
|
|
73
|
+
*/
|
|
74
|
+
export type Block = {
|
|
75
|
+
id: string
|
|
76
|
+
label: string
|
|
77
|
+
description: string
|
|
78
|
+
category: BlockCategory
|
|
79
|
+
keywords: ReadonlyArray<string>
|
|
80
|
+
snippet: string
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const callout = (name: string, label: string, description: string, keywords: Array<string>): Block => ({
|
|
84
|
+
id: name.toLowerCase(),
|
|
85
|
+
label,
|
|
86
|
+
description,
|
|
87
|
+
category: "Encadrés",
|
|
88
|
+
keywords: [name.toLowerCase(), ...keywords],
|
|
89
|
+
snippet: `<${name}>\n$|\n</${name}>`,
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
const columns = (cols: number): Block => ({
|
|
93
|
+
id: `columns-${cols}`,
|
|
94
|
+
label: `${cols} colonnes`,
|
|
95
|
+
description: `Cartes côte à côte, sur ${cols} colonnes.`,
|
|
96
|
+
category: "Mise en page",
|
|
97
|
+
keywords: ["colonnes", "columns", "grille", String(cols)],
|
|
98
|
+
snippet: `<Columns cols={${cols}}>\n${Array.from({ length: cols }, (_, i) => ` <Card title="Carte ${i + 1}">${i === 0 ? "$|" : ""}</Card>`).join("\n")}\n</Columns>`,
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
export const BLOCKS: ReadonlyArray<Block> = [
|
|
102
|
+
callout("Note", "Note", "Une information utile à côté du texte.", ["information", "remarque"]),
|
|
103
|
+
callout("Tip", "Conseil", "Une astuce qui fait gagner du temps.", ["astuce", "conseil"]),
|
|
104
|
+
callout("Info", "Info", "Un contexte ou une précision.", ["information"]),
|
|
105
|
+
callout("Warning", "Attention", "Un point à ne pas manquer.", ["attention", "avertissement"]),
|
|
106
|
+
callout("Danger", "Danger", "Une action risquée ou irréversible.", ["danger", "risque"]),
|
|
107
|
+
callout("Check", "Validé", "Une étape réussie, un résultat attendu.", ["validé", "succès", "ok"]),
|
|
108
|
+
columns(2),
|
|
109
|
+
columns(3),
|
|
110
|
+
columns(4),
|
|
111
|
+
{
|
|
112
|
+
id: "steps",
|
|
113
|
+
label: "Étapes",
|
|
114
|
+
description: "Une marche à suivre numérotée.",
|
|
115
|
+
category: "Mise en page",
|
|
116
|
+
keywords: ["étapes", "steps", "procédure"],
|
|
117
|
+
snippet:
|
|
118
|
+
'<Steps>\n <Step title="Première étape">\n $|\n </Step>\n <Step title="Deuxième étape">\n </Step>\n</Steps>',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: "tabs",
|
|
122
|
+
label: "Onglets",
|
|
123
|
+
description: "Plusieurs variantes d'un même contenu.",
|
|
124
|
+
category: "Mise en page",
|
|
125
|
+
keywords: ["onglets", "tabs"],
|
|
126
|
+
snippet: '<Tabs>\n <Tab title="Premier">\n $|\n </Tab>\n <Tab title="Second">\n </Tab>\n</Tabs>',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "accordion",
|
|
130
|
+
label: "Accordéon",
|
|
131
|
+
description: "Un détail replié, ouvert au clic.",
|
|
132
|
+
category: "Mise en page",
|
|
133
|
+
keywords: ["accordéon", "accordion", "replié", "faq"],
|
|
134
|
+
snippet: '<AccordionGroup>\n <Accordion title="Question">\n $|\n </Accordion>\n</AccordionGroup>',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
id: "card",
|
|
138
|
+
label: "Carte",
|
|
139
|
+
description: "Un lien mis en avant, avec un titre.",
|
|
140
|
+
category: "Contenu",
|
|
141
|
+
keywords: ["carte", "card", "lien"],
|
|
142
|
+
snippet: '<Card title="Titre" href="/">\n $|\n</Card>',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
id: "code-group",
|
|
146
|
+
label: "Groupe de code",
|
|
147
|
+
description: "Le même exemple en plusieurs langages.",
|
|
148
|
+
category: "Contenu",
|
|
149
|
+
keywords: ["code", "codegroup", "exemple"],
|
|
150
|
+
snippet: "<CodeGroup>\n\n```bash npm\n$|\n```\n\n```bash bun\n\n```\n\n</CodeGroup>",
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
id: "frame",
|
|
154
|
+
label: "Cadre",
|
|
155
|
+
description: "Une image ou une capture, avec sa légende.",
|
|
156
|
+
category: "Contenu",
|
|
157
|
+
keywords: ["cadre", "frame", "image", "capture"],
|
|
158
|
+
snippet: '<Frame caption="Légende">\n \n</Frame>',
|
|
159
|
+
},
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
/** Texte à insérer et position du curseur dans ce texte. */
|
|
163
|
+
export function expandSnippet(snippet: string): { text: string; cursor: number } {
|
|
164
|
+
const cursor = snippet.indexOf("$|")
|
|
165
|
+
return cursor === -1 ? { text: snippet, cursor: snippet.length } : { text: snippet.replace("$|", ""), cursor }
|
|
166
|
+
}
|
package/src/core/config.ts
CHANGED
|
@@ -56,6 +56,47 @@ const logo = z.union([
|
|
|
56
56
|
z.object({ light: z.string(), dark: z.string().optional(), href: z.string().optional() }),
|
|
57
57
|
])
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Réseaux du pied de page : clé de `footer.socials` (celles de Mintlify), libellé, icône de
|
|
61
|
+
* Starlight. Lu par le build et par le formulaire des réglages de la console.
|
|
62
|
+
*/
|
|
63
|
+
export const SOCIAL_NETWORKS = {
|
|
64
|
+
linkedin: { label: "LinkedIn", icon: "linkedin" },
|
|
65
|
+
github: { label: "GitHub", icon: "github" },
|
|
66
|
+
gitlab: { label: "GitLab", icon: "gitlab" },
|
|
67
|
+
x: { label: "X", icon: "x.com" },
|
|
68
|
+
youtube: { label: "YouTube", icon: "youtube" },
|
|
69
|
+
instagram: { label: "Instagram", icon: "instagram" },
|
|
70
|
+
facebook: { label: "Facebook", icon: "facebook" },
|
|
71
|
+
discord: { label: "Discord", icon: "discord" },
|
|
72
|
+
mastodon: { label: "Mastodon", icon: "mastodon" },
|
|
73
|
+
bluesky: { label: "Bluesky", icon: "blueSky" },
|
|
74
|
+
website: { label: "Site web", icon: "external" },
|
|
75
|
+
} as const
|
|
76
|
+
|
|
77
|
+
/** Ancienne écriture acceptée : `x.com` (Starlight) et `twitter` désignent X. */
|
|
78
|
+
const SOCIAL_ALIASES: Record<string, keyof typeof SOCIAL_NETWORKS> = { "x.com": "x", twitter: "x" }
|
|
79
|
+
|
|
80
|
+
export function socialNetwork(key: string): (typeof SOCIAL_NETWORKS)[keyof typeof SOCIAL_NETWORKS] | null {
|
|
81
|
+
const name = (SOCIAL_ALIASES[key] ?? key) as keyof typeof SOCIAL_NETWORKS
|
|
82
|
+
return SOCIAL_NETWORKS[name] ?? null
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const REDIRECT_SOURCE = /^\/(?!\/)[A-Za-z0-9._~\-/%]*$/
|
|
86
|
+
|
|
87
|
+
/** Ancienne adresse vers la nouvelle (champ `redirects` de Mintlify), sans motif. */
|
|
88
|
+
const redirect = z.object({
|
|
89
|
+
source: z.string().regex(REDIRECT_SOURCE, "adresse source attendue, commençant par « / » (ex. /guides/ancien)"),
|
|
90
|
+
destination: z
|
|
91
|
+
.string()
|
|
92
|
+
.min(1)
|
|
93
|
+
.refine(
|
|
94
|
+
(value) => /^\/(?!\/)/.test(value) || value.startsWith("https://"),
|
|
95
|
+
"destination attendue : un chemin du site (« /… ») ou une adresse https://",
|
|
96
|
+
),
|
|
97
|
+
permanent: z.boolean().optional(),
|
|
98
|
+
})
|
|
99
|
+
|
|
59
100
|
export const docsConfigSchema = z.object({
|
|
60
101
|
$schema: z.string().optional(),
|
|
61
102
|
name: z.string().min(1).max(80),
|
|
@@ -86,6 +127,7 @@ export const docsConfigSchema = z.object({
|
|
|
86
127
|
})
|
|
87
128
|
.optional(),
|
|
88
129
|
footer: z.object({ socials: z.record(z.string(), z.url()).optional() }).optional(),
|
|
130
|
+
redirects: z.array(redirect).max(500, "500 redirections au plus").optional(),
|
|
89
131
|
assistant: z
|
|
90
132
|
.object({
|
|
91
133
|
enabled: z.boolean().default(true),
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Contrat de `POST /api/v1/feedback` entre le bas de chaque page (« Cette page t'a aidé ? »)
|
|
5
|
+
* et la console. Aucune donnée personnelle : la page, la réponse, un commentaire facultatif.
|
|
6
|
+
*/
|
|
7
|
+
export const MAX_FEEDBACK_COMMENT = 1000
|
|
8
|
+
/** Code joint à un signalement « Signaler un code faux », tronqué par le site. */
|
|
9
|
+
export const MAX_FEEDBACK_CODE = 2000
|
|
10
|
+
|
|
11
|
+
export const feedbackRequestSchema = z
|
|
12
|
+
.object({
|
|
13
|
+
project: z.string().regex(/^[a-z0-9]{8,64}$/),
|
|
14
|
+
/** Chemin de la page, `base` compris (`/docs/guides/publier/`). */
|
|
15
|
+
page: z.string().startsWith("/").max(512),
|
|
16
|
+
helpful: z.boolean(),
|
|
17
|
+
comment: z.string().trim().max(MAX_FEEDBACK_COMMENT).optional(),
|
|
18
|
+
/** `code` : « Signaler un code faux » sur un bloc de code ; absent, l'avis porte sur la page. */
|
|
19
|
+
kind: z.enum(["page", "code"]).optional(),
|
|
20
|
+
code: z.string().max(MAX_FEEDBACK_CODE).optional(),
|
|
21
|
+
})
|
|
22
|
+
.refine((value) => value.kind !== "code" || Boolean(value.comment), {
|
|
23
|
+
message: "un signalement de code dit ce qui ne va pas",
|
|
24
|
+
path: ["comment"],
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
export type FeedbackRequest = z.infer<typeof feedbackRequestSchema>
|
package/src/core/theme.ts
CHANGED
|
@@ -12,8 +12,10 @@ export type Theme = { light: AccentPalette; dark: AccentPalette }
|
|
|
12
12
|
/** Accent violet de la DA HGDC (`--brand-accent` du kit), si le client n'en donne pas. */
|
|
13
13
|
export const HGDC_ACCENT = "#7c3aed"
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
/** Fonds sur lesquels l'accent doit tenir 4,5:1 : la surface la plus proche de lui (élément
|
|
16
|
+
* courant teinté, encart `muted`), un cran plus foncé ou plus clair que la page. */
|
|
17
|
+
const LIGHT_BG = "#f2f2f2"
|
|
18
|
+
const DARK_BG = "#2a2a2a"
|
|
17
19
|
|
|
18
20
|
export function themeFor(primary: string = HGDC_ACCENT, dark?: string): Theme {
|
|
19
21
|
const base = hexToOklch(primary)
|
|
@@ -48,7 +50,8 @@ export function withContrast(color: Oklch, background: string, ratio: number): s
|
|
|
48
50
|
export function themeCss(theme: Theme): string {
|
|
49
51
|
const vars = (p: AccentPalette) =>
|
|
50
52
|
`--sl-color-accent-low:${p.low};--sl-color-accent:${p.accent};--sl-color-accent-high:${p.high};--hgdc-on-accent:${p.onAccent};`
|
|
51
|
-
|
|
53
|
+
// Clair par défaut : le sombre ne vaut que choisi (`data-hd-theme`, overrides/ThemeProvider.astro).
|
|
54
|
+
return `:root{${vars(theme.dark)}}:root:not([data-hd-theme="dark"]){${vars(theme.light)}}`
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
// --- Conversions sRGB ↔ OKLCH (Björn Ottosson) et contraste WCAG 2 ---
|