@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,52 @@
1
+ /** Where the list is kept. Namespaced so a consumer's own keys cannot collide. */
2
+ const STORAGE_KEY = 'duxt:recent-pages';
3
+ const LIMIT = 5;
4
+
5
+ export interface RecentPage {
6
+ path: string;
7
+ title: string;
8
+ }
9
+
10
+ /**
11
+ * The pages this reader visited last, for the search dialog's empty state.
12
+ *
13
+ * localStorage, not a cookie: unlike the package-manager choice this is never
14
+ * needed during server rendering, so it has no business travelling with every
15
+ * request. It stays in the browser, identifies nobody, and clearing site data
16
+ * forgets it.
17
+ */
18
+ export function useRecentPages() {
19
+ const recent = useState<RecentPage[]>('duxt-recent-pages', () => []);
20
+
21
+ function read(): RecentPage[] {
22
+ try {
23
+ const stored = window.localStorage.getItem(STORAGE_KEY);
24
+ return stored ? (JSON.parse(stored) as RecentPage[]) : [];
25
+ } catch {
26
+ // Blocked storage, or a value someone else wrote — either way, no history.
27
+ return [];
28
+ }
29
+ }
30
+
31
+ function remember(page: RecentPage) {
32
+ if (!import.meta.client || !page.path || !page.title) return;
33
+
34
+ const next = [
35
+ page,
36
+ ...read().filter((entry) => entry.path !== page.path)
37
+ ].slice(0, LIMIT);
38
+ recent.value = next;
39
+
40
+ try {
41
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
42
+ } catch {
43
+ // A convenience not worth an error.
44
+ }
45
+ }
46
+
47
+ function load() {
48
+ if (import.meta.client) recent.value = read();
49
+ }
50
+
51
+ return { recent, remember, load };
52
+ }
package/app/error.vue ADDED
@@ -0,0 +1,133 @@
1
+ <script setup lang="ts">
2
+ import type { NuxtError } from '#app';
3
+
4
+ const props = defineProps<{ error: NuxtError }>();
5
+
6
+ const localeLink = useDuxtLink();
7
+ const path = useDuxtPath();
8
+ const duxt = useDuxtConfig();
9
+ const { locale } = useI18n();
10
+
11
+ /**
12
+ * The error page replaces `app.vue`, so it inherits nothing from it — not the
13
+ * `lang` attribute and not the title template. Both have to be set again here,
14
+ * or the one page a reader reaches by accident is the one page with an
15
+ * untitled, language-less document.
16
+ */
17
+ useHead(() => ({
18
+ htmlAttrs: { lang: locale.value },
19
+ title: `${props.error.statusCode} · ${duxt.title}`
20
+ }));
21
+
22
+ /**
23
+ * An error page is not a page of the site.
24
+ *
25
+ * Nothing stopped a crawler indexing this one, and a 404 that gets indexed
26
+ * competes in a search result with the page the reader was actually looking
27
+ * for. `follow` on purpose: the suggestions below are real pages and a crawler
28
+ * that arrived here by a broken link should still reach them.
29
+ */
30
+ useSeoMeta({ robots: 'noindex, follow' });
31
+
32
+ /**
33
+ * The nearest real pages, from the navigation the layout already fetched.
34
+ *
35
+ * A 404 in versioned documentation is usually a URL that is nearly right, and
36
+ * an empty "not found" tells that reader nothing. Only for a 404 — a 500 has
37
+ * no near miss to offer, and suggesting pages after a server error reads as if
38
+ * the site had decided the reader was mistaken.
39
+ */
40
+ const { data: navigation } = await useDuxtNavigation();
41
+
42
+ const suggestions = computed(() => {
43
+ if (props.error.statusCode !== 404) return [];
44
+
45
+ const pages: { path: string; title?: string }[] = [];
46
+
47
+ const walk = (
48
+ items: { path?: string; title?: string; children?: unknown[] }[]
49
+ ) => {
50
+ for (const item of items) {
51
+ if (item.path) pages.push({ path: item.path, title: item.title });
52
+ if (Array.isArray(item.children)) {
53
+ walk(item.children as { path?: string; title?: string }[]);
54
+ }
55
+ }
56
+ };
57
+
58
+ walk((navigation.value ?? []) as { path?: string; title?: string }[]);
59
+
60
+ return nearestPages(path.value, pages);
61
+ });
62
+
63
+ // A page missing from one version but present in another is the interesting
64
+ // case: the reader asked for something real, just not here.
65
+ const elsewhere = computed(
66
+ () =>
67
+ (
68
+ props.error.data as {
69
+ elsewhere?: { version: { label: string }; path: string }[];
70
+ }
71
+ )?.elsewhere ?? []
72
+ );
73
+ </script>
74
+
75
+ <template>
76
+ <NuxtLayout>
77
+ <div
78
+ class="mx-auto flex max-w-2xl flex-col items-center px-4 py-32 text-center"
79
+ >
80
+ <p class="font-mono text-sm text-muted-foreground">
81
+ {{ error.statusCode }}
82
+ </p>
83
+ <h1 class="mt-3 text-3xl font-semibold tracking-tight text-balance">
84
+ {{ error.statusMessage ?? $t('duxt.error.title') }}
85
+ </h1>
86
+
87
+ <div v-if="elsewhere.length" class="mt-8 w-full">
88
+ <p class="mb-3 text-sm text-muted-foreground">
89
+ {{ $t('duxt.error.elsewhere') }}
90
+ </p>
91
+ <div class="flex flex-wrap justify-center gap-2">
92
+ <UiButton
93
+ v-for="entry in elsewhere"
94
+ :key="entry.path"
95
+ as-child
96
+ variant="outline"
97
+ size="sm"
98
+ >
99
+ <NuxtLink :to="localeLink(entry.path)" class="font-mono text-xs">
100
+ {{ entry.version.label }}
101
+ </NuxtLink>
102
+ </UiButton>
103
+ </div>
104
+ </div>
105
+
106
+ <div v-if="suggestions.length" class="mt-8 w-full">
107
+ <p class="mb-3 text-sm text-muted-foreground">
108
+ {{ $t('duxt.error.nearest') }}
109
+ </p>
110
+ <ul class="flex flex-col gap-1 text-sm">
111
+ <li v-for="page in suggestions" :key="page.path">
112
+ <NuxtLink
113
+ :to="localeLink(page.path)"
114
+ class="flex items-center justify-center gap-2 rounded-md px-3 py-1.5 transition-colors hover:bg-accent"
115
+ >
116
+ <span class="font-medium">{{ page.title ?? page.path }}</span>
117
+ <span class="font-mono text-xs text-muted-foreground">{{
118
+ page.path
119
+ }}</span>
120
+ </NuxtLink>
121
+ </li>
122
+ </ul>
123
+ </div>
124
+
125
+ <UiButton as-child class="mt-10">
126
+ <NuxtLink :to="localeLink('/')">
127
+ <Icon name="lucide:arrow-left" class="size-4" />
128
+ {{ $t('duxt.error.back') }}
129
+ </NuxtLink>
130
+ </UiButton>
131
+ </div>
132
+ </NuxtLayout>
133
+ </template>
@@ -0,0 +1,85 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * The shell a release history gets: the releases beside it, and a reading
4
+ * column for the entries.
5
+ *
6
+ * THE SECOND NAME THROUGH THE SHARED SLOT (`DuxtSectionType.layout`), and the
7
+ * shape a changelog needs — which is not the shape the API reference needed.
8
+ * `reference` hands its page the whole column it has, because parameter tables
9
+ * and a request client want it; a release note is prose, and prose set across
10
+ * that column is unreadable. So the column is capped at a measure and the
11
+ * releases take the sidebar. Both shells stop at the same 90rem the header and
12
+ * the footer do — the difference is what each gives its page inside that.
13
+ *
14
+ * Two differences from `docs`, and both follow from what the pages ARE. The
15
+ * sidebar is the release list rather than a prose tree — same navigation, same
16
+ * collection, because a generated section is an ordinary collection and its
17
+ * pages are the releases. And the reading column is capped inside a window that
18
+ * still leaves room for the contents on the right, which is why `main` carries
19
+ * a width rather than the page: a layout owns how wide its prose is set, and
20
+ * `pages/[...slug].vue` draws the same column for every generated section.
21
+ *
22
+ * The contents column IS there, and its links are not the ones Content found:
23
+ * a release page's headings are drawn by `ChangelogGroup` from a prop, so the
24
+ * outline is read back off the page's own AST — see `generated-toc.ts`.
25
+ *
26
+ * Bound only by the SPLIT granularity. A changelog asked for as the one file it
27
+ * was written as is an ordinary docs page and renders in the docs shell — see
28
+ * `changelogSectionType.layout`.
29
+ *
30
+ * A page rendered here draws its own header: see the `owned` computed in
31
+ * `pages/[...slug].vue`.
32
+ */
33
+ const { data: navigation } = await useDuxtNavigation();
34
+
35
+ const { items } = useDuxtSection(navigation);
36
+
37
+ // The header the sticky columns hang under — `6.5rem` with the section row,
38
+ // less without it. Handed down as a variable so the columns here and the
39
+ // contents column `pages/[...slug].vue` draws all read one value.
40
+ const { headerOffset } = useDuxtSectionRow();
41
+ </script>
42
+
43
+ <template>
44
+ <div
45
+ class="flex min-h-[100dvh] flex-col bg-background text-foreground"
46
+ :style="{ '--duxt-header-offset': headerOffset }"
47
+ >
48
+ <DuxtSkipLink />
49
+
50
+ <DuxtProgress />
51
+ <DuxtShortcuts />
52
+
53
+ <DuxtHeader />
54
+ <DuxtSections />
55
+
56
+ <div class="mx-auto flex w-full max-w-[90rem] flex-1 gap-8 px-4 lg:px-8">
57
+ <!-- A section with one page has nothing to navigate, exactly as in the
58
+ docs layout: the column would list the page the reader is on. That is
59
+ the whole overview of a changelog with a single release. -->
60
+ <div v-if="items.length > 1" class="hidden w-56 shrink-0 lg:block">
61
+ <div
62
+ class="sticky top-[var(--duxt-header-offset)] max-h-[calc(100vh-var(--duxt-header-offset)-1.5rem)] overflow-y-auto py-8 pr-2"
63
+ >
64
+ <DuxtNavigation
65
+ :items="items"
66
+ :label="$t('duxt.changelog.releases')"
67
+ />
68
+ </div>
69
+ </div>
70
+
71
+ <main
72
+ id="duxt-main"
73
+ tabindex="-1"
74
+ class="mx-auto flex w-full min-w-0 max-w-5xl flex-1 outline-none"
75
+ >
76
+ <slot />
77
+ </main>
78
+ </div>
79
+
80
+ <DuxtFooter />
81
+
82
+ <!-- One toaster per layout: toast() needs a mounted target to draw into. -->
83
+ <UiToaster position="bottom-right" />
84
+ </div>
85
+ </template>
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ // The landing layout: full width, no sidebar. Docs pages opt into `docs`.
3
+ </script>
4
+
5
+ <template>
6
+ <div class="flex min-h-[100dvh] flex-col bg-background text-foreground">
7
+ <DuxtSkipLink />
8
+
9
+ <!-- How far down the page the reader is, and the `?` sheet listing every
10
+ key the theme binds. -->
11
+ <DuxtProgress />
12
+ <DuxtShortcuts />
13
+
14
+ <DuxtHeader />
15
+ <main id="duxt-main" tabindex="-1" class="flex-1 outline-none">
16
+ <slot />
17
+ </main>
18
+ <DuxtFooter />
19
+
20
+ <!-- One toaster per layout: toast() needs a mounted target to draw into. -->
21
+ <UiToaster position="bottom-right" />
22
+ </div>
23
+ </template>
@@ -0,0 +1,62 @@
1
+ <script setup lang="ts">
2
+ const { data: navigation } = await useDuxtNavigation();
3
+
4
+ const { items } = useDuxtSection(navigation);
5
+
6
+ // The header the sticky columns hang under — `6.5rem` with the section row,
7
+ // less without it. Handed down as a variable so the columns here and the
8
+ // contents column `pages/[...slug].vue` draws all read one value.
9
+ const { headerOffset } = useDuxtSectionRow();
10
+ </script>
11
+
12
+ <template>
13
+ <div
14
+ class="flex min-h-[100dvh] flex-col bg-background text-foreground"
15
+ :style="{ '--duxt-header-offset': headerOffset }"
16
+ >
17
+ <DuxtSkipLink />
18
+
19
+ <!-- How far down the page the reader is, and the `?` sheet listing every
20
+ key the theme binds. -->
21
+ <DuxtProgress />
22
+ <DuxtShortcuts />
23
+
24
+ <DuxtHeader />
25
+
26
+ <!-- The section row sits with the docs, not in the global header: the
27
+ landing page has no sections to show. -->
28
+ <DuxtSections />
29
+
30
+ <!-- Three columns inside one centred container, not a sidebar pinned to the
31
+ window edge: on a wide screen the docs stay a readable block instead of
32
+ drifting apart. -->
33
+ <div class="mx-auto flex w-full max-w-[90rem] flex-1 gap-8 px-4 lg:px-8">
34
+ <!-- A div, not an aside. The <nav> inside is the landmark and carries
35
+ the label; a second, unnamed `complementary` around it only makes a
36
+ screen reader's landmark list longer. -->
37
+ <!-- A section with one page has nothing to navigate: the sidebar would be
38
+ a column listing the page the reader is already on. It drops out, and
39
+ the content takes the width. -->
40
+ <div v-if="items.length > 1" class="hidden w-56 shrink-0 lg:block">
41
+ <div
42
+ class="sticky top-[var(--duxt-header-offset)] max-h-[calc(100vh-var(--duxt-header-offset)-1.5rem)] overflow-y-auto py-8 pr-2"
43
+ >
44
+ <DuxtNavigation :items="items" :label="$t('duxt.nav.docs')" />
45
+ </div>
46
+ </div>
47
+
48
+ <main
49
+ id="duxt-main"
50
+ tabindex="-1"
51
+ class="flex min-w-0 flex-1 outline-none"
52
+ >
53
+ <slot />
54
+ </main>
55
+ </div>
56
+
57
+ <DuxtFooter />
58
+
59
+ <!-- One toaster per layout: toast() needs a mounted target to draw into. -->
60
+ <UiToaster position="bottom-right" />
61
+ </div>
62
+ </template>
@@ -0,0 +1,85 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * The layout a generated section's type binds when the docs shell will not do.
4
+ *
5
+ * THE FIRST NAME THROUGH THE SHARED SLOT (`DuxtSectionType.layout`), and the
6
+ * shape the API reference needs: the operations on the left, and the whole
7
+ * remaining width for the page — which then splits itself into the description
8
+ * and the client, because those two are properties of the operation and a
9
+ * layout cannot reach them.
10
+ *
11
+ * ONE difference from `docs`, and it is the sidebar: the endpoint list rather
12
+ * than a prose tree — the same navigation, from the same collection, because a
13
+ * generated section is an ordinary collection and its pages ARE the endpoints.
14
+ *
15
+ * The WIDTH is not a difference, and it was: this shell ran to 100rem where
16
+ * every other one on the site stops at 90rem, so on a wide screen the reference
17
+ * stood ten rem past the header above it and the footer below it. The argument
18
+ * for it — parameter tables and a request client want room — was an argument
19
+ * about the OPERATION, which splits itself and can be given that room there;
20
+ * it was never an argument for the page hanging over the site's own edge.
21
+ * Alignment with the header is worth more than ten rem nobody asked for.
22
+ *
23
+ * A page rendered here draws its own header: see the `owned` computed in
24
+ * `pages/[...slug].vue`.
25
+ *
26
+ * NO CONTENTS COLUMN, and it is this layout that has to say so — the page
27
+ * cannot know. An operation already fills its right-hand side with the request
28
+ * client, and a second sticky column beside that one is two columns of
29
+ * furniture around a table of parameters. `provide` before any await, or the
30
+ * value never reaches the page.
31
+ */
32
+ provide(DUXT_ASIDE, false);
33
+
34
+ const { data: navigation } = await useDuxtNavigation();
35
+
36
+ const { items } = useDuxtSection(navigation);
37
+
38
+ // The header the sticky columns hang under — `6.5rem` with the section row,
39
+ // less without it. Handed down as a variable so the columns here and the
40
+ // contents column `pages/[...slug].vue` draws all read one value.
41
+ const { headerOffset } = useDuxtSectionRow();
42
+ </script>
43
+
44
+ <template>
45
+ <div
46
+ class="flex min-h-[100dvh] flex-col bg-background text-foreground"
47
+ :style="{ '--duxt-header-offset': headerOffset }"
48
+ >
49
+ <DuxtSkipLink />
50
+
51
+ <DuxtProgress />
52
+ <DuxtShortcuts />
53
+
54
+ <DuxtHeader />
55
+ <DuxtSections />
56
+
57
+ <div class="mx-auto flex w-full max-w-[90rem] flex-1 gap-8 px-4 lg:px-8">
58
+ <!-- A section with one page has nothing to navigate, exactly as in the
59
+ docs layout: the column would list the page the reader is on. -->
60
+ <div v-if="items.length > 1" class="hidden w-64 shrink-0 lg:block">
61
+ <div
62
+ class="sticky top-[var(--duxt-header-offset)] max-h-[calc(100vh-var(--duxt-header-offset)-1.5rem)] overflow-y-auto py-8 pr-2"
63
+ >
64
+ <DuxtNavigation
65
+ :items="items"
66
+ :label="$t('duxt.openapi.endpoints')"
67
+ />
68
+ </div>
69
+ </div>
70
+
71
+ <main
72
+ id="duxt-main"
73
+ tabindex="-1"
74
+ class="flex min-w-0 flex-1 outline-none"
75
+ >
76
+ <slot />
77
+ </main>
78
+ </div>
79
+
80
+ <DuxtFooter />
81
+
82
+ <!-- One toaster per layout: toast() needs a mounted target to draw into. -->
83
+ <UiToaster position="bottom-right" />
84
+ </div>
85
+ </template>
@@ -0,0 +1,7 @@
1
+ import { type ClassValue, clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+
4
+ /** Merge conditional class lists, letting later Tailwind utilities win. */
5
+ export function cn(...inputs: ClassValue[]) {
6
+ return twMerge(clsx(inputs));
7
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The layout slot a generated section's type renders through.
3
+ *
4
+ * A ROUTE MIDDLEWARE, and deliberately not `<NuxtLayout>` inside the page: a
5
+ * layout rendered from within a page is remounted on every navigation, which
6
+ * would rebuild the header, the section row and the sidebar — losing their
7
+ * scroll and their open groups — on every click of a docs site. `setPageLayout`
8
+ * from a middleware is the one place the choice can be made before the route
9
+ * resolves, so the layout stays where it is and only its name changes.
10
+ *
11
+ * Cheap where no type names a layout: `generatedLayout` filters to the sections
12
+ * that do and answers before matching a single prefix. The path it is handed is
13
+ * still computed either way — arguments are evaluated first — which is one
14
+ * `stripLocalePrefix` per navigation and nothing else.
15
+ */
16
+ export default defineNuxtRouteMiddleware((to) => {
17
+ const sources =
18
+ (useAppConfig().duxt as DuxtConfig | undefined)?.resolvedSources ?? [];
19
+
20
+ const layout = generatedLayout(
21
+ // The DOCUMENTATION path, as every other lookup in the theme means it: the
22
+ // locale translates the interface, not the content tree, so the manifest's
23
+ // prefixes have no locale segment in front of them.
24
+ stripLocalePrefix(to.path, localeCodes()),
25
+ sources
26
+ );
27
+
28
+ // Cast for the reason `DuxtCollectionName` is a plain string: the name is
29
+ // DATA. Nuxt types `setPageLayout` by the layouts it found in this app, and a
30
+ // type's layout is named in a config the layer cannot see at build time.
31
+ //
32
+ // The FUNCTION is cast, not the argument. `setPageLayout` is generic over
33
+ // `keyof NuxtLayouts`, so `Parameters<typeof setPageLayout>[0]` resolves
34
+ // through a conditional on the type parameter and lands back on `string` —
35
+ // which is then not assignable to the parameter it was derived from. Casting
36
+ // the call signature says the one thing that is actually true: this name is
37
+ // checked at run time, against a registry the compiler cannot see.
38
+ if (layout) (setPageLayout as (name: string) => void)(layout);
39
+ });
40
+
41
+ /**
42
+ * The locales the site serves, read off the plugin rather than `useI18n()`.
43
+ *
44
+ * `useI18n()` wants a component instance; a middleware has none, and
45
+ * `nuxtApp.$i18n` is what @nuxtjs/i18n exposes for exactly this. Absent — a
46
+ * consumer who removed the module — the path is used as it stands, which is
47
+ * correct for a site with no locale prefixes to strip.
48
+ */
49
+ function localeCodes(): string[] {
50
+ const i18n = useNuxtApp().$i18n as
51
+ | { locales?: { value?: (string | { code: string })[] } }
52
+ | undefined;
53
+
54
+ return (i18n?.locales?.value ?? []).map((entry) =>
55
+ typeof entry === 'string' ? entry : entry.code
56
+ );
57
+ }