@hgdc/docs 0.0.0-stage → 0.1.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/bin/hgdc-docs.mjs +48 -0
- package/docs.schema.json +294 -0
- package/package.json +50 -4
- package/src/build/auto-import.ts +74 -0
- package/src/build/markdown.ts +114 -0
- package/src/build/outputs.ts +91 -0
- package/src/build/public-files.test.ts +29 -0
- package/src/build/public-files.ts +35 -0
- package/src/components/Accordion.astro +12 -0
- package/src/components/AccordionGroup.astro +4 -0
- package/src/components/Card.astro +15 -0
- package/src/components/CardGroup.astro +8 -0
- package/src/components/Check.astro +10 -0
- package/src/components/CodeGroup.astro +4 -0
- package/src/components/Columns.astro +8 -0
- package/src/components/Danger.astro +10 -0
- package/src/components/Frame.astro +11 -0
- package/src/components/Info.astro +10 -0
- package/src/components/Note.astro +10 -0
- package/src/components/Step.astro +11 -0
- package/src/components/Steps.astro +4 -0
- package/src/components/Tab.astro +9 -0
- package/src/components/Tabs.astro +9 -0
- package/src/components/Tip.astro +10 -0
- package/src/components/Warning.astro +10 -0
- package/src/core/answer-markdown.ts +109 -0
- package/src/core/assistant-api.ts +65 -0
- package/src/core/chunk.ts +134 -0
- package/src/core/config.ts +153 -0
- package/src/core/core.test.ts +253 -0
- package/src/core/corpus.ts +42 -0
- package/src/core/json-schema.ts +12 -0
- package/src/core/llms.ts +95 -0
- package/src/core/navigation.ts +88 -0
- package/src/core/theme.ts +111 -0
- package/src/integration.ts +229 -0
- package/src/locals.d.ts +6 -0
- package/src/overrides/Assistant.astro +72 -0
- package/src/overrides/Head.astro +12 -0
- package/src/overrides/PageFrame.astro +15 -0
- package/src/overrides/PageTitle.astro +94 -0
- package/src/overrides/Sidebar.astro +60 -0
- package/src/overrides/route-data.ts +33 -0
- package/src/styles/theme.css +773 -0
- package/src/virtual.d.ts +6 -0
- package/src/widget/client.ts +252 -0
- package/template/.astro/collections/docs.schema.json +651 -0
- package/template/.astro/content-assets.mjs +1 -0
- package/template/.astro/content-modules.mjs +18 -0
- package/template/.astro/content.d.ts +179 -0
- package/template/.astro/types.d.ts +2 -0
- package/template/.build/.well-known/llms.txt +38 -0
- package/template/.build/404.html +42 -0
- package/template/.build/_astro/Assistant.astro_astro_type_script_index_0_lang.DWgmlr85.js +4 -0
- package/template/.build/_astro/MobileTableOfContents.astro_astro_type_script_index_0_lang.C3fM4Kra.js +1 -0
- package/template/.build/_astro/Search.astro_astro_type_script_index_0_lang.g9hoxVJg.js +1 -0
- package/template/.build/_astro/TableOfContents.astro_astro_type_script_index_0_lang.BpJaGz7G.js +1 -0
- package/template/.build/_astro/common.8GHCkW7i.css +3 -0
- package/template/.build/_astro/ec.0vx5m.js +3 -0
- package/template/.build/_astro/ec.8nqtp.css +1 -0
- package/template/.build/_astro/geist-cyrillic-ext-wght-normal.DjL33-gN.woff2 +0 -0
- package/template/.build/_astro/geist-cyrillic-wght-normal.BEAKL7Jp.woff2 +0 -0
- package/template/.build/_astro/geist-latin-ext-wght-normal.DC-KSUi6.woff2 +0 -0
- package/template/.build/_astro/geist-latin-wght-normal.BgDaEnEv.woff2 +0 -0
- package/template/.build/_astro/geist-vietnamese-wght-normal.6IgcOCM7.woff2 +0 -0
- package/template/.build/_astro/inter-cyrillic-ext-wght-normal.BOeWTOD4.woff2 +0 -0
- package/template/.build/_astro/inter-cyrillic-wght-normal.DqGufNeO.woff2 +0 -0
- package/template/.build/_astro/inter-greek-ext-wght-normal.DlzME5K_.woff2 +0 -0
- package/template/.build/_astro/inter-greek-wght-normal.CkhJZR-_.woff2 +0 -0
- package/template/.build/_astro/inter-latin-ext-wght-normal.DO1Apj_S.woff2 +0 -0
- package/template/.build/_astro/inter-latin-wght-normal.Dx4kXJAl.woff2 +0 -0
- package/template/.build/_astro/inter-vietnamese-wght-normal.CBcvBZtf.woff2 +0 -0
- package/template/.build/_astro/logo-clair.BqNh6JNi.svg +1 -0
- package/template/.build/_astro/logo-sombre.BkgsFXxh.svg +1 -0
- package/template/.build/_astro/page.cNngjUgL.js +1 -0
- package/template/.build/_astro/print.ehPL0gv-.css +1 -0
- package/template/.build/_astro/starlight-toc.D4UDIxQL.js +1 -0
- package/template/.build/_astro/ui-core.Clh5jUUO.js +2 -0
- package/template/.build/_hgdc/corpus.json +1 -0
- package/template/.build/demarrer/premiere-doc/index.html +84 -0
- package/template/.build/demarrer/premiere-doc.md +65 -0
- package/template/.build/explications/donnees/index.html +114 -0
- package/template/.build/explications/donnees.md +28 -0
- package/template/.build/explications/fonctionnement/index.html +92 -0
- package/template/.build/explications/fonctionnement.md +32 -0
- package/template/.build/guides/agents/index.html +113 -0
- package/template/.build/guides/agents.md +40 -0
- package/template/.build/guides/assistant/index.html +117 -0
- package/template/.build/guides/assistant.md +42 -0
- package/template/.build/guides/composants/index.html +97 -0
- package/template/.build/guides/composants.md +103 -0
- package/template/.build/guides/ecrire/index.html +115 -0
- package/template/.build/guides/ecrire.md +63 -0
- package/template/.build/guides/navigation/index.html +89 -0
- package/template/.build/guides/navigation.md +63 -0
- package/template/.build/guides/publier/index.html +86 -0
- package/template/.build/guides/publier.md +65 -0
- package/template/.build/guides/theme/index.html +86 -0
- package/template/.build/guides/theme.md +33 -0
- package/template/.build/images/favicon.svg +1 -0
- package/template/.build/images/logo-clair.svg +1 -0
- package/template/.build/images/logo-sombre.svg +1 -0
- package/template/.build/index.html +87 -0
- package/template/.build/index.md +35 -0
- package/template/.build/llms-full.txt +830 -0
- package/template/.build/llms.txt +38 -0
- package/template/.build/pagefind/fragment/fr-ch_148313b.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_424fd16.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_4f8575c.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_5a4d77d.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_6c36edc.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_73d7887.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_8234ed3.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_8f8a19e.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_9f1b981.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_a19039d.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_d72cc1e.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_d732215.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_e2c46e3.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_e78d58b.pf_fragment +0 -0
- package/template/.build/pagefind/fragment/fr-ch_e92f972.pf_fragment +0 -0
- package/template/.build/pagefind/index/fr-ch_f94c95d.pf_index +0 -0
- package/template/.build/pagefind/pagefind-component-ui.css +1509 -0
- package/template/.build/pagefind/pagefind-component-ui.js +56 -0
- package/template/.build/pagefind/pagefind-entry.json +1 -0
- package/template/.build/pagefind/pagefind-highlight.js +1070 -0
- package/template/.build/pagefind/pagefind-modular-ui.css +214 -0
- package/template/.build/pagefind/pagefind-modular-ui.js +8 -0
- package/template/.build/pagefind/pagefind-ui.css +1 -0
- package/template/.build/pagefind/pagefind-ui.js +2 -0
- package/template/.build/pagefind/pagefind-worker.js +6 -0
- package/template/.build/pagefind/pagefind.fr-ch_fb78ab42961f4.pf_meta +0 -0
- package/template/.build/pagefind/pagefind.js +6 -0
- package/template/.build/pagefind/wasm.fr-ch.pagefind +0 -0
- package/template/.build/pagefind/wasm.unknown.pagefind +0 -0
- package/template/.build/reference/api-assistant/index.html +161 -0
- package/template/.build/reference/api-assistant.md +60 -0
- package/template/.build/reference/cli/index.html +153 -0
- package/template/.build/reference/cli.md +31 -0
- package/template/.build/reference/docs-json/index.html +192 -0
- package/template/.build/reference/docs-json.md +43 -0
- package/template/.build/reference/mcp/index.html +151 -0
- package/template/.build/reference/mcp.md +49 -0
- package/template/astro.config.ts +6 -0
- package/template/node_modules/.vite/deps/_metadata.json +74 -0
- package/template/node_modules/.vite/deps/astro-B3JHJyiv.js +434 -0
- package/template/node_modules/.vite/deps/astro-B3JHJyiv.js.map +1 -0
- package/template/node_modules/.vite/deps/astro_n_aria-query.js +6390 -0
- package/template/node_modules/.vite/deps/astro_n_aria-query.js.map +1 -0
- package/template/node_modules/.vite/deps/astro_n_axobject-query.js +2705 -0
- package/template/node_modules/.vite/deps/astro_n_axobject-query.js.map +1 -0
- package/template/node_modules/.vite/deps/astro_n_html-escaper.js +65 -0
- package/template/node_modules/.vite/deps/astro_n_html-escaper.js.map +1 -0
- package/template/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +455 -0
- package/template/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +1 -0
- package/template/node_modules/.vite/deps/audit-Do8QH17W.js +1543 -0
- package/template/node_modules/.vite/deps/audit-Do8QH17W.js.map +1 -0
- package/template/node_modules/.vite/deps/highlight-BLtvqtzO.js +48 -0
- package/template/node_modules/.vite/deps/highlight-BLtvqtzO.js.map +1 -0
- package/template/node_modules/.vite/deps/icons-C92i61-2.js +42 -0
- package/template/node_modules/.vite/deps/icons-C92i61-2.js.map +1 -0
- package/template/node_modules/.vite/deps/package.json +3 -0
- package/template/node_modules/.vite/deps/rolldown-runtime-C3I60J0A.js +4 -0
- package/template/node_modules/.vite/deps/settings-BYmTKrLi.js +189 -0
- package/template/node_modules/.vite/deps/settings-BYmTKrLi.js.map +1 -0
- package/template/node_modules/.vite/deps/toolbar-CEKhukuK.js +461 -0
- package/template/node_modules/.vite/deps/toolbar-CEKhukuK.js.map +1 -0
- package/template/node_modules/.vite/deps/ui-library-BO4--ANp.js +1015 -0
- package/template/node_modules/.vite/deps/ui-library-BO4--ANp.js.map +1 -0
- package/template/node_modules/.vite/deps/window-vo3A6TMn.js +32 -0
- package/template/node_modules/.vite/deps/window-vo3A6TMn.js.map +1 -0
- package/template/node_modules/.vite/deps/xray-Lf9x6g8P.js +112 -0
- package/template/node_modules/.vite/deps/xray-Lf9x6g8P.js.map +1 -0
- package/template/src/content.config.ts +21 -0
- package/README.md +0 -3
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-check
|
|
3
|
+
// CLI de HGDC Docs : construit la doc du dossier courant (docs.json + pages MDX) avec le
|
|
4
|
+
// modèle Starlight du paquet. En JavaScript : Node ne retire pas les types d'un fichier
|
|
5
|
+
// situé dans node_modules, et ce fichier y vit chez le client.
|
|
6
|
+
import { resolve } from "node:path"
|
|
7
|
+
import { fileURLToPath } from "node:url"
|
|
8
|
+
import { parseArgs } from "node:util"
|
|
9
|
+
|
|
10
|
+
const USAGE = `Utilisation : hgdc-docs <dev|build|preview> [dossier] [--port 4321] [--host 0.0.0.0]
|
|
11
|
+
|
|
12
|
+
dev site local, rechargé à chaque modification
|
|
13
|
+
build site statique dans <dossier>/dist (llms.txt et corpus de l'assistant compris)
|
|
14
|
+
preview sert le dernier build
|
|
15
|
+
|
|
16
|
+
Variables : HGDC_DOCS_SITE (adresse publique), HGDC_DOCS_API (API de l'assistant), HGDC_DOCS_OUT.`
|
|
17
|
+
|
|
18
|
+
const { positionals, values } = parseArgs({
|
|
19
|
+
allowPositionals: true,
|
|
20
|
+
options: { port: { type: "string" }, host: { type: "string" }, help: { type: "boolean", short: "h" } },
|
|
21
|
+
})
|
|
22
|
+
const [command = "build", dir = "."] = positionals
|
|
23
|
+
if (values.help || !["dev", "build", "preview"].includes(command)) {
|
|
24
|
+
process.stdout.write(`${USAGE}
|
|
25
|
+
`)
|
|
26
|
+
process.exit(values.help ? 0 : 1)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
process.env.HGDC_DOCS_DIR = resolve(dir)
|
|
30
|
+
if (!process.env.HGDC_DOCS_OUT) process.env.HGDC_DOCS_OUT = resolve(dir, "dist")
|
|
31
|
+
const root = fileURLToPath(new URL("../template/", import.meta.url))
|
|
32
|
+
const port = values.port ? Number(values.port) : undefined
|
|
33
|
+
const server = { ...(port ? { port } : {}), ...(values.host ? { host: values.host } : {}) }
|
|
34
|
+
const inline = { root, server }
|
|
35
|
+
|
|
36
|
+
// Astro écrit son cache dans le dossier courant : celui du modèle, pas le dépôt du client.
|
|
37
|
+
process.chdir(root)
|
|
38
|
+
const astro = await import("astro")
|
|
39
|
+
try {
|
|
40
|
+
if (command === "build") await astro.build(inline)
|
|
41
|
+
else if (command === "dev") await astro.dev(inline)
|
|
42
|
+
else await astro.preview(inline)
|
|
43
|
+
} catch (error) {
|
|
44
|
+
// Une erreur de docs.json se lit sans pile d'appels : elle dit déjà quoi corriger.
|
|
45
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
46
|
+
console.error(message.includes("docs.json") ? `\n${message}\n` : error)
|
|
47
|
+
process.exit(1)
|
|
48
|
+
}
|
package/docs.schema.json
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"$schema": {
|
|
6
|
+
"type": "string"
|
|
7
|
+
},
|
|
8
|
+
"name": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"minLength": 1,
|
|
11
|
+
"maxLength": 80
|
|
12
|
+
},
|
|
13
|
+
"description": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"maxLength": 300
|
|
16
|
+
},
|
|
17
|
+
"project": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"pattern": "^[a-z0-9]{8,64}$"
|
|
20
|
+
},
|
|
21
|
+
"language": {
|
|
22
|
+
"default": "fr",
|
|
23
|
+
"type": "string",
|
|
24
|
+
"enum": ["fr", "en", "de", "it"]
|
|
25
|
+
},
|
|
26
|
+
"colors": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"properties": {
|
|
29
|
+
"primary": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"pattern": "^#(?:[0-9a-f]{3}|[0-9a-f]{6})$"
|
|
32
|
+
},
|
|
33
|
+
"light": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"pattern": "^#(?:[0-9a-f]{3}|[0-9a-f]{6})$"
|
|
36
|
+
},
|
|
37
|
+
"dark": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"pattern": "^#(?:[0-9a-f]{3}|[0-9a-f]{6})$"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"required": ["primary"]
|
|
43
|
+
},
|
|
44
|
+
"logo": {
|
|
45
|
+
"anyOf": [
|
|
46
|
+
{
|
|
47
|
+
"type": "string"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"type": "object",
|
|
51
|
+
"properties": {
|
|
52
|
+
"light": {
|
|
53
|
+
"type": "string"
|
|
54
|
+
},
|
|
55
|
+
"dark": {
|
|
56
|
+
"type": "string"
|
|
57
|
+
},
|
|
58
|
+
"href": {
|
|
59
|
+
"type": "string"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"required": ["light"]
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
"favicon": {
|
|
67
|
+
"type": "string"
|
|
68
|
+
},
|
|
69
|
+
"navigation": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"properties": {
|
|
72
|
+
"versions": {
|
|
73
|
+
"type": "array",
|
|
74
|
+
"items": {
|
|
75
|
+
"type": "object",
|
|
76
|
+
"properties": {
|
|
77
|
+
"version": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"minLength": 1,
|
|
80
|
+
"maxLength": 32
|
|
81
|
+
},
|
|
82
|
+
"default": {
|
|
83
|
+
"type": "boolean"
|
|
84
|
+
},
|
|
85
|
+
"tabs": {
|
|
86
|
+
"type": "array",
|
|
87
|
+
"items": {
|
|
88
|
+
"type": "object",
|
|
89
|
+
"properties": {
|
|
90
|
+
"tab": {
|
|
91
|
+
"type": "string",
|
|
92
|
+
"minLength": 1
|
|
93
|
+
},
|
|
94
|
+
"groups": {
|
|
95
|
+
"type": "array",
|
|
96
|
+
"items": {
|
|
97
|
+
"$ref": "#/$defs/__schema0"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"pages": {
|
|
101
|
+
"type": "array",
|
|
102
|
+
"items": {
|
|
103
|
+
"anyOf": [
|
|
104
|
+
{
|
|
105
|
+
"type": "string",
|
|
106
|
+
"pattern": "^(?!\\/)(?!.*\\.\\.)[a-z0-9][a-z0-9/_-]*$"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"$ref": "#/$defs/__schema0"
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"required": ["tab"]
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"groups": {
|
|
119
|
+
"type": "array",
|
|
120
|
+
"items": {
|
|
121
|
+
"$ref": "#/$defs/__schema0"
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"pages": {
|
|
125
|
+
"type": "array",
|
|
126
|
+
"items": {
|
|
127
|
+
"anyOf": [
|
|
128
|
+
{
|
|
129
|
+
"type": "string",
|
|
130
|
+
"pattern": "^(?!\\/)(?!.*\\.\\.)[a-z0-9][a-z0-9/_-]*$"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"$ref": "#/$defs/__schema0"
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"required": ["version"]
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"tabs": {
|
|
143
|
+
"type": "array",
|
|
144
|
+
"items": {
|
|
145
|
+
"type": "object",
|
|
146
|
+
"properties": {
|
|
147
|
+
"tab": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"minLength": 1
|
|
150
|
+
},
|
|
151
|
+
"groups": {
|
|
152
|
+
"type": "array",
|
|
153
|
+
"items": {
|
|
154
|
+
"$ref": "#/$defs/__schema0"
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
"pages": {
|
|
158
|
+
"type": "array",
|
|
159
|
+
"items": {
|
|
160
|
+
"anyOf": [
|
|
161
|
+
{
|
|
162
|
+
"type": "string",
|
|
163
|
+
"pattern": "^(?!\\/)(?!.*\\.\\.)[a-z0-9][a-z0-9/_-]*$"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"$ref": "#/$defs/__schema0"
|
|
167
|
+
}
|
|
168
|
+
]
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
"required": ["tab"]
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
"groups": {
|
|
176
|
+
"type": "array",
|
|
177
|
+
"items": {
|
|
178
|
+
"$ref": "#/$defs/__schema0"
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"pages": {
|
|
182
|
+
"type": "array",
|
|
183
|
+
"items": {
|
|
184
|
+
"anyOf": [
|
|
185
|
+
{
|
|
186
|
+
"type": "string",
|
|
187
|
+
"pattern": "^(?!\\/)(?!.*\\.\\.)[a-z0-9][a-z0-9/_-]*$"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"$ref": "#/$defs/__schema0"
|
|
191
|
+
}
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
"navbar": {
|
|
198
|
+
"type": "object",
|
|
199
|
+
"properties": {
|
|
200
|
+
"links": {
|
|
201
|
+
"maxItems": 5,
|
|
202
|
+
"type": "array",
|
|
203
|
+
"items": {
|
|
204
|
+
"type": "object",
|
|
205
|
+
"properties": {
|
|
206
|
+
"label": {
|
|
207
|
+
"type": "string"
|
|
208
|
+
},
|
|
209
|
+
"href": {
|
|
210
|
+
"type": "string",
|
|
211
|
+
"format": "uri"
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
"required": ["label", "href"]
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
"primary": {
|
|
218
|
+
"type": "object",
|
|
219
|
+
"properties": {
|
|
220
|
+
"label": {
|
|
221
|
+
"type": "string"
|
|
222
|
+
},
|
|
223
|
+
"href": {
|
|
224
|
+
"type": "string",
|
|
225
|
+
"format": "uri"
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
"required": ["label", "href"]
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"footer": {
|
|
233
|
+
"type": "object",
|
|
234
|
+
"properties": {
|
|
235
|
+
"socials": {
|
|
236
|
+
"type": "object",
|
|
237
|
+
"propertyNames": {
|
|
238
|
+
"type": "string"
|
|
239
|
+
},
|
|
240
|
+
"additionalProperties": {
|
|
241
|
+
"type": "string",
|
|
242
|
+
"format": "uri"
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
"assistant": {
|
|
248
|
+
"type": "object",
|
|
249
|
+
"properties": {
|
|
250
|
+
"enabled": {
|
|
251
|
+
"default": true,
|
|
252
|
+
"type": "boolean"
|
|
253
|
+
},
|
|
254
|
+
"endpoint": {
|
|
255
|
+
"type": "string",
|
|
256
|
+
"format": "uri"
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
"required": ["name", "navigation"],
|
|
262
|
+
"$defs": {
|
|
263
|
+
"__schema0": {
|
|
264
|
+
"type": "object",
|
|
265
|
+
"properties": {
|
|
266
|
+
"group": {
|
|
267
|
+
"type": "string",
|
|
268
|
+
"minLength": 1
|
|
269
|
+
},
|
|
270
|
+
"pages": {
|
|
271
|
+
"minItems": 1,
|
|
272
|
+
"type": "array",
|
|
273
|
+
"items": {
|
|
274
|
+
"anyOf": [
|
|
275
|
+
{
|
|
276
|
+
"type": "string",
|
|
277
|
+
"pattern": "^(?!\\/)(?!.*\\.\\.)[a-z0-9][a-z0-9/_-]*$"
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"$ref": "#/$defs/__schema0"
|
|
281
|
+
}
|
|
282
|
+
]
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
"expanded": {
|
|
286
|
+
"type": "boolean"
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
"required": ["group", "pages"]
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
"$id": "https://docs.hgdc.ch/docs.schema.json",
|
|
293
|
+
"title": "docs.json de HGDC Docs"
|
|
294
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hgdc/docs",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Modèle de site de HGDC Docs : documentation MDX (docs.json) construite avec Astro Starlight, recherche, versions, llms.txt et assistant.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"hgdc-docs": "./bin/hgdc-docs.mjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"src",
|
|
13
|
+
"template",
|
|
14
|
+
"docs.schema.json"
|
|
15
|
+
],
|
|
16
|
+
"exports": {
|
|
17
|
+
"./core/*": "./src/core/*.ts",
|
|
18
|
+
"./integration": "./src/integration.ts",
|
|
19
|
+
"./components/*": "./src/components/*",
|
|
20
|
+
"./docs.schema.json": "./docs.schema.json",
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"test": "vitest run"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@astrojs/markdown-remark": "7.3.2",
|
|
29
|
+
"@astrojs/mdx": "8.0.3",
|
|
30
|
+
"@astrojs/starlight": "0.42.6",
|
|
31
|
+
"@fontsource-variable/geist": "5.3.0",
|
|
32
|
+
"@fontsource-variable/inter": "5.3.0",
|
|
33
|
+
"astro": "7.3.8",
|
|
34
|
+
"github-slugger": "2.0.0",
|
|
35
|
+
"hast-util-select": "6.0.4",
|
|
36
|
+
"hast-util-to-string": "3.0.1",
|
|
37
|
+
"rehype-parse": "9.0.1",
|
|
38
|
+
"rehype-remark": "10.0.1",
|
|
39
|
+
"remark-gfm": "4.0.1",
|
|
40
|
+
"remark-stringify": "11.0.0",
|
|
41
|
+
"unified": "11.0.5",
|
|
42
|
+
"vfile": "6.0.3",
|
|
43
|
+
"zod": "4.6.5"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "24.19.2",
|
|
47
|
+
"typescript": "7.0.2",
|
|
48
|
+
"vitest": "5.0.3",
|
|
49
|
+
"@types/hast": "3.0.4",
|
|
50
|
+
"@types/mdast": "4.0.4"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Root } from "mdast"
|
|
2
|
+
import type { VFile } from "vfile"
|
|
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
|
|
28
|
+
|
|
29
|
+
const SOURCE = "@hgdc/docs/components"
|
|
30
|
+
|
|
31
|
+
type EsmNode = { type: "mdxjsEsm"; value: string; data?: { estree?: { body?: Array<EstreeImport> } } }
|
|
32
|
+
type EstreeImport = { type: string; specifiers?: Array<{ local?: { name?: string } }> }
|
|
33
|
+
|
|
34
|
+
function declaredNames(tree: Root): Set<string> {
|
|
35
|
+
const names = new Set<string>()
|
|
36
|
+
for (const node of tree.children as unknown as Array<EsmNode>) {
|
|
37
|
+
if (node.type !== "mdxjsEsm") continue
|
|
38
|
+
for (const statement of node.data?.estree?.body ?? [])
|
|
39
|
+
for (const specifier of statement.specifiers ?? []) if (specifier.local?.name) names.add(specifier.local.name)
|
|
40
|
+
}
|
|
41
|
+
return names
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Import par défaut d'un fichier `.astro`, sous la forme ESTree qu'attend le compilateur MDX. */
|
|
45
|
+
function importNode(name: string): EsmNode {
|
|
46
|
+
const source = `${SOURCE}/${name}.astro`
|
|
47
|
+
const identifier = { type: "Identifier", name }
|
|
48
|
+
return {
|
|
49
|
+
type: "mdxjsEsm",
|
|
50
|
+
value: `import ${name} from ${JSON.stringify(source)}`,
|
|
51
|
+
data: {
|
|
52
|
+
estree: {
|
|
53
|
+
type: "Program",
|
|
54
|
+
sourceType: "module",
|
|
55
|
+
body: [
|
|
56
|
+
{
|
|
57
|
+
type: "ImportDeclaration",
|
|
58
|
+
specifiers: [{ type: "ImportDefaultSpecifier", local: identifier }],
|
|
59
|
+
source: { type: "Literal", value: source, raw: JSON.stringify(source) },
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
} as never,
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function remarkAutoImport() {
|
|
68
|
+
return (tree: Root, file: VFile) => {
|
|
69
|
+
if (!String(file.path ?? file.history.at(-1) ?? "").endsWith(".mdx")) return
|
|
70
|
+
const declared = declaredNames(tree)
|
|
71
|
+
const imports = MDX_COMPONENTS.filter((name) => !declared.has(name)).map(importNode)
|
|
72
|
+
tree.children.unshift(...(imports as never[]))
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { Element, Root } from "hast"
|
|
2
|
+
import { select, selectAll } from "hast-util-select"
|
|
3
|
+
import { toString } from "hast-util-to-string"
|
|
4
|
+
import rehypeParse from "rehype-parse"
|
|
5
|
+
import rehypeRemark from "rehype-remark"
|
|
6
|
+
import remarkGfm from "remark-gfm"
|
|
7
|
+
import remarkStringify from "remark-stringify"
|
|
8
|
+
import { unified } from "unified"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Page construite (HTML) → Markdown propre, pour `.md`, `llms-full.txt` et le corpus.
|
|
12
|
+
*
|
|
13
|
+
* On part du HTML final plutôt que du MDX source : les composants (encadrés, onglets,
|
|
14
|
+
* étapes) sont déjà rendus, et ce que lit l'agent est exactement ce que voit le visiteur.
|
|
15
|
+
*/
|
|
16
|
+
const REMOVED = [
|
|
17
|
+
"script",
|
|
18
|
+
"style",
|
|
19
|
+
"template",
|
|
20
|
+
"button",
|
|
21
|
+
".sl-anchor-link",
|
|
22
|
+
"[data-hgdc-skip]",
|
|
23
|
+
".expressive-code .copy",
|
|
24
|
+
"starlight-tabs [role=tablist]",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
export function htmlToMarkdown(html: string): string {
|
|
28
|
+
const tree = unified().use(rehypeParse).parse(html) as Root
|
|
29
|
+
const content = select(".sl-markdown-content", tree) ?? select("main", tree)
|
|
30
|
+
if (!content) return ""
|
|
31
|
+
replaceCodeBlocks(content)
|
|
32
|
+
replaceAsides(content)
|
|
33
|
+
for (const selector of REMOVED) for (const node of selectAll(selector, content)) remove(content, node)
|
|
34
|
+
|
|
35
|
+
const root: Root = { type: "root", children: content.children }
|
|
36
|
+
const mdast = unified().use(rehypeRemark).runSync(root)
|
|
37
|
+
const markdown = unified()
|
|
38
|
+
.use(remarkGfm)
|
|
39
|
+
.use(remarkStringify, { bullet: "-", fences: true, rule: "-" })
|
|
40
|
+
.stringify(mdast)
|
|
41
|
+
return String(markdown)
|
|
42
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
43
|
+
.trim()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Expressive Code découpe le code en une ligne par élément ; le texte exact, sauts de ligne
|
|
48
|
+
* compris, est dans `data-code` du bouton Copier (saut de ligne codé U+007F).
|
|
49
|
+
*/
|
|
50
|
+
function replaceCodeBlocks(content: Element): void {
|
|
51
|
+
for (const figure of selectAll(".expressive-code", content)) {
|
|
52
|
+
const code = select("[data-code]", figure)?.properties["dataCode"]
|
|
53
|
+
const language = select("pre[data-language]", figure)?.properties["dataLanguage"]
|
|
54
|
+
if (typeof code !== "string") continue
|
|
55
|
+
const pre: Element = {
|
|
56
|
+
type: "element",
|
|
57
|
+
tagName: "pre",
|
|
58
|
+
properties: {},
|
|
59
|
+
children: [
|
|
60
|
+
{
|
|
61
|
+
type: "element",
|
|
62
|
+
tagName: "code",
|
|
63
|
+
properties:
|
|
64
|
+
typeof language === "string" && language !== "plaintext" ? { className: [`language-${language}`] } : {},
|
|
65
|
+
children: [{ type: "text", value: code.replaceAll("\u007f", "\n") }],
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
}
|
|
69
|
+
Object.assign(figure, pre)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Encadré → citation dont la première ligne porte le titre en gras : `> **Note**`. */
|
|
74
|
+
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
|
+
const label = title ? toString(title as Parameters<typeof toString>[0]).trim() : ""
|
|
79
|
+
const quote: Element = {
|
|
80
|
+
type: "element",
|
|
81
|
+
tagName: "blockquote",
|
|
82
|
+
properties: {},
|
|
83
|
+
children: [
|
|
84
|
+
...(label
|
|
85
|
+
? [
|
|
86
|
+
{
|
|
87
|
+
type: "element" as const,
|
|
88
|
+
tagName: "p",
|
|
89
|
+
properties: {},
|
|
90
|
+
children: [
|
|
91
|
+
{
|
|
92
|
+
type: "element" as const,
|
|
93
|
+
tagName: "strong",
|
|
94
|
+
properties: {},
|
|
95
|
+
children: [{ type: "text" as const, value: label }],
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
]
|
|
100
|
+
: []),
|
|
101
|
+
...(body?.children ?? []),
|
|
102
|
+
],
|
|
103
|
+
}
|
|
104
|
+
Object.assign(aside, quote)
|
|
105
|
+
}
|
|
106
|
+
for (const title of selectAll(".hgdc-step__title", content)) {
|
|
107
|
+
title.children = [{ type: "element", tagName: "strong", properties: {}, children: [...title.children] }]
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function remove(parent: Element | Root, target: Element): void {
|
|
112
|
+
parent.children = parent.children.filter((child) => child !== target)
|
|
113
|
+
for (const child of parent.children) if (child.type === "element") remove(child, target)
|
|
114
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { existsSync } from "node:fs"
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises"
|
|
3
|
+
import { dirname, join } from "node:path"
|
|
4
|
+
|
|
5
|
+
import { select } from "hast-util-select"
|
|
6
|
+
import { toString } from "hast-util-to-string"
|
|
7
|
+
import rehypeParse from "rehype-parse"
|
|
8
|
+
import { unified } from "unified"
|
|
9
|
+
|
|
10
|
+
import type { DocsConfig } from "../core/config.ts"
|
|
11
|
+
import { CORPUS_FORMAT, CORPUS_PATH, MAX_PAGE_CHARS, type Corpus } from "../core/corpus.ts"
|
|
12
|
+
import { llmsFullTxt, llmsTxt, markdownPath, type LlmsPage } from "../core/llms.ts"
|
|
13
|
+
import { allPages, locatePage, pageToPath, type NavTree } from "../core/navigation.ts"
|
|
14
|
+
import { htmlToMarkdown } from "./markdown.ts"
|
|
15
|
+
|
|
16
|
+
type Input = { outDir: string; pathnames: Array<string>; config: DocsConfig; tree: NavTree; site: string | null }
|
|
17
|
+
|
|
18
|
+
/** `guides/publier/` (pathname d'Astro) → `/guides/publier/`. */
|
|
19
|
+
const normalize = (pathname: string) => `/${pathname}`.replace(/\/+/g, "/").replace(/([^/])$/, "$1/")
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Après le build : une version Markdown de chaque page, `llms.txt`, `llms-full.txt`
|
|
23
|
+
* (aussi sous `/.well-known/`) et le corpus de l'assistant. Seules les pages de la
|
|
24
|
+
* navigation y entrent : une page hors navigation n'est pas annoncée aux agents.
|
|
25
|
+
*/
|
|
26
|
+
export async function writeMachineReadable(input: Input): Promise<{ pages: number }> {
|
|
27
|
+
const byPath = new Map(allPages(input.tree).map((page) => [pageToPath(page), page]))
|
|
28
|
+
const pages = new Map<string, LlmsPage>()
|
|
29
|
+
const corpusPages: Corpus["pages"] = []
|
|
30
|
+
|
|
31
|
+
for (const pathname of input.pathnames) {
|
|
32
|
+
const path = normalize(pathname)
|
|
33
|
+
const page = byPath.get(path)
|
|
34
|
+
const htmlFile = join(input.outDir, path, "index.html")
|
|
35
|
+
if (!page || !existsSync(htmlFile)) continue
|
|
36
|
+
const html = await readFile(htmlFile, "utf8")
|
|
37
|
+
const tree = unified().use(rehypeParse).parse(html)
|
|
38
|
+
const heading = select("h1#_top", tree) ?? select("title", tree)
|
|
39
|
+
const title = heading ? toString(heading as Parameters<typeof toString>[0]).trim() : path
|
|
40
|
+
const description = select('meta[name="description"]', tree)?.properties["content"]
|
|
41
|
+
const markdown = htmlToMarkdown(html).slice(0, MAX_PAGE_CHARS)
|
|
42
|
+
// Starlight reprend la description du site quand la page n'en a pas : ce n'est pas la sienne.
|
|
43
|
+
const own = typeof description === "string" && description !== input.config.description ? description : null
|
|
44
|
+
const entry = { page, title, description: own, markdown }
|
|
45
|
+
pages.set(page, entry)
|
|
46
|
+
await write(input.outDir, markdownPath(path), `# ${title}\n\n${markdown}\n`)
|
|
47
|
+
corpusPages.push({
|
|
48
|
+
path,
|
|
49
|
+
title,
|
|
50
|
+
description: entry.description,
|
|
51
|
+
version: locatePage(input.tree, page)?.version.id ?? null,
|
|
52
|
+
markdown,
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const llms = {
|
|
57
|
+
name: input.config.name,
|
|
58
|
+
description: input.config.description ?? null,
|
|
59
|
+
site: input.site,
|
|
60
|
+
tree: input.tree,
|
|
61
|
+
pages,
|
|
62
|
+
}
|
|
63
|
+
const index = llmsTxt(llms)
|
|
64
|
+
const full = llmsFullTxt(llms, [...new Set(allPages(input.tree))])
|
|
65
|
+
await write(input.outDir, "/llms.txt", index)
|
|
66
|
+
await write(input.outDir, "/.well-known/llms.txt", index)
|
|
67
|
+
await write(input.outDir, "/llms-full.txt", full)
|
|
68
|
+
|
|
69
|
+
const logo = input.config.logo
|
|
70
|
+
const corpus: Corpus = {
|
|
71
|
+
format: CORPUS_FORMAT,
|
|
72
|
+
project: input.config.project ?? null,
|
|
73
|
+
name: input.config.name,
|
|
74
|
+
language: input.config.language,
|
|
75
|
+
builtAt: new Date().toISOString(),
|
|
76
|
+
theme: {
|
|
77
|
+
primary: input.config.colors?.primary ?? null,
|
|
78
|
+
logo: typeof logo === "string" ? logo : (logo?.light ?? null),
|
|
79
|
+
},
|
|
80
|
+
versions: input.tree.versions.map(({ id, label, isDefault }) => ({ id, label, isDefault })),
|
|
81
|
+
pages: corpusPages,
|
|
82
|
+
}
|
|
83
|
+
await write(input.outDir, CORPUS_PATH, JSON.stringify(corpus))
|
|
84
|
+
return { pages: pages.size }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function write(outDir: string, path: string, content: string): Promise<void> {
|
|
88
|
+
const target = join(outDir, path)
|
|
89
|
+
await mkdir(dirname(target), { recursive: true })
|
|
90
|
+
await writeFile(target, content)
|
|
91
|
+
}
|