@kirchdev/duxt 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.
Files changed (401) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -0
  3. package/app/app.config.ts +13 -0
  4. package/app/app.vue +122 -0
  5. package/app/assets/css/duxt.css +555 -0
  6. package/app/assets/css/typeset.css +498 -0
  7. package/app/components/DuxtBrand.vue +53 -0
  8. package/app/components/DuxtBreadcrumb.vue +37 -0
  9. package/app/components/DuxtCodeBlock.vue +143 -0
  10. package/app/components/DuxtCopyPage.vue +117 -0
  11. package/app/components/DuxtFooter.vue +86 -0
  12. package/app/components/DuxtHeader.vue +496 -0
  13. package/app/components/DuxtJsonEditor.vue +359 -0
  14. package/app/components/DuxtLandingProse.vue +90 -0
  15. package/app/components/DuxtLandingShowcase.vue +295 -0
  16. package/app/components/DuxtLiveWindow.vue +343 -0
  17. package/app/components/DuxtLocale.vue +86 -0
  18. package/app/components/DuxtMetaList.vue +76 -0
  19. package/app/components/DuxtNavigation.vue +94 -0
  20. package/app/components/DuxtNavigationLink.vue +41 -0
  21. package/app/components/DuxtOpenApiCallbacks.vue +92 -0
  22. package/app/components/DuxtOpenApiClient.vue +1339 -0
  23. package/app/components/DuxtOpenApiMedia.vue +108 -0
  24. package/app/components/DuxtOpenApiMethod.vue +59 -0
  25. package/app/components/DuxtOpenApiParameters.vue +114 -0
  26. package/app/components/DuxtOpenApiResponses.vue +109 -0
  27. package/app/components/DuxtOpenApiSchema.vue +365 -0
  28. package/app/components/DuxtOpenApiSecurity.vue +115 -0
  29. package/app/components/DuxtPageFeedback.vue +56 -0
  30. package/app/components/DuxtPageInfo.vue +194 -0
  31. package/app/components/DuxtPageNav.vue +93 -0
  32. package/app/components/DuxtPreviewSkeleton.vue +262 -0
  33. package/app/components/DuxtProgress.vue +45 -0
  34. package/app/components/DuxtSearch.vue +271 -0
  35. package/app/components/DuxtSections.vue +65 -0
  36. package/app/components/DuxtShortcuts.vue +46 -0
  37. package/app/components/DuxtSkipLink.vue +34 -0
  38. package/app/components/DuxtToc.vue +86 -0
  39. package/app/components/DuxtTranslationBanner.vue +64 -0
  40. package/app/components/DuxtVersion.vue +168 -0
  41. package/app/components/DuxtVersionBanner.vue +109 -0
  42. package/app/components/OgImage/Duxt.satori.vue +82 -0
  43. package/app/components/content/Accordion.vue +37 -0
  44. package/app/components/content/AccordionItem.vue +46 -0
  45. package/app/components/content/Callout.vue +58 -0
  46. package/app/components/content/ChangelogGroup.vue +91 -0
  47. package/app/components/content/ChangelogReleases.vue +520 -0
  48. package/app/components/content/CodeGroup.vue +183 -0
  49. package/app/components/content/DevtoolsPanel.vue +107 -0
  50. package/app/components/content/Field.vue +50 -0
  51. package/app/components/content/FieldGroup.vue +8 -0
  52. package/app/components/content/FileTree.vue +92 -0
  53. package/app/components/content/Mermaid.vue +70 -0
  54. package/app/components/content/OpenApiOperation.vue +185 -0
  55. package/app/components/content/OpenApiOperations.vue +72 -0
  56. package/app/components/content/OpenApiOverview.vue +302 -0
  57. package/app/components/content/PackageManagers.vue +187 -0
  58. package/app/components/content/PageCards.vue +48 -0
  59. package/app/components/content/Partial.vue +65 -0
  60. package/app/components/content/Preview.vue +173 -0
  61. package/app/components/content/ProseA.vue +55 -0
  62. package/app/components/content/ProseH2.vue +53 -0
  63. package/app/components/content/ProseH3.vue +53 -0
  64. package/app/components/content/ProseH4.vue +53 -0
  65. package/app/components/content/ProseImg.vue +87 -0
  66. package/app/components/content/ProsePre.vue +58 -0
  67. package/app/components/content/ProseTable.vue +11 -0
  68. package/app/components/content/Since.vue +21 -0
  69. package/app/components/content/Steps.vue +20 -0
  70. package/app/components/content/Tab.vue +23 -0
  71. package/app/components/content/TabGroup.vue +58 -0
  72. package/app/components/ui/alert/Alert.vue +21 -0
  73. package/app/components/ui/alert/AlertDescription.vue +22 -0
  74. package/app/components/ui/alert/AlertTitle.vue +22 -0
  75. package/app/components/ui/alert/index.ts +24 -0
  76. package/app/components/ui/badge/Badge.vue +28 -0
  77. package/app/components/ui/badge/index.ts +52 -0
  78. package/app/components/ui/breadcrumb/Breadcrumb.vue +13 -0
  79. package/app/components/ui/breadcrumb/BreadcrumbEllipsis.vue +22 -0
  80. package/app/components/ui/breadcrumb/BreadcrumbItem.vue +17 -0
  81. package/app/components/ui/breadcrumb/BreadcrumbLink.vue +24 -0
  82. package/app/components/ui/breadcrumb/BreadcrumbList.vue +22 -0
  83. package/app/components/ui/breadcrumb/BreadcrumbPage.vue +20 -0
  84. package/app/components/ui/breadcrumb/BreadcrumbSeparator.vue +21 -0
  85. package/app/components/ui/breadcrumb/index.ts +7 -0
  86. package/app/components/ui/button/Button.vue +31 -0
  87. package/app/components/ui/button/index.ts +39 -0
  88. package/app/components/ui/card/Card.vue +22 -0
  89. package/app/components/ui/card/CardAction.vue +22 -0
  90. package/app/components/ui/card/CardContent.vue +14 -0
  91. package/app/components/ui/card/CardDescription.vue +17 -0
  92. package/app/components/ui/card/CardFooter.vue +17 -0
  93. package/app/components/ui/card/CardHeader.vue +22 -0
  94. package/app/components/ui/card/CardTitle.vue +17 -0
  95. package/app/components/ui/card/index.ts +7 -0
  96. package/app/components/ui/collapsible/Collapsible.vue +19 -0
  97. package/app/components/ui/collapsible/CollapsibleContent.vue +12 -0
  98. package/app/components/ui/collapsible/CollapsibleTrigger.vue +12 -0
  99. package/app/components/ui/collapsible/index.ts +3 -0
  100. package/app/components/ui/command/Command.vue +98 -0
  101. package/app/components/ui/command/CommandDialog.vue +42 -0
  102. package/app/components/ui/command/CommandEmpty.vue +31 -0
  103. package/app/components/ui/command/CommandGroup.vue +52 -0
  104. package/app/components/ui/command/CommandInput.vue +45 -0
  105. package/app/components/ui/command/CommandItem.vue +85 -0
  106. package/app/components/ui/command/CommandList.vue +32 -0
  107. package/app/components/ui/command/CommandSeparator.vue +23 -0
  108. package/app/components/ui/command/CommandShortcut.vue +19 -0
  109. package/app/components/ui/command/index.ts +29 -0
  110. package/app/components/ui/dialog/Dialog.vue +15 -0
  111. package/app/components/ui/dialog/DialogClose.vue +12 -0
  112. package/app/components/ui/dialog/DialogContent.vue +61 -0
  113. package/app/components/ui/dialog/DialogDescription.vue +25 -0
  114. package/app/components/ui/dialog/DialogFooter.vue +30 -0
  115. package/app/components/ui/dialog/DialogHeader.vue +17 -0
  116. package/app/components/ui/dialog/DialogOverlay.vue +28 -0
  117. package/app/components/ui/dialog/DialogScrollContent.vue +65 -0
  118. package/app/components/ui/dialog/DialogTitle.vue +25 -0
  119. package/app/components/ui/dialog/DialogTrigger.vue +12 -0
  120. package/app/components/ui/dialog/index.ts +10 -0
  121. package/app/components/ui/dropdown-menu/DropdownMenu.vue +19 -0
  122. package/app/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +47 -0
  123. package/app/components/ui/dropdown-menu/DropdownMenuContent.vue +47 -0
  124. package/app/components/ui/dropdown-menu/DropdownMenuGroup.vue +12 -0
  125. package/app/components/ui/dropdown-menu/DropdownMenuItem.vue +41 -0
  126. package/app/components/ui/dropdown-menu/DropdownMenuLabel.vue +27 -0
  127. package/app/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
  128. package/app/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +48 -0
  129. package/app/components/ui/dropdown-menu/DropdownMenuSeparator.vue +23 -0
  130. package/app/components/ui/dropdown-menu/DropdownMenuShortcut.vue +19 -0
  131. package/app/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
  132. package/app/components/ui/dropdown-menu/DropdownMenuSubContent.vue +34 -0
  133. package/app/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +34 -0
  134. package/app/components/ui/dropdown-menu/DropdownMenuTrigger.vue +17 -0
  135. package/app/components/ui/dropdown-menu/index.ts +16 -0
  136. package/app/components/ui/input/Input.vue +35 -0
  137. package/app/components/ui/input/index.ts +1 -0
  138. package/app/components/ui/navigation-menu/NavigationMenu.vue +42 -0
  139. package/app/components/ui/navigation-menu/NavigationMenuContent.vue +35 -0
  140. package/app/components/ui/navigation-menu/NavigationMenuIndicator.vue +32 -0
  141. package/app/components/ui/navigation-menu/NavigationMenuItem.vue +23 -0
  142. package/app/components/ui/navigation-menu/NavigationMenuLink.vue +30 -0
  143. package/app/components/ui/navigation-menu/NavigationMenuList.vue +30 -0
  144. package/app/components/ui/navigation-menu/NavigationMenuTrigger.vue +31 -0
  145. package/app/components/ui/navigation-menu/NavigationMenuViewport.vue +30 -0
  146. package/app/components/ui/navigation-menu/index.ts +14 -0
  147. package/app/components/ui/scroll-area/ScrollArea.vue +31 -0
  148. package/app/components/ui/scroll-area/ScrollBar.vue +38 -0
  149. package/app/components/ui/scroll-area/index.ts +2 -0
  150. package/app/components/ui/select/Select.vue +15 -0
  151. package/app/components/ui/select/SelectContent.vue +59 -0
  152. package/app/components/ui/select/SelectGroup.vue +19 -0
  153. package/app/components/ui/select/SelectItem.vue +42 -0
  154. package/app/components/ui/select/SelectItemText.vue +12 -0
  155. package/app/components/ui/select/SelectLabel.vue +16 -0
  156. package/app/components/ui/select/SelectScrollDownButton.vue +28 -0
  157. package/app/components/ui/select/SelectScrollUpButton.vue +28 -0
  158. package/app/components/ui/select/SelectSeparator.vue +20 -0
  159. package/app/components/ui/select/SelectTrigger.vue +32 -0
  160. package/app/components/ui/select/SelectValue.vue +12 -0
  161. package/app/components/ui/select/index.ts +11 -0
  162. package/app/components/ui/separator/Separator.vue +30 -0
  163. package/app/components/ui/separator/index.ts +1 -0
  164. package/app/components/ui/sheet/Sheet.vue +15 -0
  165. package/app/components/ui/sheet/SheetClose.vue +12 -0
  166. package/app/components/ui/sheet/SheetContent.vue +68 -0
  167. package/app/components/ui/sheet/SheetDescription.vue +23 -0
  168. package/app/components/ui/sheet/SheetFooter.vue +15 -0
  169. package/app/components/ui/sheet/SheetHeader.vue +15 -0
  170. package/app/components/ui/sheet/SheetOverlay.vue +28 -0
  171. package/app/components/ui/sheet/SheetTitle.vue +23 -0
  172. package/app/components/ui/sheet/SheetTrigger.vue +12 -0
  173. package/app/components/ui/sheet/index.ts +8 -0
  174. package/app/components/ui/sidebar/Sidebar.vue +110 -0
  175. package/app/components/ui/sidebar/SidebarContent.vue +23 -0
  176. package/app/components/ui/sidebar/SidebarFooter.vue +18 -0
  177. package/app/components/ui/sidebar/SidebarGroup.vue +18 -0
  178. package/app/components/ui/sidebar/SidebarGroupAction.vue +31 -0
  179. package/app/components/ui/sidebar/SidebarGroupContent.vue +18 -0
  180. package/app/components/ui/sidebar/SidebarGroupLabel.vue +30 -0
  181. package/app/components/ui/sidebar/SidebarHeader.vue +18 -0
  182. package/app/components/ui/sidebar/SidebarInput.vue +19 -0
  183. package/app/components/ui/sidebar/SidebarInset.vue +23 -0
  184. package/app/components/ui/sidebar/SidebarMenu.vue +18 -0
  185. package/app/components/ui/sidebar/SidebarMenuAction.vue +42 -0
  186. package/app/components/ui/sidebar/SidebarMenuBadge.vue +28 -0
  187. package/app/components/ui/sidebar/SidebarMenuButton.vue +60 -0
  188. package/app/components/ui/sidebar/SidebarMenuButtonChild.vue +36 -0
  189. package/app/components/ui/sidebar/SidebarMenuItem.vue +18 -0
  190. package/app/components/ui/sidebar/SidebarMenuSkeleton.vue +35 -0
  191. package/app/components/ui/sidebar/SidebarMenuSub.vue +24 -0
  192. package/app/components/ui/sidebar/SidebarMenuSubButton.vue +43 -0
  193. package/app/components/ui/sidebar/SidebarMenuSubItem.vue +18 -0
  194. package/app/components/ui/sidebar/SidebarProvider.vue +109 -0
  195. package/app/components/ui/sidebar/SidebarRail.vue +35 -0
  196. package/app/components/ui/sidebar/SidebarSeparator.vue +19 -0
  197. package/app/components/ui/sidebar/SidebarTrigger.vue +26 -0
  198. package/app/components/ui/sidebar/index.ts +62 -0
  199. package/app/components/ui/sidebar/utils.ts +19 -0
  200. package/app/components/ui/skeleton/Skeleton.vue +17 -0
  201. package/app/components/ui/skeleton/index.ts +1 -0
  202. package/app/components/ui/sonner/Sonner.vue +67 -0
  203. package/app/components/ui/sonner/index.ts +1 -0
  204. package/app/components/ui/tabs/Tabs.vue +26 -0
  205. package/app/components/ui/tabs/TabsContent.vue +23 -0
  206. package/app/components/ui/tabs/TabsList.vue +28 -0
  207. package/app/components/ui/tabs/TabsTrigger.vue +30 -0
  208. package/app/components/ui/tabs/index.ts +4 -0
  209. package/app/components/ui/textarea/Textarea.vue +32 -0
  210. package/app/components/ui/textarea/index.ts +1 -0
  211. package/app/components/ui/tooltip/Tooltip.vue +15 -0
  212. package/app/components/ui/tooltip/TooltipContent.vue +49 -0
  213. package/app/components/ui/tooltip/TooltipProvider.vue +14 -0
  214. package/app/components/ui/tooltip/TooltipTrigger.vue +12 -0
  215. package/app/components/ui/tooltip/index.ts +4 -0
  216. package/app/composables/useActiveHeading.ts +90 -0
  217. package/app/composables/useDuxtAnimatedHeight.ts +155 -0
  218. package/app/composables/useDuxtBreadcrumb.ts +60 -0
  219. package/app/composables/useDuxtChoice.ts +28 -0
  220. package/app/composables/useDuxtCollection.ts +89 -0
  221. package/app/composables/useDuxtConfig.ts +47 -0
  222. package/app/composables/useDuxtNavigation.ts +87 -0
  223. package/app/composables/useDuxtPageFocus.ts +30 -0
  224. package/app/composables/useDuxtPath.ts +42 -0
  225. package/app/composables/useDuxtSearch.ts +208 -0
  226. package/app/composables/useDuxtSection.ts +44 -0
  227. package/app/composables/useDuxtSectionRow.ts +49 -0
  228. package/app/composables/useDuxtShortcuts.ts +58 -0
  229. package/app/composables/useDuxtSiteUrl.ts +27 -0
  230. package/app/composables/useDuxtToast.ts +25 -0
  231. package/app/composables/useDuxtVersion.ts +138 -0
  232. package/app/composables/useFuzzySearch.ts +83 -0
  233. package/app/composables/usePackageManager.ts +4 -0
  234. package/app/composables/useRecentPages.ts +52 -0
  235. package/app/error.vue +133 -0
  236. package/app/layouts/changelog.vue +85 -0
  237. package/app/layouts/default.vue +23 -0
  238. package/app/layouts/docs.vue +62 -0
  239. package/app/layouts/reference.vue +85 -0
  240. package/app/lib/utils.ts +7 -0
  241. package/app/middleware/duxt-section-layout.global.ts +57 -0
  242. package/app/pages/[...slug].vue +441 -0
  243. package/app/pages/index.vue +479 -0
  244. package/app/types/duxt.d.ts +955 -0
  245. package/app/utils/aside.ts +16 -0
  246. package/app/utils/changelog.ts +182 -0
  247. package/app/utils/code-highlight.ts +116 -0
  248. package/app/utils/duxt-config.ts +185 -0
  249. package/app/utils/duxt-text.ts +135 -0
  250. package/app/utils/file-icons.ts +62 -0
  251. package/app/utils/generated-sections.ts +190 -0
  252. package/app/utils/generated-toc.ts +216 -0
  253. package/app/utils/heading-link.ts +32 -0
  254. package/app/utils/locale-path.ts +45 -0
  255. package/app/utils/navigation-tree.ts +206 -0
  256. package/app/utils/nearest-page.ts +72 -0
  257. package/app/utils/openapi.ts +1028 -0
  258. package/app/utils/package-command.ts +162 -0
  259. package/app/utils/request-samples.ts +635 -0
  260. package/app/utils/section-scope.ts +97 -0
  261. package/app/utils/sheet-navigation.ts +100 -0
  262. package/app/utils/source-file.ts +84 -0
  263. package/app/utils/version-choices.ts +68 -0
  264. package/app/utils/version-paths.ts +65 -0
  265. package/bin/duxt-report.mjs +45 -0
  266. package/components.json +19 -0
  267. package/content-cache.ts +193 -0
  268. package/content.config.ts +38 -0
  269. package/duxt-app-config.ts +124 -0
  270. package/highlight-langs.ts +68 -0
  271. package/i18n/i18n.config.ts +16 -0
  272. package/i18n/locales/de/duxt/changelog.json +17 -0
  273. package/i18n/locales/de/duxt/code.json +13 -0
  274. package/i18n/locales/de/duxt/defaults.json +22 -0
  275. package/i18n/locales/de/duxt/devtools.json +7 -0
  276. package/i18n/locales/de/duxt/error.json +10 -0
  277. package/i18n/locales/de/duxt/footer.json +7 -0
  278. package/i18n/locales/de/duxt/locale.json +7 -0
  279. package/i18n/locales/de/duxt/nav.json +17 -0
  280. package/i18n/locales/de/duxt/openapi.json +89 -0
  281. package/i18n/locales/de/duxt/page.json +34 -0
  282. package/i18n/locales/de/duxt/search.json +12 -0
  283. package/i18n/locales/de/duxt/shortcuts.json +11 -0
  284. package/i18n/locales/de/duxt/theme.json +7 -0
  285. package/i18n/locales/de/duxt/toc.json +7 -0
  286. package/i18n/locales/de/duxt/version.json +25 -0
  287. package/i18n/locales/en/duxt/changelog.json +17 -0
  288. package/i18n/locales/en/duxt/code.json +13 -0
  289. package/i18n/locales/en/duxt/defaults.json +22 -0
  290. package/i18n/locales/en/duxt/devtools.json +7 -0
  291. package/i18n/locales/en/duxt/error.json +10 -0
  292. package/i18n/locales/en/duxt/footer.json +7 -0
  293. package/i18n/locales/en/duxt/locale.json +7 -0
  294. package/i18n/locales/en/duxt/nav.json +17 -0
  295. package/i18n/locales/en/duxt/openapi.json +89 -0
  296. package/i18n/locales/en/duxt/page.json +34 -0
  297. package/i18n/locales/en/duxt/search.json +12 -0
  298. package/i18n/locales/en/duxt/shortcuts.json +11 -0
  299. package/i18n/locales/en/duxt/theme.json +7 -0
  300. package/i18n/locales/en/duxt/toc.json +7 -0
  301. package/i18n/locales/en/duxt/version.json +25 -0
  302. package/i18n/locales/es/duxt/changelog.json +17 -0
  303. package/i18n/locales/es/duxt/code.json +13 -0
  304. package/i18n/locales/es/duxt/defaults.json +22 -0
  305. package/i18n/locales/es/duxt/devtools.json +7 -0
  306. package/i18n/locales/es/duxt/error.json +10 -0
  307. package/i18n/locales/es/duxt/footer.json +7 -0
  308. package/i18n/locales/es/duxt/locale.json +7 -0
  309. package/i18n/locales/es/duxt/nav.json +17 -0
  310. package/i18n/locales/es/duxt/openapi.json +89 -0
  311. package/i18n/locales/es/duxt/page.json +34 -0
  312. package/i18n/locales/es/duxt/search.json +12 -0
  313. package/i18n/locales/es/duxt/shortcuts.json +11 -0
  314. package/i18n/locales/es/duxt/theme.json +7 -0
  315. package/i18n/locales/es/duxt/toc.json +7 -0
  316. package/i18n/locales/es/duxt/version.json +25 -0
  317. package/i18n/locales/fr/duxt/changelog.json +17 -0
  318. package/i18n/locales/fr/duxt/code.json +13 -0
  319. package/i18n/locales/fr/duxt/defaults.json +22 -0
  320. package/i18n/locales/fr/duxt/devtools.json +7 -0
  321. package/i18n/locales/fr/duxt/error.json +10 -0
  322. package/i18n/locales/fr/duxt/footer.json +7 -0
  323. package/i18n/locales/fr/duxt/locale.json +7 -0
  324. package/i18n/locales/fr/duxt/nav.json +17 -0
  325. package/i18n/locales/fr/duxt/openapi.json +89 -0
  326. package/i18n/locales/fr/duxt/page.json +34 -0
  327. package/i18n/locales/fr/duxt/search.json +12 -0
  328. package/i18n/locales/fr/duxt/shortcuts.json +11 -0
  329. package/i18n/locales/fr/duxt/theme.json +7 -0
  330. package/i18n/locales/fr/duxt/toc.json +7 -0
  331. package/i18n/locales/fr/duxt/version.json +25 -0
  332. package/i18n/locales/pt/duxt/changelog.json +17 -0
  333. package/i18n/locales/pt/duxt/code.json +13 -0
  334. package/i18n/locales/pt/duxt/defaults.json +22 -0
  335. package/i18n/locales/pt/duxt/devtools.json +7 -0
  336. package/i18n/locales/pt/duxt/error.json +10 -0
  337. package/i18n/locales/pt/duxt/footer.json +7 -0
  338. package/i18n/locales/pt/duxt/locale.json +7 -0
  339. package/i18n/locales/pt/duxt/nav.json +17 -0
  340. package/i18n/locales/pt/duxt/openapi.json +89 -0
  341. package/i18n/locales/pt/duxt/page.json +34 -0
  342. package/i18n/locales/pt/duxt/search.json +12 -0
  343. package/i18n/locales/pt/duxt/shortcuts.json +11 -0
  344. package/i18n/locales/pt/duxt/theme.json +7 -0
  345. package/i18n/locales/pt/duxt/toc.json +7 -0
  346. package/i18n/locales/pt/duxt/version.json +25 -0
  347. package/i18n/locales/pt-BR/duxt/error.json +8 -0
  348. package/i18n/locales/pt-BR/duxt/nav.json +10 -0
  349. package/i18n/locales/pt-BR/duxt/page.json +10 -0
  350. package/i18n/locales/pt-BR/duxt/search.json +11 -0
  351. package/i18n/locales/pt-BR/duxt/version.json +13 -0
  352. package/mdc.config.ts +28 -0
  353. package/modules/config.ts +440 -0
  354. package/modules/devtools.ts +126 -0
  355. package/modules/git-meta.ts +349 -0
  356. package/modules/redirects.ts +152 -0
  357. package/modules/validate.ts +137 -0
  358. package/nuxt.config.ts +530 -0
  359. package/openapi-model.ts +358 -0
  360. package/openapi-parse.ts +1052 -0
  361. package/package.json +161 -0
  362. package/public/devtools/cache.html +318 -0
  363. package/public/devtools/checks.html +309 -0
  364. package/public/devtools/config.html +461 -0
  365. package/public/devtools/i18n.html +309 -0
  366. package/public/devtools/pages.html +348 -0
  367. package/public/devtools/paths.html +315 -0
  368. package/public/devtools/redirects.html +309 -0
  369. package/public/devtools/search.html +324 -0
  370. package/public/devtools/sources.html +309 -0
  371. package/public/devtools/versions.html +318 -0
  372. package/report.ts +303 -0
  373. package/repository-root.ts +26 -0
  374. package/section-reports.ts +55 -0
  375. package/sections-changelog.ts +644 -0
  376. package/sections-openapi.ts +450 -0
  377. package/sections-resolve.ts +711 -0
  378. package/sections.ts +157 -0
  379. package/server/devtools/content.ts +120 -0
  380. package/server/devtools/context.ts +38 -0
  381. package/server/devtools/entry-path.ts +30 -0
  382. package/server/devtools/handler.ts +104 -0
  383. package/server/devtools/preview.ts +461 -0
  384. package/server/devtools/render/content.ts +233 -0
  385. package/server/devtools/render/sources.ts +414 -0
  386. package/server/devtools/render/system.ts +352 -0
  387. package/server/devtools/shell.ts +611 -0
  388. package/server/devtools/sources.ts +122 -0
  389. package/server/devtools/system.ts +178 -0
  390. package/server/mcp/tools/list-pages.ts +52 -0
  391. package/server/mcp/tools/read-page.ts +57 -0
  392. package/server/mcp/tools/search-docs.ts +74 -0
  393. package/server/middleware/raw-markdown.ts +86 -0
  394. package/server/routes/llms-full.txt.get.ts +75 -0
  395. package/server/routes/llms.txt.get.ts +63 -0
  396. package/server/routes/rss.xml.get.ts +125 -0
  397. package/server/utils/duxt-server-text.ts +46 -0
  398. package/sources-git.ts +113 -0
  399. package/sources-resolve.ts +908 -0
  400. package/sources.ts +287 -0
  401. package/validate-report.ts +494 -0
@@ -0,0 +1,955 @@
1
+ declare global {
2
+ /**
3
+ * A configured string: a literal, an i18n key, or a per-locale record.
4
+ *
5
+ * Which one it is, is decided by whether a key is registered — see
6
+ * `resolveDuxtText`. Every text field below accepts all three, so a
7
+ * single-language site never sees the other two.
8
+ */
9
+ type DuxtText = string | Record<string, string>;
10
+
11
+ /**
12
+ * The package managers a command block can speak for.
13
+ *
14
+ * Declared here rather than in `app/utils/package-command.ts` because this is
15
+ * the file that owns the public config surface, and one definition cannot
16
+ * drift from the other. The translation table is checked against it: `dlx`
17
+ * maps every member, so a fifth name added here fails to compile until it has
18
+ * a spelling.
19
+ */
20
+ type DuxtPackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';
21
+
22
+ /**
23
+ * The request the try-it client has built, as a sample generator receives it.
24
+ *
25
+ * Declared here rather than exported from `app/utils/openapi.ts` because it is
26
+ * public now: `duxt.requestSamples` takes a consumer's own generator, and this
27
+ * is the whole of what such a generator is given. `body` is the editor's text,
28
+ * not parsed — a generator that wants it as data parses it itself, and gets to
29
+ * decide what to do when it is not JSON.
30
+ */
31
+ interface DuxtOpenApiRequest {
32
+ method: string;
33
+ url: string;
34
+ headers: Record<string, string>;
35
+ body?: string;
36
+ /**
37
+ * The component name of what a successful response returns, where the
38
+ * document gave it one — `Widget`, or `Widget[]` for a list.
39
+ *
40
+ * This is what makes a TypeScript sample worth more than the JavaScript one
41
+ * it would otherwise be character for character: `$fetch<Widget>(…)` is the
42
+ * line somebody actually writes. Absent where the response schema is inline
43
+ * rather than a `$ref`, which no generator can invent a name for — a sample
44
+ * then simply has no type parameter.
45
+ */
46
+ responseType?: string;
47
+ }
48
+
49
+ /**
50
+ * One code sample beside the try-it client.
51
+ *
52
+ * `generate` runs in the BROWSER, on every keystroke, because the sample has to
53
+ * follow the request the reader is editing. It must therefore be synchronous,
54
+ * pure, and cheap; it must not touch the network or the DOM.
55
+ *
56
+ * `language` is a Shiki id, and it is read at BUILD time: `modules/config.ts`
57
+ * collects the ids of the configured samples and loads exactly those grammars
58
+ * into the runtime highlighter, so a site pays for the languages it shows and
59
+ * no others. A language Shiki does not know renders as plain text.
60
+ *
61
+ * `group` is the first level of the picker and `label` the second, so three
62
+ * clients for one language cost one control rather than three tabs.
63
+ */
64
+ interface DuxtRequestSample {
65
+ /** Stable across releases: it is also the value remembered in the cookie. */
66
+ id: string;
67
+ label: DuxtText;
68
+ group: DuxtText;
69
+ language: string;
70
+ /**
71
+ * The icon for this sample's GROUP, where the language does not answer for
72
+ * it.
73
+ *
74
+ * Without one the picker draws `fileIcon(language)`, and the language is the
75
+ * grammar rather than the tab: every JavaScript client asks for
76
+ * `typescript`, so the tab reading "JavaScript" wore a TypeScript logo, and
77
+ * `curl` wore a generic shell file. The first sample of a group that names
78
+ * one wins, so a group needs it on at most one member — the shipped ones set
79
+ * it on all of theirs, so dropping `fetch` from the list does not cost
80
+ * JavaScript its mark.
81
+ */
82
+ icon?: string;
83
+ generate: (request: DuxtOpenApiRequest) => string;
84
+ }
85
+
86
+ /**
87
+ * The name of a page collection, as Content generated it for THIS site.
88
+ *
89
+ * Was the literal `'docs'` while the layer always shipped a collection by
90
+ * that name. It no longer does — the collections are generated from the
91
+ * site's own `duxt.sources`, so a site with two repositories has
92
+ * `docs_duxt` and `docs_workflows` and no `docs` at all.
93
+ *
94
+ * A plain string, because the name is DATA: it comes from the resolved
95
+ * manifest, which the build computed from a list only the consumer knows.
96
+ * Content's own key union cannot be named here — it is generated per site —
97
+ * so the few calls that need it derive it from Content's own signature
98
+ * instead, with `DuxtCollectionArg`.
99
+ */
100
+ type DuxtCollectionName = string;
101
+
102
+ /** The exact key type a Content query wants, taken from its own signature. */
103
+ type DuxtCollectionArg = Parameters<typeof queryCollection>[0];
104
+
105
+ /**
106
+ * The same config after `useDuxtConfig()` has resolved it: every `DuxtText`
107
+ * has collapsed to a string.
108
+ *
109
+ * Two types rather than one because they are genuinely two things — what a
110
+ * consumer WRITES may be a key or a record, what a component READS is always
111
+ * a word. Without the split every template would have to narrow a union it
112
+ * can never actually receive.
113
+ */
114
+ type DuxtResolved<T> = [NonNullable<T>] extends [DuxtText]
115
+ ? [Record<string, string>] extends [NonNullable<T>]
116
+ ? undefined extends T
117
+ ? string | undefined
118
+ : string
119
+ : T
120
+ : // A FUNCTION IS AN OBJECT, and the mapped type below turns one into `{}` —
121
+ // it has no own enumerable keys to map. Harmless while every field was
122
+ // data; `DuxtRequestSample.generate` is a function a consumer writes, and
123
+ // without this branch the config type says it cannot be called.
124
+ T extends (...args: never[]) => unknown
125
+ ? T
126
+ : T extends readonly (infer U)[]
127
+ ? DuxtResolved<U>[]
128
+ : T extends object
129
+ ? { [K in keyof T]: DuxtResolved<T[K]> }
130
+ : T;
131
+
132
+ type DuxtConfigResolved = DuxtResolved<DuxtConfig>;
133
+
134
+ /** A navbar, footer or landing link. `children` turns a navbar entry into a dropdown. */
135
+ /**
136
+ * Where a version sits in its life — see `DuxtSourceStatus` in
137
+ * `sources-resolve.ts` for what each one costs the page.
138
+ */
139
+ type DuxtSourceStatusInput =
140
+ | 'upcoming'
141
+ | 'current'
142
+ | 'maintained'
143
+ | 'deprecated'
144
+ | 'eol';
145
+
146
+ /**
147
+ * A branch by name, or a tag stated as one.
148
+ *
149
+ * `'latest'` is reserved: it resolves at build time to the newest semver tag
150
+ * of that repository. A branch genuinely called latest needs `{ branch }`.
151
+ */
152
+ type DuxtRefInput =
153
+ | string
154
+ | {
155
+ branch: string;
156
+ label?: string;
157
+ status?: DuxtSourceStatusInput;
158
+ locales?: DuxtSourceLocaleInput[];
159
+ }
160
+ | {
161
+ tag: string;
162
+ label?: string;
163
+ status?: DuxtSourceStatusInput;
164
+ locales?: DuxtSourceLocaleInput[];
165
+ };
166
+
167
+ /**
168
+ * One language of a source: the folder it lives in, or where else it lives.
169
+ *
170
+ * A string is a folder inside the source's `path`. The object form moves the
171
+ * language wholesale — its own folder, repository or ref — which is how a
172
+ * translation kept by other people at their own pace becomes a source rather
173
+ * than a second website.
174
+ */
175
+ type DuxtSourceLocaleInput =
176
+ | string
177
+ | { locale: string; path?: string; repo?: string; ref?: DuxtRefInput };
178
+
179
+ /**
180
+ * A documentation source, as a consumer declares it in `app.config.ts`.
181
+ *
182
+ * Read at BUILD time — this is what the collections are generated from — so
183
+ * a change here needs a rebuild, unlike the rest of this config.
184
+ */
185
+ interface DuxtSourceInput {
186
+ /** Folder holding the Markdown, relative to the repository root. */
187
+ path?: string;
188
+ /** `owner/name` or a full git URL. Omitted means this repository. */
189
+ repo?: string;
190
+ /** Refs to publish as versions. Omitted means the current checkout. */
191
+ refs?: DuxtRefInput[];
192
+ /**
193
+ * Languages this source is available in, beyond the one in `path`.
194
+ *
195
+ * The default locale is the tree in `path` itself, so listing it changes
196
+ * nothing and a site that adds this key does not move the pages it already
197
+ * serves. A ref may override the list, because a translation is usually
198
+ * kept for the current version and not for the two behind it.
199
+ */
200
+ locales?: DuxtSourceLocaleInput[];
201
+ /**
202
+ * The version THIS source is, where no ref names one.
203
+ *
204
+ * A version is normally a checkout — list `refs` and each becomes one. An API
205
+ * is usually not versioned that way: `openapi/v1.yaml` sits beside
206
+ * `openapi/v2.yaml` in one repository, and without this key the two are two
207
+ * unrelated sections rather than two versions of one document.
208
+ *
209
+ * Named here, everything else follows the ref path exactly: the URL segment,
210
+ * the switcher entry (scoped to the same artefact), the banner and the
211
+ * canonical. `sourceOptions.defaultRef` names which of them is served without
212
+ * a prefix, whether it is a ref or one of these.
213
+ *
214
+ * Never beside `refs` — a source with both would have to be served at two
215
+ * prefixes at once, and the resolver says so rather than picking one.
216
+ */
217
+ version?: string;
218
+ /** Shown in the version switcher and used in the URL; defaults to the ref. */
219
+ label?: DuxtText;
220
+ /**
221
+ * Segment used in the URL for this source; defaults to the repository name.
222
+ *
223
+ * A claim on a segment, not a spelling: a source that names one is served
224
+ * under it whether or not the site has a second repository, which is what
225
+ * lets one prefixed source sit beside documentation that stays at the root.
226
+ */
227
+ slug?: string;
228
+ /** Lifecycle of every version this entry publishes, unless a ref says otherwise. */
229
+ status?: DuxtSourceStatusInput;
230
+ /**
231
+ * The repository a source read off disk lives in, for links back to it.
232
+ * Not `repo`, which is what makes Content download a source.
233
+ */
234
+ origin?: { repo: string; ref?: string };
235
+ /**
236
+ * Read this source's git history for "Last updated" and the contributors.
237
+ * Off by default for a remote source: Content clones with `--depth 1`, and
238
+ * unshallowing that is a download the consumer should choose.
239
+ */
240
+ history?: boolean;
241
+ /**
242
+ * Artefacts beside this source's Markdown, published as pages of the site.
243
+ *
244
+ * Off until declared. A list, because a monorepo declaring a changelog per
245
+ * package is the normal case rather than the exotic one.
246
+ */
247
+ generated?: DuxtGeneratedSectionInput[];
248
+ }
249
+
250
+ /** Where a generated section's navbar entry goes. */
251
+ type DuxtSectionPlacementInput = 'navigation' | 'sections' | false;
252
+
253
+ /**
254
+ * One artefact that is not Markdown, published as pages of the site.
255
+ *
256
+ * Not spelled `sections`: `duxt.sections` below is the second navbar row, and
257
+ * two meanings on one public name is a collision the layer pays for later.
258
+ */
259
+ interface DuxtGeneratedSectionInput {
260
+ /** The registry key of the type that parses it, e.g. `changelog`. */
261
+ type: string;
262
+ /**
263
+ * The artefact, relative to the source's own root — the repository root
264
+ * for a source read off disk, the root of the downloaded checkout for one
265
+ * Content clones. A path only, never a URL.
266
+ */
267
+ path: string;
268
+ /**
269
+ * The navbar entry's label, and — slugified — its URL segment.
270
+ *
271
+ * A plain string, not a `DuxtText`: a translated text is not a stable URL,
272
+ * the same rule a version's label follows.
273
+ */
274
+ label: string;
275
+ /** URL segment for this section; defaults to the slugified label. */
276
+ slug?: string;
277
+ /**
278
+ * The versions of THIS ARTEFACT, where the source's own refs do not name
279
+ * them.
280
+ *
281
+ * A version is normally a checkout: list `refs` on the source and every
282
+ * section it carries is published once per ref. An API is usually not kept
283
+ * that way — `openapi/v1.yaml` beside `openapi/v2.yaml` in one repository,
284
+ * versioned by FILE — and without this key the two are two unrelated
285
+ * sections with two entries in the navbar.
286
+ *
287
+ * Declared here rather than as two sources: two sections are offered as
288
+ * versions of one another only when they came from ONE declaration, and a
289
+ * source always publishes a documentation tree, so a source per API version
290
+ * would publish the prose twice.
291
+ *
292
+ * Never beside a source versioned by refs — both want the same segment of
293
+ * the URL, and the build says so.
294
+ *
295
+ * ```ts
296
+ * generated: [
297
+ * {
298
+ * type: 'openapi',
299
+ * label: 'API',
300
+ * versions: [
301
+ * { version: 'v2', path: 'openapi/v2.yaml' },
302
+ * { version: 'v1', path: 'openapi/v1.yaml', status: 'deprecated' }
303
+ * ]
304
+ * }
305
+ * ]
306
+ * ```
307
+ */
308
+ versions?: {
309
+ /** Shown in the switcher and used in the URL. */
310
+ version: string;
311
+ /** The artefact this version reads; defaults to the declaration's. */
312
+ path?: string;
313
+ /** Per-locale artefacts for this version. */
314
+ locales?: Record<string, string>;
315
+ /** Lifecycle of this version. */
316
+ status?: DuxtSourceStatusInput;
317
+ /** Served without a version segment. Defaults to the first in the list. */
318
+ default?: boolean;
319
+ }[];
320
+ /**
321
+ * The knobs this TYPE offers, as this site turns them.
322
+ *
323
+ * Opaque to the layer: what a key means is the type's own business — the
324
+ * `changelog` type reads `granularity` here (`split`, the default, or
325
+ * `flat`), an API reference would read something else entirely. A type
326
+ * names the option it does not recognise rather than ignoring it.
327
+ */
328
+ options?: Record<string, unknown>;
329
+ /**
330
+ * The artefact a LOCALE reads, where that locale ships one of its own.
331
+ *
332
+ * Only a `per-locale` type reads it. Keyed by the locale code the source
333
+ * declares, with the language alone accepted too, so `pt` answers for
334
+ * `pt-BR`. A locale absent from the map builds no collection at all, and
335
+ * the existing fallback chain then serves it the default language's
336
+ * section with the translation banner saying so.
337
+ */
338
+ locales?: Record<string, string>;
339
+ /**
340
+ * Where its navbar entry goes. The second navbar row unless stated, so a
341
+ * declared section is findable without further config.
342
+ */
343
+ navigation?: DuxtSectionPlacementInput;
344
+ /** Icon for that entry; falls back to the type's own. */
345
+ icon?: string;
346
+ }
347
+
348
+ /** One page a section type's parser produced. */
349
+ interface DuxtSectionPageInput {
350
+ /** File name inside the section, extension included. */
351
+ file: string;
352
+ /** The whole file — frontmatter block and body. */
353
+ body: string;
354
+ }
355
+
356
+ /**
357
+ * A type in the section registry: what turns one artefact into pages.
358
+ *
359
+ * The whole extension surface, and public from day one — a consumer supplying
360
+ * a parser and a layout inherits search, `llms.txt`, the feed, the sitemap and
361
+ * the navigation, because what it produces is an ordinary collection.
362
+ */
363
+ interface DuxtSectionTypeInput {
364
+ parse: (
365
+ artefact: string,
366
+ context: {
367
+ label: string;
368
+ prefix: string;
369
+ /** The declaration's own `options`, empty where it named none. */
370
+ options: Record<string, unknown>;
371
+ }
372
+ ) => DuxtSectionPageInput[];
373
+ /** `global` is one history at a version-neutral URL; `per-version` is not. */
374
+ versioning: 'global' | 'per-version';
375
+ /**
376
+ * `original` builds one collection and lets the translation banner say so;
377
+ * `per-locale` builds one per language that declares an artefact of its own.
378
+ */
379
+ localisation: 'original' | 'per-locale';
380
+ /**
381
+ * The layout its pages render in. A name bound here is public surface.
382
+ *
383
+ * A function where the declaration's own options decide it — a changelog
384
+ * split into a page per release draws chrome of its own, the same file
385
+ * rendered whole is an ordinary docs page.
386
+ */
387
+ layout?:
388
+ | string
389
+ | ((options: Record<string, unknown>) => string | undefined);
390
+ /** Icon for the navbar entry, when the declaration names none. */
391
+ icon?: string;
392
+ }
393
+
394
+ interface DuxtSourceOptionsInput {
395
+ /** Force a repository segment even with a single repository. */
396
+ showRepo?: boolean;
397
+ /** Force a version segment even with a single version. */
398
+ showVersion?: boolean;
399
+ /** The ref served without a version prefix, by name. Defaults to the first. */
400
+ defaultRef?: string;
401
+ /**
402
+ * The locale whose pages are the tree in `path` itself, without a folder.
403
+ * Defaults to the first locale any source declares.
404
+ */
405
+ defaultLocale?: string;
406
+ }
407
+
408
+ /** One entry of the resolved source manifest — see `duxtSourceManifest()`. */
409
+ interface DuxtResolvedSource {
410
+ collection: string;
411
+ prefix: string;
412
+ repo?: string;
413
+ version?: string;
414
+ isDefault: boolean;
415
+ /** Where the pages came from — what "Edit this page" links back to. */
416
+ repository?: string;
417
+ repositoryUrl?: string;
418
+ ref?: string;
419
+ refKind?: 'branch' | 'tag';
420
+ path: string;
421
+ /** The locale this collection serves; absent on a site with no translations. */
422
+ locale?: string;
423
+ /** True for the locale served from `path` itself, without a folder. */
424
+ isDefaultLocale: boolean;
425
+ status: DuxtSourceStatusInput;
426
+ history: boolean;
427
+ /**
428
+ * Present when this collection is a generated section rather than a docs
429
+ * tree. `path` is then the artefact itself rather than a folder.
430
+ */
431
+ generated?: {
432
+ type: string;
433
+ label: string;
434
+ slug: string;
435
+ /**
436
+ * Which declaration produced this entry — the identity, not an address.
437
+ *
438
+ * A section is one collection per version and per locale, so one declared
439
+ * section reaches the manifest as several of these; the navbar puts one
440
+ * link in the row for all of them, and this is how it knows which ones.
441
+ * Compared for equality only, inside one manifest.
442
+ */
443
+ declaration: number;
444
+ navigation: DuxtSectionPlacementInput;
445
+ icon?: string;
446
+ layout?: string;
447
+ versioning: 'global' | 'per-version';
448
+ localisation: 'original' | 'per-locale';
449
+ remote: boolean;
450
+ /** The declaration's own options, where it named any. */
451
+ options?: Record<string, unknown>;
452
+ };
453
+ }
454
+
455
+ interface DuxtLink {
456
+ label: DuxtText;
457
+ to?: string;
458
+ icon?: string;
459
+ description?: DuxtText;
460
+ external?: boolean;
461
+ children?: DuxtLink[];
462
+ }
463
+
464
+ interface DuxtSection extends DuxtLink {
465
+ /**
466
+ * The icon for pages in this section that carry none of their own.
467
+ *
468
+ * A page states its icon in frontmatter, and most do — the sidebar then
469
+ * shows ten pages with ten symbols that actually distinguish them. Some
470
+ * pages cannot: an ADR's frontmatter is fixed at `title`, `description`,
471
+ * `status` and `date`, so a decision log renders eight rows with nothing
472
+ * beside them while every other section has a column of icons.
473
+ *
474
+ * Set here, one symbol stands in for the whole section, which is what a set
475
+ * of like records wants anyway. Falls back to `duxt.pageIcon`, and a page's
476
+ * own icon always wins.
477
+ */
478
+ pageIcon?: string;
479
+ }
480
+
481
+ interface DuxtAction extends DuxtLink {
482
+ variant?:
483
+ | 'default'
484
+ | 'secondary'
485
+ | 'outline'
486
+ | 'ghost'
487
+ | 'link'
488
+ | 'destructive';
489
+ }
490
+
491
+ interface DuxtFeature {
492
+ title: DuxtText;
493
+ description?: DuxtText;
494
+ icon?: string;
495
+ /** Makes the whole card a link — to the page that explains this feature. */
496
+ to?: string;
497
+ external?: boolean;
498
+ }
499
+
500
+ /**
501
+ * The pill above the headline. A plain text is the short form; the object
502
+ * adds an icon, a colour and a destination — "Latest release" pointing at the
503
+ * releases page is the case it was built for.
504
+ */
505
+ interface DuxtBadge {
506
+ label: DuxtText;
507
+ icon?: string;
508
+ variant?: 'default' | 'secondary' | 'outline' | 'success' | 'destructive';
509
+ to?: string;
510
+ external?: boolean;
511
+ }
512
+
513
+ interface DuxtLanding {
514
+ badge?: DuxtText | DuxtBadge;
515
+ headline?: DuxtText;
516
+ description?: DuxtText;
517
+ actions?: DuxtAction[];
518
+ /**
519
+ * The command under the hero buttons — how a reader installs the thing this
520
+ * site documents, e.g. `pnpm add -D @acme/sdk`.
521
+ *
522
+ * Not a `DuxtText`: a shell command is the same in every language, and one
523
+ * translated by mistake is one that does not run. The layer ships none, for
524
+ * the same reason it ships no repository link — it does not know what your
525
+ * project is called.
526
+ */
527
+ command?: string;
528
+ /** A picture of the site itself, framed as a browser window. */
529
+ preview?: DuxtPreview;
530
+ /**
531
+ * The claims the hero makes in numbers — "7 locales", "1 line of config".
532
+ *
533
+ * A row rather than a sentence, because a number read in a paragraph is a
534
+ * number nobody remembers. Drawn under the hero's buttons; absent, the row
535
+ * is not drawn at all.
536
+ */
537
+ stats?: DuxtStat[];
538
+ /**
539
+ * The window under the hero, in the shape a reader can drive: several pages
540
+ * of this same site behind a tab bar, one frame, one page loaded at a time.
541
+ *
542
+ * `preview` is the single-page form of the same idea and stays what a site
543
+ * with one thing to show writes. Where both are set the tabbed one wins,
544
+ * because it is strictly the larger statement.
545
+ */
546
+ demo?: DuxtLandingDemo;
547
+ /**
548
+ * The bands between the window and the feature grid: one feature at a time,
549
+ * its prose on one side and something running on the other.
550
+ *
551
+ * This is where a site shows rather than tells — a live page of its own API
552
+ * reference, the config that produced it, a screenshot. The sides alternate
553
+ * on their own, so a list written top to bottom needs no layout decisions.
554
+ */
555
+ showcase?: DuxtShowcase[];
556
+ features?: DuxtFeature[];
557
+ /**
558
+ * The closing list: everything that is real but does not earn a band of its
559
+ * own. An icon, a line, no link — a reader who wants one of these will find
560
+ * it in the navigation.
561
+ */
562
+ highlights?: DuxtFeature[];
563
+ /**
564
+ * The visible heading over that list.
565
+ *
566
+ * A CONFIG FIELD rather than one of the layer's own strings, and the line
567
+ * between the two is whether a reader sees it. `featuresTitle` is shipped
568
+ * because it is `sr-only` — a name the document outline needs and nobody
569
+ * reads. "And the rest" is prose on the page, and prose on the page belongs
570
+ * to the site that wrote the list underneath it.
571
+ *
572
+ * Unset, the list draws no heading and its entries are paragraphs rather
573
+ * than headings, so the outline gains nothing to explain.
574
+ */
575
+ highlightsTitle?: DuxtText;
576
+ }
577
+
578
+ /** One number in the hero's row, with the words that give it a meaning. */
579
+ interface DuxtStat {
580
+ /**
581
+ * The number as it is printed — `'7'`, `'1 line'`, `'~0 KB'`. A string, not
582
+ * a number: half of these are not quantities, and a site that has to format
583
+ * `0` into `'zero config'` in the config is a site that will not.
584
+ */
585
+ value: string;
586
+ label: DuxtText;
587
+ icon?: string;
588
+ }
589
+
590
+ /**
591
+ * The tabbed window: one live frame, several pages to point it at.
592
+ *
593
+ * Every tab is a page of THIS site, for the reason `DuxtPreview.to` gives —
594
+ * a window framing somebody else's site is an advert.
595
+ */
596
+ interface DuxtLandingDemo {
597
+ tabs: DuxtDemoTab[];
598
+ /** Window height, any CSS length. Defaults to a responsive clamp. */
599
+ height?: string;
600
+ }
601
+
602
+ interface DuxtDemoTab {
603
+ label: DuxtText;
604
+ to: string;
605
+ icon?: string;
606
+ /** The poster drawn while this page loads. Defaults to `docs`. */
607
+ skeleton?: DuxtSkeletonVariant;
608
+ }
609
+
610
+ /**
611
+ * Which shape the window draws while a page is on its way.
612
+ *
613
+ * Named per target rather than guessed from its path: the layer has no idea
614
+ * that `/api` is an OpenAPI section or that `/llms.txt` is plain text — a
615
+ * consumer may call them anything — and a poster whose layout is not the
616
+ * layout that arrives reads as the frame having loaded the wrong page.
617
+ */
618
+ type DuxtSkeletonVariant = 'docs' | 'api' | 'text';
619
+
620
+ /**
621
+ * The words half of a band: eyebrow, heading, paragraph, list, link.
622
+ *
623
+ * A type of its own because a band may need TWO of them — a split client puts
624
+ * its form in one row and its samples in the next, and each row wants its own
625
+ * sentence about what the reader is looking at.
626
+ */
627
+ interface DuxtShowcaseProse {
628
+ /** The eyebrow over the title — a two-word name for the area. */
629
+ badge?: DuxtText;
630
+ icon?: string;
631
+ title: DuxtText;
632
+ description?: DuxtText;
633
+ /** The three things this feature actually does, as a checked list. */
634
+ bullets?: DuxtShowcaseBullet[];
635
+ /** The way into the page that explains it. */
636
+ action?: DuxtAction;
637
+ }
638
+
639
+ /** One band: prose on one side, something running on the other. */
640
+ interface DuxtShowcase extends DuxtShowcaseProse {
641
+ /**
642
+ * Put the demo on the LEFT, against the alternation.
643
+ *
644
+ * Unset, the bands alternate by their position in the list, which is what a
645
+ * page of them wants. Set, a band overrides that — and every band after it
646
+ * keeps alternating from wherever the list said, not from the override.
647
+ */
648
+ reverse?: boolean;
649
+ /**
650
+ * Give the demo the WHOLE width, with the prose above it rather than beside
651
+ * it.
652
+ *
653
+ * For a demo that is not a picture of something but the thing itself: a
654
+ * try-it client squeezed into half a band is the same mistake a framed page
655
+ * makes one level down — a control built for a column of its own, put in a
656
+ * column that is not one. `reverse` means nothing here; there are no sides.
657
+ */
658
+ full?: boolean;
659
+ demo: DuxtDemo;
660
+ }
661
+
662
+ interface DuxtShowcaseBullet {
663
+ label: DuxtText;
664
+ icon?: string;
665
+ }
666
+
667
+ /**
668
+ * What a band shows. Three kinds, and the discriminant is `type` rather than
669
+ * which key happens to be set: a demo missing its one required field should
670
+ * fail to typecheck, not fall through to another kind.
671
+ */
672
+ type DuxtDemo =
673
+ | DuxtDemoFrame
674
+ | DuxtDemoCode
675
+ | DuxtDemoImage
676
+ | DuxtDemoOperation;
677
+
678
+ /**
679
+ * The try-it client of one operation, rendered on its own.
680
+ *
681
+ * `frame` pointed at the same page shows the client inside a whole second
682
+ * copy of the application — and below 80rem the panel sits under the entire
683
+ * description, so a band-sized window opened the page and showed prose. This
684
+ * renders the CONTROL, which is what the band is about: no frame, no poster,
685
+ * no wait, and strictly less to download than the page around it.
686
+ *
687
+ * `to` is the operation page's own path; the operation is read from the page
688
+ * Content already built for it, so nothing here parses OpenAPI a second time.
689
+ */
690
+ interface DuxtDemoOperation {
691
+ type: 'operation';
692
+ to: string;
693
+ /**
694
+ * `split` breaks the client into two rows — the form in one, the request
695
+ * samples in the next — each with its own prose beside it, and the sides
696
+ * alternating the way the bands themselves do. The shape a full-width band
697
+ * wants. Defaults to the single card an operation page draws.
698
+ */
699
+ layout?: 'panel' | 'split';
700
+ /**
701
+ * The words beside the samples row.
702
+ *
703
+ * Only read when the client is split, because only then is there a second
704
+ * row to write a sentence for. Without it the row draws the samples alone
705
+ * and the space beside them stays empty.
706
+ */
707
+ samples?: DuxtShowcaseProse;
708
+ /**
709
+ * How tall the panel may get before it scrolls itself, any CSS length.
710
+ *
711
+ * A `max-height`, not a height: a GET with two parameters is a short panel
712
+ * and padding it out to the height of a POST would be a box mostly empty.
713
+ * Defaults to the same measure the windows beside it use.
714
+ */
715
+ height?: string;
716
+ }
717
+
718
+ /** A live page of this site, framed and operable — mounted on approach. */
719
+ interface DuxtDemoFrame {
720
+ type: 'frame';
721
+ to: string;
722
+ height?: string;
723
+ /** `false` drops the browser chrome, leaving the page in a plain box. */
724
+ chrome?: boolean;
725
+ /** The poster drawn while the page loads. Defaults to `docs`. */
726
+ skeleton?: DuxtSkeletonVariant;
727
+ }
728
+
729
+ /**
730
+ * The config or the command behind the feature, highlighted.
731
+ *
732
+ * A list rather than one file, because the interesting answer is often two
733
+ * files — what you write and what comes out. Several become tabs.
734
+ */
735
+ interface DuxtDemoCode {
736
+ type: 'code';
737
+ files: DuxtDemoFile[];
738
+ }
739
+
740
+ interface DuxtDemoFile {
741
+ /** The tab's label and the block's header — a file name, or a command. */
742
+ name?: string;
743
+ /** A grammar the RUNTIME highlighter carries: bash, json, typescript. */
744
+ language?: string;
745
+ code: string;
746
+ }
747
+
748
+ /** A picture, for what cannot be framed — a devtools panel, an editor. */
749
+ interface DuxtDemoImage {
750
+ type: 'image';
751
+ src: string;
752
+ srcDark?: string;
753
+ alt?: DuxtText;
754
+ }
755
+
756
+ /**
757
+ * The window under the hero: a page of THIS site, embedded and operable —
758
+ * the reader scrolls it, opens its navigation and switches its theme without
759
+ * leaving the landing page.
760
+ *
761
+ * A still image is the POSTER, not the alternative: the frame is a second
762
+ * copy of the application, and the picture covers the box until that copy has
763
+ * booted. Where no picture is given the window draws the shape of a page
764
+ * instead — see `DuxtPreviewSkeleton`, which needs no asset and is right in
765
+ * both themes by construction. `live: false` is how a site says it would
766
+ * rather not load itself twice at all.
767
+ */
768
+ interface DuxtPreview {
769
+ /** The page to embed. Defaults to the first section. */
770
+ to?: string;
771
+ /** Window height, any CSS length. Defaults to a responsive clamp. */
772
+ height?: string;
773
+ /**
774
+ * A screenshot shown until the live page is up — or instead of it, where
775
+ * `live` is false. `srcDark` serves dark mode; without one, `src` serves
776
+ * both, which on a dark page is a torch.
777
+ */
778
+ src?: string;
779
+ srcDark?: string;
780
+ /**
781
+ * Embed the page at all. `false` shows only `src`, which is what a site
782
+ * picks when a second copy of the application is a cost it will not pay.
783
+ */
784
+ live?: boolean;
785
+ /** The image's alt text, and the frame's accessible name. */
786
+ alt?: DuxtText;
787
+ }
788
+
789
+ interface DuxtConfig {
790
+ title: DuxtText;
791
+ /**
792
+ * A wordmark shown in the header and footer instead of the icon-and-title
793
+ * pair. Unset by default, and deliberately so: the layer ships no branding,
794
+ * because a site extending duxt has its own.
795
+ *
796
+ * `srcDark` is swapped in by CSS, not by reading the colour mode — see
797
+ * `DuxtBrand`. The image is drawn at a fixed height with the width left to
798
+ * follow, so any aspect ratio works. `alt` falls back to `title`.
799
+ */
800
+ logo?: {
801
+ src?: string;
802
+ srcDark?: string;
803
+ alt?: DuxtText;
804
+ };
805
+ /**
806
+ * Which of the layer's locales this site serves. Omitted means all of them.
807
+ *
808
+ * Read at BUILD time — locales decide routes and hreflang, not just what a
809
+ * component draws — so a change here needs a rebuild, unlike the rest of
810
+ * this config. `i18n.defaultLocale` in nuxt.config picks which one is
811
+ * served without a prefix.
812
+ */
813
+ locales?: string[];
814
+ /**
815
+ * Who publishes the site, for the `Organization` node schema.org readers
816
+ * look for — a knowledge panel, a rich result, an AI summary naming a
817
+ * source.
818
+ *
819
+ * Unset by default and unset in the layer: duxt does not know, and must not
820
+ * guess, whose documentation it is rendering (ADR 0005). Without it the
821
+ * site still describes itself as a `WebSite`; what it loses is the publisher
822
+ * behind it.
823
+ *
824
+ * `logo` wants an ABSOLUTE URL or a path from the site root, and schema.org
825
+ * wants it square-ish and at least 112px; `url` defaults to `site.url`.
826
+ */
827
+ organization?: {
828
+ name?: DuxtText;
829
+ url?: string;
830
+ logo?: string;
831
+ };
832
+ /**
833
+ * The icon for any page that carries none of its own, anywhere in the tree.
834
+ *
835
+ * A section's own `pageIcon` overrides it; a page's frontmatter overrides
836
+ * both. Unset, a page without an icon simply shows none — which is the right
837
+ * default, because an icon repeated down a whole sidebar carries no
838
+ * information.
839
+ */
840
+ pageIcon?: string;
841
+ /** Shown as a badge beside the title. */
842
+ version?: string;
843
+ navigation?: DuxtLink[];
844
+ /** The second navbar row: top-level parts of the documentation. */
845
+ sections?: DuxtSection[];
846
+ /** Fixed links under the table of contents. */
847
+ aside?: {
848
+ title?: DuxtText;
849
+ links?: DuxtLink[];
850
+ };
851
+ links?: DuxtLink[];
852
+ landing?: DuxtLanding;
853
+ /**
854
+ * Package managers offered by a command block, in display order.
855
+ *
856
+ * A closed set, not free text: `packageCommand` translates one written
857
+ * command into each manager's own spelling, and it can only do that for the
858
+ * four it has a table for. A fifth name used to be accepted and then
859
+ * prefixed naively — `deno add -D pkg`, where deno wants `deno add npm:pkg`
860
+ * — which is a configurable list with closed semantics, and an invitation.
861
+ */
862
+ packageManagers?: DuxtPackageManager[];
863
+ /**
864
+ * The code samples the try-it client offers, in display order.
865
+ *
866
+ * A string picks one the layer ships — `curl`, `fetch`, `ofetch`,
867
+ * `use-fetch`, `axios`, `python-requests`, `python-httpx`, `python-urllib`,
868
+ * `go`, `php-guzzle`, `php-laravel`, `php-curl` — and an object adds one of
869
+ * the site's own, or replaces a shipped one by reusing its id.
870
+ *
871
+ * Unset means the default seven. A configured list REPLACES rather than
872
+ * extends, like every other list in `duxtDefaults`: otherwise a site
873
+ * documenting a PHP API could add its clients but never drop the ones it
874
+ * does not want.
875
+ */
876
+ requestSamples?: (string | DuxtRequestSample)[];
877
+ /**
878
+ * Extra Shiki grammars for the runtime highlighter, beyond the ones the
879
+ * configured samples already name.
880
+ *
881
+ * The one case that needs it is `x-codeSamples`: a sample written into the
882
+ * OpenAPI document is coloured in the browser like a generated one, and its
883
+ * language is not visible to the build — the document may live in a
884
+ * repository that has not been cloned yet. A spec carrying Ruby samples
885
+ * names `ruby` here, and pays for that one grammar.
886
+ */
887
+ sampleLanguages?: string[];
888
+ /** Layout a consumer can switch off. */
889
+ breadcrumb?: boolean;
890
+ /**
891
+ * The section `/rss.xml` publishes — a changelog, a release log, a blog.
892
+ *
893
+ * Off until it is set. A feed is a list of things that happened, and a
894
+ * reference page being edited is not an event.
895
+ */
896
+ feed?: {
897
+ /** Path prefix whose pages are the feed's items, e.g. `/changelog`. */
898
+ path?: string;
899
+ title?: DuxtText;
900
+ };
901
+ /**
902
+ * The documentation sources. The only place they are declared: the
903
+ * collections and the manifest below are both generated from this.
904
+ */
905
+ sources?: DuxtSourceInput[];
906
+ /** How those sources become URL prefixes. */
907
+ sourceOptions?: DuxtSourceOptionsInput;
908
+ /**
909
+ * Types a source's `generated` sections may name, beyond `changelog`.
910
+ *
911
+ * Read at BUILD time, like `sources` — a map rather than a registration
912
+ * call, because the two loaders that need it cannot see one another's
913
+ * globals. A consumer's entry wins, so a shipped type can be replaced.
914
+ */
915
+ sectionTypes?: Record<string, DuxtSectionTypeInput>;
916
+ /**
917
+ * GENERATED, not written. The duxt module resolves `sources` at build time
918
+ * and writes the manifest here: which collection serves which prefix. It is
919
+ * what the theme and the version switcher actually read.
920
+ */
921
+ resolvedSources?: DuxtResolvedSource[];
922
+ /**
923
+ * GENERATED, not written. The layer's own version and repository, read out
924
+ * of its `package.json` by the duxt module — what the footer's "Powered by"
925
+ * line says and links to.
926
+ */
927
+ layerVersion?: string;
928
+ layerRepository?: string;
929
+ /** `false` drops the "Powered by duxt" line from the footer. */
930
+ poweredBy?: boolean;
931
+ /** Overrides the versions derived from `sources`, when they need labels. */
932
+ versions?: { label: DuxtText; to?: string; description?: DuxtText }[];
933
+ footer?: {
934
+ /** The consumer's own legal links — imprint, privacy policy. */
935
+ legal?: DuxtLink[];
936
+ copyright?: DuxtText;
937
+ };
938
+ }
939
+
940
+ // Typing the config is what makes a consumer's override checkable — without
941
+ // this it is inferred structurally from the layer's own literal, and every
942
+ // optional key the layer happens not to use becomes a type error downstream.
943
+ }
944
+
945
+ declare module 'nuxt/schema' {
946
+ interface AppConfigInput {
947
+ duxt?: Partial<DuxtConfig>;
948
+ }
949
+
950
+ interface AppConfig {
951
+ duxt: DuxtConfig;
952
+ }
953
+ }
954
+
955
+ export {};