@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.
Files changed (233) hide show
  1. package/docs.schema.json +21 -0
  2. package/package.json +3 -1
  3. package/src/build/auto-import.ts +5 -24
  4. package/src/build/content.ts +82 -0
  5. package/src/build/markdown.ts +10 -5
  6. package/src/components/Accordion.astro +3 -1
  7. package/src/components/Callout.astro +31 -0
  8. package/src/components/Card.astro +3 -1
  9. package/src/components/Check.astro +2 -3
  10. package/src/components/CodeGroup.astro +9 -1
  11. package/src/components/Danger.astro +2 -3
  12. package/src/components/Info.astro +2 -3
  13. package/src/components/Note.astro +2 -3
  14. package/src/components/Tip.astro +2 -3
  15. package/src/components/Warning.astro +2 -3
  16. package/src/core/components.ts +166 -0
  17. package/src/core/config.ts +42 -0
  18. package/src/core/feedback-api.ts +27 -0
  19. package/src/core/theme.ts +6 -3
  20. package/src/core/validate.ts +276 -0
  21. package/src/integration.ts +102 -30
  22. package/src/overrides/Assistant.astro +17 -39
  23. package/src/overrides/Footer.astro +107 -0
  24. package/src/overrides/Head.astro +14 -14
  25. package/src/overrides/Header.astro +92 -0
  26. package/src/overrides/Icon.astro +65 -0
  27. package/src/overrides/PageFrame.astro +55 -8
  28. package/src/overrides/PageSidebar.astro +7 -0
  29. package/src/overrides/PageTitle.astro +126 -95
  30. package/src/overrides/Search.astro +54 -0
  31. package/src/overrides/Sidebar.astro +105 -60
  32. package/src/overrides/SidebarList.astro +52 -0
  33. package/src/overrides/SiteFooter.astro +51 -0
  34. package/src/overrides/ThemeProvider.astro +23 -0
  35. package/src/overrides/ThemeToggle.astro +90 -0
  36. package/src/overrides/TwoColumnContent.astro +45 -0
  37. package/src/overrides/sections.ts +29 -0
  38. package/src/styles/theme.css +2137 -511
  39. package/src/widget/client.ts +51 -19
  40. package/src/widget/code.ts +218 -0
  41. package/src/widget/excerpt.ts +5 -0
  42. package/src/widget/search.ts +222 -0
  43. package/template/.astro/collections/docs.schema.json +3 -0
  44. package/template/.astro/content-modules.mjs +35 -15
  45. package/template/.astro/data-store.json +1 -0
  46. package/template/.astro/settings.json +5 -0
  47. package/template/.build/.well-known/llms.txt +51 -34
  48. package/template/.build/404.html +16 -42
  49. package/template/.build/_astro/Assistant.astro_astro_type_script_index_0_lang.C1pz7yK1.js +4 -0
  50. package/template/.build/_astro/CodeGroup.astro_astro_type_script_index_0_lang.-eM8maAX.js +1 -0
  51. package/template/.build/_astro/Footer.astro_astro_type_script_index_0_lang.DzCnn3OT.js +1 -0
  52. package/template/.build/_astro/Search.astro_astro_type_script_index_0_lang.D7EcezBU.js +1 -0
  53. package/template/.build/_astro/code.smqv0zhe.js +9 -0
  54. package/template/.build/_astro/common.Dx3aBIS0.css +3 -0
  55. package/template/.build/_astro/{ec.8nqtp.css → ec.t9qpe.css} +1 -1
  56. package/template/.build/_astro/logo.BPu921Tp.svg +1 -0
  57. package/template/.build/_hgdc/corpus.json +1 -1
  58. package/template/.build/concepts/confidentialite/index.html +50 -0
  59. package/template/.build/concepts/confidentialite.md +38 -0
  60. package/template/.build/concepts/deploiements/index.html +106 -0
  61. package/template/.build/concepts/deploiements.md +70 -0
  62. package/template/.build/concepts/organisations-et-roles/index.html +83 -0
  63. package/template/.build/concepts/organisations-et-roles.md +39 -0
  64. package/template/.build/concepts/preversion/index.html +49 -0
  65. package/template/.build/concepts/preversion.md +52 -0
  66. package/template/.build/concepts/secrets-et-coffre/index.html +70 -0
  67. package/template/.build/concepts/secrets-et-coffre.md +54 -0
  68. package/template/.build/demarrer/depuis-github/index.html +34 -0
  69. package/template/.build/demarrer/depuis-github.md +68 -0
  70. package/template/.build/demarrer/premier-site/index.html +28 -0
  71. package/template/.build/demarrer/premier-site.md +94 -0
  72. package/template/.build/guides/brancher-un-domaine/index.html +91 -0
  73. package/template/.build/guides/brancher-un-domaine.md +81 -0
  74. package/template/.build/guides/cle-d-api/index.html +62 -0
  75. package/template/.build/guides/cle-d-api.md +78 -0
  76. package/template/.build/guides/depannage/index.html +64 -0
  77. package/template/.build/guides/depannage.md +69 -0
  78. package/template/.build/guides/deployer-depuis-github/index.html +45 -0
  79. package/template/.build/guides/deployer-depuis-github.md +70 -0
  80. package/template/.build/guides/deployer-un-framework/index.html +81 -0
  81. package/template/.build/guides/deployer-un-framework.md +74 -0
  82. package/template/.build/guides/github-actions-sans-application/index.html +53 -0
  83. package/template/.build/guides/github-actions-sans-application.md +95 -0
  84. package/template/.build/guides/inviter-une-personne/index.html +28 -0
  85. package/template/.build/guides/inviter-une-personne.md +38 -0
  86. package/template/.build/guides/lire-les-logs/index.html +37 -0
  87. package/template/.build/guides/lire-les-logs.md +48 -0
  88. package/template/.build/guides/migrer-depuis-vercel/index.html +25 -0
  89. package/template/.build/guides/migrer-depuis-vercel.md +51 -0
  90. package/template/.build/guides/monorepo/index.html +40 -0
  91. package/template/.build/guides/monorepo.md +42 -0
  92. package/template/.build/guides/revenir-en-arriere/index.html +39 -0
  93. package/template/.build/guides/revenir-en-arriere.md +50 -0
  94. package/template/.build/guides/site-statique/index.html +41 -0
  95. package/template/.build/guides/site-statique.md +59 -0
  96. package/template/.build/guides/synchroniser-doppler/index.html +46 -0
  97. package/template/.build/guides/synchroniser-doppler.md +63 -0
  98. package/template/.build/guides/variables-d-environnement/index.html +73 -0
  99. package/template/.build/guides/variables-d-environnement.md +92 -0
  100. package/template/.build/images/famille/account.svg +1 -0
  101. package/template/.build/images/famille/analytics.svg +1 -0
  102. package/template/.build/images/famille/docs.svg +1 -0
  103. package/template/.build/images/famille/host.svg +1 -0
  104. package/template/.build/images/famille/mail.svg +1 -0
  105. package/template/.build/images/famille/portal.svg +1 -0
  106. package/template/.build/images/famille/status.svg +1 -0
  107. package/template/.build/images/logo.svg +1 -0
  108. package/template/.build/index.html +30 -86
  109. package/template/.build/index.md +59 -21
  110. package/template/.build/llms-full.txt +2330 -518
  111. package/template/.build/llms.txt +51 -34
  112. package/template/.build/pagefind/fragment/fr-ch_16987e2.pf_fragment +0 -0
  113. package/template/.build/pagefind/fragment/fr-ch_2b4c97b.pf_fragment +0 -0
  114. package/template/.build/pagefind/fragment/fr-ch_3294a5c.pf_fragment +0 -0
  115. package/template/.build/pagefind/fragment/fr-ch_34858c9.pf_fragment +0 -0
  116. package/template/.build/pagefind/fragment/fr-ch_39ddba1.pf_fragment +0 -0
  117. package/template/.build/pagefind/fragment/fr-ch_4ab1899.pf_fragment +0 -0
  118. package/template/.build/pagefind/fragment/fr-ch_4d3a52a.pf_fragment +0 -0
  119. package/template/.build/pagefind/fragment/fr-ch_506c187.pf_fragment +0 -0
  120. package/template/.build/pagefind/fragment/fr-ch_5aa255a.pf_fragment +0 -0
  121. package/template/.build/pagefind/fragment/fr-ch_6841c7d.pf_fragment +0 -0
  122. package/template/.build/pagefind/fragment/fr-ch_6dc7a2d.pf_fragment +0 -0
  123. package/template/.build/pagefind/fragment/fr-ch_847edff.pf_fragment +0 -0
  124. package/template/.build/pagefind/fragment/fr-ch_8745af7.pf_fragment +0 -0
  125. package/template/.build/pagefind/fragment/fr-ch_8aac5e6.pf_fragment +0 -0
  126. package/template/.build/pagefind/fragment/fr-ch_916b233.pf_fragment +0 -0
  127. package/template/.build/pagefind/fragment/fr-ch_9fd014a.pf_fragment +0 -0
  128. package/template/.build/pagefind/fragment/fr-ch_a0808f8.pf_fragment +0 -0
  129. package/template/.build/pagefind/fragment/fr-ch_a4e1f69.pf_fragment +0 -0
  130. package/template/.build/pagefind/fragment/fr-ch_a80a53d.pf_fragment +0 -0
  131. package/template/.build/pagefind/fragment/fr-ch_a9e725b.pf_fragment +0 -0
  132. package/template/.build/pagefind/fragment/fr-ch_ac3f64c.pf_fragment +0 -0
  133. package/template/.build/pagefind/fragment/fr-ch_af292f1.pf_fragment +0 -0
  134. package/template/.build/pagefind/fragment/fr-ch_af3e716.pf_fragment +0 -0
  135. package/template/.build/pagefind/fragment/fr-ch_b0689a4.pf_fragment +0 -0
  136. package/template/.build/pagefind/fragment/fr-ch_baed996.pf_fragment +0 -0
  137. package/template/.build/pagefind/fragment/fr-ch_c89e27a.pf_fragment +0 -0
  138. package/template/.build/pagefind/fragment/fr-ch_cd6ca13.pf_fragment +0 -0
  139. package/template/.build/pagefind/fragment/fr-ch_d09af09.pf_fragment +0 -0
  140. package/template/.build/pagefind/fragment/fr-ch_d4bcea8.pf_fragment +0 -0
  141. package/template/.build/pagefind/fragment/fr-ch_dc2a134.pf_fragment +0 -0
  142. package/template/.build/pagefind/fragment/fr-ch_ded7ddc.pf_fragment +0 -0
  143. package/template/.build/pagefind/fragment/fr-ch_e2528cb.pf_fragment +0 -0
  144. package/template/.build/pagefind/fragment/fr-ch_e3cbb4e.pf_fragment +0 -0
  145. package/template/.build/pagefind/fragment/fr-ch_e7902d9.pf_fragment +0 -0
  146. package/template/.build/pagefind/fragment/fr-ch_f48ca47.pf_fragment +0 -0
  147. package/template/.build/pagefind/index/fr-ch_8a5f905.pf_index +0 -0
  148. package/template/.build/pagefind/index/fr-ch_fbd9c96.pf_index +0 -0
  149. package/template/.build/pagefind/pagefind-entry.json +1 -1
  150. package/template/.build/pagefind/pagefind.fr-ch_211aacbfa7f0e.pf_meta +0 -0
  151. package/template/.build/reference/api/deploiements/index.html +326 -0
  152. package/template/.build/reference/api/deploiements.md +170 -0
  153. package/template/.build/reference/api/erreurs/index.html +102 -0
  154. package/template/.build/reference/api/erreurs.md +50 -0
  155. package/template/.build/reference/api/fichiers/index.html +82 -0
  156. package/template/.build/reference/api/fichiers.md +62 -0
  157. package/template/.build/reference/api/introduction/index.html +126 -0
  158. package/template/.build/reference/api/introduction.md +84 -0
  159. package/template/.build/reference/api/projets/index.html +184 -0
  160. package/template/.build/reference/api/projets.md +102 -0
  161. package/template/.build/reference/api/utilisateur/index.html +96 -0
  162. package/template/.build/reference/api/utilisateur.md +89 -0
  163. package/template/.build/reference/api/variables/index.html +75 -0
  164. package/template/.build/reference/api/variables.md +58 -0
  165. package/template/.build/reference/cli/index.html +165 -82
  166. package/template/.build/reference/cli.md +159 -23
  167. package/template/.build/reference/compatibilite/index.html +196 -0
  168. package/template/.build/reference/compatibilite.md +64 -0
  169. package/template/.build/reference/domaines/index.html +171 -0
  170. package/template/.build/reference/domaines.md +76 -0
  171. package/template/.build/reference/limites/index.html +159 -0
  172. package/template/.build/reference/limites.md +56 -0
  173. package/template/.build/reference/variables/index.html +164 -0
  174. package/template/.build/reference/variables.md +63 -0
  175. package/template/.build/reference/vercel-json/index.html +65 -0
  176. package/template/.build/reference/vercel-json.md +51 -0
  177. package/template/node_modules/.vite/deps/_metadata.json +8 -8
  178. package/template/src/content.config.ts +8 -2
  179. package/template/.build/_astro/Assistant.astro_astro_type_script_index_0_lang.DWgmlr85.js +0 -4
  180. package/template/.build/_astro/MobileTableOfContents.astro_astro_type_script_index_0_lang.C3fM4Kra.js +0 -1
  181. package/template/.build/_astro/Search.astro_astro_type_script_index_0_lang.Cn3-p701.js +0 -1
  182. package/template/.build/_astro/TableOfContents.astro_astro_type_script_index_0_lang.BpJaGz7G.js +0 -1
  183. package/template/.build/_astro/common.C-MpX45O.css +0 -3
  184. package/template/.build/_astro/logo-clair.BqNh6JNi.svg +0 -1
  185. package/template/.build/_astro/logo-sombre.BkgsFXxh.svg +0 -1
  186. package/template/.build/_astro/starlight-toc.D4UDIxQL.js +0 -1
  187. package/template/.build/_astro/ui-core.CrG20ya_.js +0 -2
  188. package/template/.build/demarrer/premiere-doc/index.html +0 -84
  189. package/template/.build/demarrer/premiere-doc.md +0 -65
  190. package/template/.build/explications/donnees/index.html +0 -114
  191. package/template/.build/explications/donnees.md +0 -28
  192. package/template/.build/explications/fonctionnement/index.html +0 -93
  193. package/template/.build/explications/fonctionnement.md +0 -32
  194. package/template/.build/guides/agents/index.html +0 -118
  195. package/template/.build/guides/agents.md +0 -54
  196. package/template/.build/guides/assistant/index.html +0 -119
  197. package/template/.build/guides/assistant.md +0 -46
  198. package/template/.build/guides/composants/index.html +0 -97
  199. package/template/.build/guides/composants.md +0 -101
  200. package/template/.build/guides/ecrire/index.html +0 -116
  201. package/template/.build/guides/ecrire.md +0 -63
  202. package/template/.build/guides/navigation/index.html +0 -90
  203. package/template/.build/guides/navigation.md +0 -63
  204. package/template/.build/guides/publier/index.html +0 -95
  205. package/template/.build/guides/publier.md +0 -65
  206. package/template/.build/guides/theme/index.html +0 -87
  207. package/template/.build/guides/theme.md +0 -33
  208. package/template/.build/images/favicon.svg +0 -1
  209. package/template/.build/images/logo-clair.svg +0 -1
  210. package/template/.build/images/logo-sombre.svg +0 -1
  211. package/template/.build/pagefind/fragment/fr-ch_2a431a9.pf_fragment +0 -0
  212. package/template/.build/pagefind/fragment/fr-ch_456586a.pf_fragment +0 -0
  213. package/template/.build/pagefind/fragment/fr-ch_4f8575c.pf_fragment +0 -0
  214. package/template/.build/pagefind/fragment/fr-ch_68e734b.pf_fragment +0 -0
  215. package/template/.build/pagefind/fragment/fr-ch_72b91f4.pf_fragment +0 -0
  216. package/template/.build/pagefind/fragment/fr-ch_8f256dd.pf_fragment +0 -0
  217. package/template/.build/pagefind/fragment/fr-ch_95a15cc.pf_fragment +0 -0
  218. package/template/.build/pagefind/fragment/fr-ch_aa80c55.pf_fragment +0 -0
  219. package/template/.build/pagefind/fragment/fr-ch_ab79738.pf_fragment +0 -0
  220. package/template/.build/pagefind/fragment/fr-ch_cfa4336.pf_fragment +0 -0
  221. package/template/.build/pagefind/fragment/fr-ch_dab8f5e.pf_fragment +0 -0
  222. package/template/.build/pagefind/fragment/fr-ch_de60b43.pf_fragment +0 -0
  223. package/template/.build/pagefind/fragment/fr-ch_e02aa49.pf_fragment +0 -0
  224. package/template/.build/pagefind/fragment/fr-ch_e254a54.pf_fragment +0 -0
  225. package/template/.build/pagefind/fragment/fr-ch_e2c46e3.pf_fragment +0 -0
  226. package/template/.build/pagefind/index/fr-ch_a71411b.pf_index +0 -0
  227. package/template/.build/pagefind/pagefind.fr-ch_2f3ea8fccf961.pf_meta +0 -0
  228. package/template/.build/reference/api-assistant/index.html +0 -161
  229. package/template/.build/reference/api-assistant.md +0 -70
  230. package/template/.build/reference/docs-json/index.html +0 -192
  231. package/template/.build/reference/docs-json.md +0 -43
  232. package/template/.build/reference/mcp/index.html +0 -151
  233. package/template/.build/reference/mcp.md +0 -49
@@ -0,0 +1,54 @@
1
+ ---
2
+ import data from "virtual:hgdc-docs/config"
3
+
4
+ import Icon from "./Icon.astro"
5
+ import { assistantEnabled } from "./sections.ts"
6
+
7
+ /**
8
+ * Recherche en palette (Ctrl K ou « / ») sur l'index Pagefind que Starlight construit au
9
+ * build. Le script de Pagefind n'est chargé qu'à la première ouverture. Logique dans
10
+ * `../widget/search.ts`.
11
+ */
12
+ const assistant = assistantEnabled(data.config)
13
+ ---
14
+
15
+ <hd-search data-base={data.base} data-assistant={assistant ? "" : undefined}>
16
+ <button type="button" class="hd-search-trigger" data-open aria-haspopup="dialog" aria-label="Rechercher (Ctrl K)">
17
+ <Icon name="search" size={16} />
18
+ <span class="hd-search-trigger__label">Rechercher</span>
19
+ <kbd class="hd-kbd" data-shortcut>Ctrl K</kbd>
20
+ </button>
21
+
22
+ <dialog class="hd-palette" aria-label="Rechercher dans la documentation">
23
+ <div class="hd-palette__box">
24
+ <div class="hd-palette__field">
25
+ <Icon name="search" />
26
+ <input
27
+ type="search"
28
+ data-input
29
+ placeholder="Rechercher dans la documentation"
30
+ autocomplete="off"
31
+ spellcheck="false"
32
+ role="combobox"
33
+ aria-expanded="false"
34
+ aria-controls="hd-palette-results"
35
+ aria-autocomplete="list"
36
+ />
37
+ <button type="button" class="hd-kbd hd-kbd--button" data-close>Échap</button>
38
+ </div>
39
+ <div class="hd-palette__results" id="hd-palette-results" role="listbox" aria-label="Résultats" data-results></div>
40
+ <p class="hd-palette__status" data-status role="status">Tape un mot pour chercher dans les pages.</p>
41
+ <footer class="hd-palette__hints" aria-hidden="true">
42
+ <span><kbd class="hd-kbd">↑</kbd><kbd class="hd-kbd">↓</kbd> Choisir</span>
43
+ <span><kbd class="hd-kbd">↵</kbd> Ouvrir</span>
44
+ <span><kbd class="hd-kbd">Échap</kbd> Fermer</span>
45
+ </footer>
46
+ </div>
47
+ </dialog>
48
+ </hd-search>
49
+
50
+ <script>
51
+ import { defineSearch } from "../widget/search.ts"
52
+
53
+ defineSearch()
54
+ </script>
@@ -1,60 +1,105 @@
1
- ---
2
- import Default from "@astrojs/starlight/components/Sidebar.astro"
3
- import data from "virtual:hgdc-docs/config"
4
-
5
- import { pagesOf, pageToPath, withBase } from "../core/navigation.ts"
6
-
7
- // Onglets et versions de docs.json, en tête de la sidebar : visibles sur ordinateur et dans
8
- // le menu mobile, sans toucher à la hauteur de l'en-tête de Starlight.
9
- const sections = data.tree.versions.flatMap((version) => version.tabs.map((tab) => ({ version, tab })))
10
- const index = Astro.locals.hgdcSection ?? 0
11
- const current = sections[index] ?? sections[0]!
12
- const firstPath = (items: Parameters<typeof pagesOf>[0]) => {
13
- const first = pagesOf(items)[0]
14
- return withBase(data.base, first ? pageToPath(first) : "/")
15
- }
16
- const tabs = current.version.tabs.filter((tab) => tab.label)
17
- const versions = data.tree.versions.filter((version) => version.label)
18
- const tabPosition = current.version.tabs.indexOf(current.tab)
19
- const versionHref = (version: (typeof versions)[number]) =>
20
- firstPath((version.tabs[tabPosition] ?? version.tabs[0]!).items)
21
- ---
22
-
23
- {
24
- (tabs.length > 1 || versions.length > 1) && (
25
- <div class="hgdc-sections">
26
- {versions.length > 1 && (
27
- <label class="hgdc-version">
28
- <span class="sr-only">Version de la documentation</span>
29
- <select data-hgdc-version>
30
- {versions.map((version) => (
31
- <option value={versionHref(version)} selected={version === current.version}>
32
- {version.label}
33
- {version.isDefault ? " (actuelle)" : ""}
34
- </option>
35
- ))}
36
- </select>
37
- </label>
38
- )}
39
- {tabs.length > 1 && (
40
- <nav aria-label="Sections de la documentation">
41
- <ul class="hgdc-tabs">
42
- {tabs.map((tab) => (
43
- <li>
44
- <a href={firstPath(tab.items)} aria-current={tab === current.tab ? "page" : undefined}>
45
- {tab.label}
46
- </a>
47
- </li>
48
- ))}
49
- </ul>
50
- </nav>
51
- )}
52
- </div>
53
- )
54
- }
55
- <Default><slot /></Default>
56
-
57
- <script>
58
- for (const select of document.querySelectorAll<HTMLSelectElement>("[data-hgdc-version]"))
59
- select.addEventListener("change", () => window.location.assign(select.value))
60
- </script>
1
+ ---
2
+ import data from "virtual:hgdc-docs/config"
3
+
4
+ import Icon from "./Icon.astro"
5
+ import { docsSections, sectionHref } from "./sections.ts"
6
+ import SidebarList from "./SidebarList.astro"
7
+ import ThemeToggle from "./ThemeToggle.astro"
8
+
9
+ /**
10
+ * Barre latérale : la version (s'il y en a plusieurs), puis les groupes de docs.json. Sur
11
+ * téléphone, le même panneau sert de menu : il reprend les onglets et les liens de
12
+ * l'en-tête, et le choix du thème.
13
+ */
14
+ const { tabs, versions, current } = docsSections(data.tree, Astro.locals.hgdcSection ?? 0)
15
+ const tabPosition = current.version.tabs.indexOf(current.tab)
16
+ const versionHref = (version: (typeof versions)[number]) =>
17
+ sectionHref(data.base, (version.tabs[tabPosition] ?? version.tabs[0]!).items)
18
+ const links = data.config.navbar?.links ?? []
19
+ const primary = data.config.navbar?.primary
20
+ ---
21
+
22
+ <div class="hd-mobile-only hd-sidebar-head">
23
+ <a class="hd-brand" href={`${data.base}/`}><span class="hd-brand__name">{data.config.name}</span></a>
24
+ <button type="button" class="hd-icon-button" popovertarget="starlight__sidebar" popovertargetaction="hide" aria-label="Fermer le menu">
25
+ <Icon name="x" />
26
+ </button>
27
+ </div>
28
+
29
+ {
30
+ versions.length > 1 && (
31
+ <label class="hd-version">
32
+ <span class="sr-only">Version de la documentation</span>
33
+ <select data-hgdc-version>
34
+ {versions.map((version) => (
35
+ <option value={versionHref(version)} selected={version === current.version}>
36
+ {version.label}
37
+ {version.isDefault ? " (actuelle)" : ""}
38
+ </option>
39
+ ))}
40
+ </select>
41
+ </label>
42
+ )
43
+ }
44
+ {
45
+ tabs.length > 1 && (
46
+ <nav class="hd-mobile-only hd-sidebar-tabs" aria-label="Sections de la documentation">
47
+ {tabs.map((tab) => (
48
+ <a href={sectionHref(data.base, tab.items)} aria-current={tab === current.tab ? "page" : undefined}>
49
+ {tab.label}
50
+ </a>
51
+ ))}
52
+ </nav>
53
+ )
54
+ }
55
+
56
+ <SidebarList entries={Astro.locals.starlightRoute.sidebar} />
57
+
58
+ <div class="hd-mobile-only hd-sidebar-footer">
59
+ {
60
+ (links.length > 0 || primary) && (
61
+ <nav class="hd-sidebar-links" aria-label="Liens">
62
+ {links.map((link) => (
63
+ <a href={link.href}>{link.label}</a>
64
+ ))}
65
+ {primary && (
66
+ <a class="hd-pill hd-pill--primary" href={primary.href}>
67
+ {primary.label}
68
+ </a>
69
+ )}
70
+ </nav>
71
+ )
72
+ }
73
+ <ThemeToggle variant="segmented" />
74
+ </div>
75
+
76
+ <script>
77
+ for (const select of document.querySelectorAll<HTMLSelectElement>("[data-hgdc-version]"))
78
+ select.addEventListener("change", () => window.location.assign(select.value))
79
+
80
+ // La barre garde sa position de défilement d'une page à l'autre, et l'élément courant
81
+ // reste visible à l'arrivée.
82
+ const pane = document.querySelector<HTMLElement>(".sidebar-pane")
83
+ if (pane) {
84
+ const KEY = "hd-sidebar-scroll"
85
+ try {
86
+ const saved = Number(sessionStorage.getItem(KEY))
87
+ if (saved) pane.scrollTop = saved
88
+ } catch {
89
+ // Stockage refusé : la barre repart du haut.
90
+ }
91
+ const current = pane.querySelector<HTMLElement>('[aria-current="page"]')
92
+ if (current) {
93
+ const box = pane.getBoundingClientRect()
94
+ const item = current.getBoundingClientRect()
95
+ if (item.top < box.top || item.bottom > box.bottom) current.scrollIntoView({ block: "center" })
96
+ }
97
+ addEventListener("pagehide", () => {
98
+ try {
99
+ sessionStorage.setItem(KEY, String(pane.scrollTop))
100
+ } catch {
101
+ // Rien à faire.
102
+ }
103
+ })
104
+ }
105
+ </script>
@@ -0,0 +1,52 @@
1
+ ---
2
+ import type { StarlightRouteData } from "@astrojs/starlight/route-data"
3
+
4
+ import Icon from "./Icon.astro"
5
+
6
+ /**
7
+ * Arbre de la barre latérale. Premier niveau : titres de groupe et pages. Plus bas : un
8
+ * groupe se replie derrière un chevron, ouvert d'office s'il contient la page affichée.
9
+ */
10
+ type Entry = StarlightRouteData["sidebar"][number]
11
+ interface Props {
12
+ entries: Array<Entry>
13
+ depth?: number
14
+ }
15
+ const { entries, depth = 0 } = Astro.props
16
+ const containsCurrent = (entry: Entry): boolean =>
17
+ entry.type === "link" ? entry.isCurrent : entry.entries.some(containsCurrent)
18
+ ---
19
+
20
+ <ul class:list={["hd-nav", `hd-nav--depth-${depth}`]}>
21
+ {
22
+ entries.map((entry) =>
23
+ entry.type === "link" ? (
24
+ <li>
25
+ <a href={entry.href} class="hd-nav__link" aria-current={entry.isCurrent ? "page" : undefined} {...entry.attrs}>
26
+ <span>{entry.label}</span>
27
+ {entry.badge && (
28
+ <span class="hd-badge" data-variant={entry.badge.variant}>
29
+ {entry.badge.text}
30
+ </span>
31
+ )}
32
+ </a>
33
+ </li>
34
+ ) : depth === 0 ? (
35
+ <li class="hd-nav__group">
36
+ <p class="hd-nav__heading">{entry.label}</p>
37
+ <Astro.self entries={entry.entries} depth={depth + 1} />
38
+ </li>
39
+ ) : (
40
+ <li>
41
+ <details class="hd-nav__fold" open={!entry.collapsed || containsCurrent(entry)}>
42
+ <summary class="hd-nav__link">
43
+ <span>{entry.label}</span>
44
+ <Icon name="chevron-right" size={14} class="hd-nav__chevron" />
45
+ </summary>
46
+ <Astro.self entries={entry.entries} depth={depth + 1} />
47
+ </details>
48
+ </li>
49
+ ),
50
+ )
51
+ }
52
+ </ul>
@@ -0,0 +1,51 @@
1
+ ---
2
+ import { Icon as StarlightIcon } from "@astrojs/starlight/components"
3
+ import data from "virtual:hgdc-docs/config"
4
+
5
+ import { socialNetwork } from "../core/config.ts"
6
+ import ThemeToggle from "./ThemeToggle.astro"
7
+
8
+ /**
9
+ * Pied de page du site, à droite de la barre latérale : le produit, ses réseaux
10
+ * (`footer.socials`) et le choix du thème.
11
+ */
12
+ const logo = typeof data.config.logo === "string" ? { light: data.config.logo } : data.config.logo
13
+ const src = (path: string) => `${data.base}${path.startsWith("/") ? path : `/${path}`}`
14
+ const socials = Object.entries(data.config.footer?.socials ?? {}).flatMap(([key, href]) => {
15
+ const network = socialNetwork(key)
16
+ return network ? [{ ...network, href }] : []
17
+ })
18
+ ---
19
+
20
+ <footer class="hd-site-footer" data-pagefind-ignore>
21
+ <div class="hd-site-footer__row">
22
+ <a class="hd-brand hd-brand--footer" href={`${data.base}/`}>
23
+ {
24
+ logo && (
25
+ <span class="hd-brand__mark">
26
+ <img class="hd-brand__light" src={src(logo.light)} alt="" width="20" height="20" loading="lazy" />
27
+ <img class="hd-brand__dark" src={src(logo.dark ?? logo.light)} alt="" width="20" height="20" loading="lazy" />
28
+ </span>
29
+ )
30
+ }
31
+ <span class="hd-brand__name">{data.config.name}</span>
32
+ </a>
33
+ {
34
+ socials.length > 0 && (
35
+ <ul class="hd-socials" aria-label="Réseaux">
36
+ {socials.map((social) => (
37
+ <li>
38
+ <a class="hd-icon-button" href={social.href} rel="me noopener" aria-label={social.label} title={social.label}>
39
+ <StarlightIcon name={social.icon as "github"} size="1.1rem" />
40
+ </a>
41
+ </li>
42
+ ))}
43
+ </ul>
44
+ )
45
+ }
46
+ </div>
47
+ <div class="hd-site-footer__row hd-site-footer__row--meta">
48
+ {data.config.description && <p>{data.config.description}</p>}
49
+ <ThemeToggle variant="segmented" />
50
+ </div>
51
+ </footer>
@@ -0,0 +1,23 @@
1
+ ---
2
+ /**
3
+ * Thème avant la première peinture, sans éclair : clair par défaut, même si le système est
4
+ * en sombre ; « Sombre » et « Système » se choisissent et restent mémorisés (`starlight-theme`
5
+ * vaut `dark` ou `auto`). `data-hd-theme` n'est posé que par ce script : sans JavaScript,
6
+ * la page reste claire (theme.css).
7
+ */
8
+ ---
9
+
10
+ <script is:inline>
11
+ ;(() => {
12
+ let stored = null
13
+ try {
14
+ stored = localStorage.getItem("starlight-theme")
15
+ } catch {}
16
+ const dark =
17
+ stored === "dark" || (stored === "auto" && matchMedia("(prefers-color-scheme: dark)").matches)
18
+ const theme = dark ? "dark" : "light"
19
+ document.documentElement.dataset.theme = theme
20
+ document.documentElement.dataset.hdTheme = theme
21
+ window.StarlightThemeProvider = { updatePickers() {} }
22
+ })()
23
+ </script>
@@ -0,0 +1,90 @@
1
+ ---
2
+ import Icon from "./Icon.astro"
3
+
4
+ /**
5
+ * Thème : un bouton clair / sombre dans l'en-tête, et le choix à trois (système, clair,
6
+ * sombre) au pied de page et dans le menu. Clair par défaut. Clé `starlight-theme`, lue avant
7
+ * la première peinture par `ThemeProvider.astro` : aucun éclair au chargement.
8
+ */
9
+ interface Props {
10
+ variant: "button" | "segmented"
11
+ }
12
+ const { variant } = Astro.props
13
+ const choices = [
14
+ { value: "auto", label: "Système", icon: "monitor" },
15
+ { value: "light", label: "Clair", icon: "sun" },
16
+ { value: "dark", label: "Sombre", icon: "moon" },
17
+ ] as const
18
+ ---
19
+
20
+ {
21
+ variant === "button" ? (
22
+ <button type="button" class="hd-icon-button hd-theme-button" data-hd-theme-toggle aria-label="Passer au thème sombre">
23
+ <Icon name="moon" class="hd-theme-button__moon" />
24
+ <Icon name="sun" class="hd-theme-button__sun" />
25
+ </button>
26
+ ) : (
27
+ <div class="hd-theme-choice" role="radiogroup" aria-label="Thème">
28
+ {choices.map((choice) => (
29
+ <button type="button" role="radio" aria-checked="false" data-hd-theme={choice.value} aria-label={choice.label} title={choice.label}>
30
+ <Icon name={choice.icon} size={16} />
31
+ </button>
32
+ ))}
33
+ </div>
34
+ )
35
+ }
36
+
37
+ <script>
38
+ const KEY = "starlight-theme"
39
+ const stored = (): string => {
40
+ try {
41
+ return localStorage.getItem(KEY) || "light"
42
+ } catch {
43
+ return "light"
44
+ }
45
+ }
46
+ const system = () => (matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark")
47
+ const apply = (choice: string) => {
48
+ try {
49
+ localStorage.setItem(KEY, choice)
50
+ } catch {
51
+ // Stockage refusé : le thème vaut pour la page affichée.
52
+ }
53
+ const theme = choice === "auto" ? system() : choice
54
+ document.documentElement.dataset.theme = theme
55
+ document.documentElement.dataset.hdTheme = theme
56
+ sync()
57
+ }
58
+ const sync = () => {
59
+ const choice = stored()
60
+ const dark = document.documentElement.dataset.theme === "dark"
61
+ for (const button of document.querySelectorAll<HTMLButtonElement>("[data-hd-theme-toggle]"))
62
+ button.setAttribute("aria-label", dark ? "Passer au thème clair" : "Passer au thème sombre")
63
+ for (const radio of document.querySelectorAll<HTMLButtonElement>("[data-hd-theme]")) {
64
+ const checked = radio.dataset.hdTheme === choice
65
+ radio.setAttribute("aria-checked", String(checked))
66
+ radio.tabIndex = checked ? 0 : -1
67
+ }
68
+ }
69
+
70
+ for (const button of document.querySelectorAll<HTMLButtonElement>("[data-hd-theme-toggle]"))
71
+ button.addEventListener("click", () => apply(document.documentElement.dataset.theme === "dark" ? "light" : "dark"))
72
+ for (const group of document.querySelectorAll<HTMLElement>(".hd-theme-choice")) {
73
+ const radios = [...group.querySelectorAll<HTMLButtonElement>("[data-hd-theme]")]
74
+ for (const radio of radios) radio.addEventListener("click", () => apply(radio.dataset.hdTheme!))
75
+ // Groupe de boutons radio : les flèches déplacent le choix, Tab sort du groupe.
76
+ group.addEventListener("keydown", (event) => {
77
+ const step = event.key === "ArrowRight" || event.key === "ArrowDown" ? 1 : event.key === "ArrowLeft" || event.key === "ArrowUp" ? -1 : 0
78
+ if (!step) return
79
+ event.preventDefault()
80
+ const index = radios.findIndex((radio) => radio.getAttribute("aria-checked") === "true")
81
+ const next = radios[(index + step + radios.length) % radios.length]!
82
+ apply(next.dataset.hdTheme!)
83
+ next.focus()
84
+ })
85
+ }
86
+ matchMedia("(prefers-color-scheme: light)").addEventListener("change", () => {
87
+ if (stored() === "auto") apply("auto")
88
+ })
89
+ sync()
90
+ </script>
@@ -0,0 +1,45 @@
1
+ ---
2
+ import data from "virtual:hgdc-docs/config"
3
+
4
+ import Icon from "./Icon.astro"
5
+ import { assistantEnabled } from "./sections.ts"
6
+
7
+ /**
8
+ * Contenu et table des matières côte à côte. La colonne du contenu garde une largeur de
9
+ * lecture ; la table colle sous l'en-tête. Elle laisse la place à l'assistant quand il est ouvert.
10
+ */
11
+ const { toc } = Astro.locals.starlightRoute
12
+ const assistant = assistantEnabled(data.config)
13
+ ---
14
+
15
+ <div class:list={["hd-columns", { "hd-columns--toc": toc }]}>
16
+ <div class="hd-columns__main main-pane">
17
+ <slot />
18
+ {
19
+ assistant && (
20
+ <form class="hd-askbar" data-askbar data-pagefind-ignore>
21
+ <label class="sr-only" for="hd-askbar-input">Pose une question à l'assistant</label>
22
+ <input
23
+ id="hd-askbar-input"
24
+ data-askbar-input
25
+ type="text"
26
+ maxlength="1000"
27
+ placeholder="Pose une question…"
28
+ autocomplete="off"
29
+ />
30
+ <kbd class="hd-kbd" data-shortcut aria-hidden="true">Ctrl I</kbd>
31
+ <button type="submit" class="hd-send" aria-label="Envoyer la question"><Icon name="arrow-up" size={16} /></button>
32
+ </form>
33
+ )
34
+ }
35
+ </div>
36
+ {
37
+ toc && (
38
+ <aside class="hd-columns__toc" aria-label="Sur cette page">
39
+ <div class="hd-toc-scroll">
40
+ <slot name="right-sidebar" />
41
+ </div>
42
+ </aside>
43
+ )
44
+ }
45
+ </div>
@@ -0,0 +1,29 @@
1
+ import type { DocsConfig } from "../core/config.ts"
2
+ import {
3
+ pagesOf,
4
+ pageToPath,
5
+ withBase,
6
+ type NavItem,
7
+ type NavTab,
8
+ type NavTree,
9
+ type NavVersion,
10
+ } from "../core/navigation.ts"
11
+
12
+ /** Section affichée (version, onglet) et onglets de sa version, pour l'en-tête et le menu. */
13
+ export function docsSections(tree: NavTree, index: number) {
14
+ const sections = tree.versions.flatMap((version) => version.tabs.map((tab) => ({ version, tab })))
15
+ const current = sections[index] ?? sections[0]!
16
+ const tabs: Array<NavTab> = current.version.tabs.filter((tab) => tab.label)
17
+ const versions: Array<NavVersion> = tree.versions.filter((version) => version.label)
18
+ return { current, tabs, versions }
19
+ }
20
+
21
+ /** Première page d'une liste : la cible d'un onglet ou d'une version. */
22
+ export function sectionHref(base: string, items: Array<NavItem>): string {
23
+ const first = pagesOf(items)[0]
24
+ return withBase(base, first ? pageToPath(first) : "/")
25
+ }
26
+
27
+ export function assistantEnabled(config: DocsConfig): boolean {
28
+ return Boolean(config.project) && config.assistant?.enabled !== false
29
+ }