@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,63 @@
1
+ import { queryCollection } from '@nuxt/content/nitro';
2
+ // Imported by path, not auto-import: app/ belongs to the Vue app, and Nitro
3
+ // does not see its utils. The defaults have to come from the same file the
4
+ // pages use, or the two descriptions drift apart.
5
+ import { duxtDefaults, mergeDuxtConfig } from '../../app/utils/duxt-config';
6
+ import { resolveServerTexts } from '../utils/duxt-server-text';
7
+
8
+ /**
9
+ * llms.txt — the site's own map, for a model reading it.
10
+ *
11
+ * The convention (llmstxt.org) is a Markdown index: an H1 with the site name,
12
+ * a blockquote summary, then linked sections. It is generated from the same
13
+ * collection the pages render from, so it cannot drift from what is published.
14
+ */
15
+ export default defineEventHandler(async (event) => {
16
+ const appConfig = useAppConfig() as { duxt?: Partial<DuxtConfig> };
17
+ // Resolved here because Nitro has no i18n: without it the description is
18
+ // printed as the translation key it is.
19
+ const duxt = resolveServerTexts(
20
+ mergeDuxtConfig(appConfig.duxt, duxtDefaults)
21
+ );
22
+
23
+ // Every collection the manifest names, not just `docs`: a versioned site
24
+ // has none by that name, and llms.txt is the whole site's index.
25
+ const collections = duxt.resolvedSources?.length
26
+ ? duxt.resolvedSources.map((source) => source.collection)
27
+ : ['docs'];
28
+
29
+ const pages = (
30
+ await Promise.all(
31
+ collections.map((name) =>
32
+ // Cast from Content's own signature: the collection name is data
33
+ // from the manifest, and the key union is generated per site.
34
+ queryCollection(event, name as Parameters<typeof queryCollection>[1])
35
+ .select('path', 'title', 'description')
36
+ .all()
37
+ )
38
+ )
39
+ ).flat();
40
+
41
+ const origin = getRequestURL(event).origin;
42
+
43
+ const lines = [
44
+ `# ${duxt.title}`,
45
+ '',
46
+ `> ${duxt.landing?.description ?? 'Documentation.'}`,
47
+ '',
48
+ '## Pages',
49
+ '',
50
+ ...pages
51
+ .filter((page) => page.path)
52
+ .sort((a, b) => a.path!.localeCompare(b.path!))
53
+ .map(
54
+ (page) =>
55
+ `- [${page.title ?? page.path}](${origin}${page.path})` +
56
+ (page.description ? `: ${page.description}` : '')
57
+ ),
58
+ ''
59
+ ];
60
+
61
+ setHeader(event, 'content-type', 'text/plain; charset=utf-8');
62
+ return lines.join('\n');
63
+ });
@@ -0,0 +1,125 @@
1
+ import { queryCollection } from '@nuxt/content/nitro';
2
+ import { duxtDefaults, mergeDuxtConfig } from '../../app/utils/duxt-config';
3
+ import { resolveServerTexts } from '../utils/duxt-server-text';
4
+
5
+ /**
6
+ * An RSS feed over one section — a changelog, a release log, a blog.
7
+ *
8
+ * Not over the whole documentation. A feed is a list of things that HAPPENED,
9
+ * and a reference page being edited is not an event; a site publishing every
10
+ * page edit as an item teaches its readers to unsubscribe. So the feed is off
11
+ * until `duxt.feed.path` names the section whose pages are events, and empty
12
+ * rather than missing before that: a feed client should be told there is
13
+ * nothing here, not that the feed is gone.
14
+ *
15
+ * Ordering is by the page's own `date`, falling back to the last commit that
16
+ * touched it — which `modules/git-meta.ts` has already put on the page.
17
+ */
18
+ const escape = (value: string) =>
19
+ value.replace(
20
+ /[&<>"']/g,
21
+ (character) =>
22
+ ({
23
+ '&': '&amp;',
24
+ '<': '&lt;',
25
+ '>': '&gt;',
26
+ '"': '&quot;',
27
+ "'": '&apos;'
28
+ })[character] ?? character
29
+ );
30
+
31
+ export default defineEventHandler(async (event) => {
32
+ const appConfig = useAppConfig() as { duxt?: Partial<DuxtConfig> };
33
+ // Resolved here because Nitro has no i18n: without it the description is
34
+ // printed as the translation key it is.
35
+ const duxt = resolveServerTexts(
36
+ mergeDuxtConfig(appConfig.duxt, duxtDefaults)
37
+ );
38
+
39
+ const origin = getRequestURL(event).origin;
40
+ const feed = duxt.feed;
41
+ const title = typeof feed?.title === 'string' ? feed.title : undefined;
42
+
43
+ const items: {
44
+ path: string;
45
+ title: string;
46
+ description?: string;
47
+ date?: string;
48
+ }[] = [];
49
+
50
+ if (feed?.path) {
51
+ const collections = duxt.resolvedSources?.length
52
+ ? duxt.resolvedSources
53
+ // One version of a changelog, not four. The default version is the
54
+ // one a feed reader wants; the others repeat every entry.
55
+ .filter((source) => source.isDefault)
56
+ .map((source) => source.collection)
57
+ : ['docs'];
58
+
59
+ const pages = (
60
+ await Promise.all(
61
+ collections.map((name) =>
62
+ queryCollection(event, name as Parameters<typeof queryCollection>[1])
63
+ .select('path', 'title', 'description', 'date', 'lastUpdated')
64
+ .all()
65
+ )
66
+ )
67
+ ).flat() as {
68
+ path?: string;
69
+ title?: string;
70
+ description?: string;
71
+ date?: string;
72
+ lastUpdated?: string;
73
+ }[];
74
+
75
+ for (const page of pages) {
76
+ if (!page.path?.startsWith(feed.path)) continue;
77
+ if (page.path === feed.path) continue;
78
+
79
+ items.push({
80
+ path: page.path,
81
+ title: page.title ?? page.path,
82
+ description: page.description,
83
+ date: page.date ?? page.lastUpdated
84
+ });
85
+ }
86
+
87
+ items.sort((a, b) => (b.date ?? '').localeCompare(a.date ?? ''));
88
+ }
89
+
90
+ const body = items
91
+ .map(
92
+ (item) => ` <item>
93
+ <title>${escape(item.title)}</title>
94
+ <link>${escape(origin + item.path)}</link>
95
+ <guid isPermaLink="true">${escape(origin + item.path)}</guid>${
96
+ item.description
97
+ ? `\n <description>${escape(item.description)}</description>`
98
+ : ''
99
+ }${
100
+ item.date
101
+ ? `\n <pubDate>${new Date(item.date).toUTCString()}</pubDate>`
102
+ : ''
103
+ }
104
+ </item>`
105
+ )
106
+ .join('\n');
107
+
108
+ setHeader(event, 'content-type', 'application/rss+xml; charset=utf-8');
109
+
110
+ return `<?xml version="1.0" encoding="UTF-8"?>
111
+ <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
112
+ <channel>
113
+ <title>${escape(title ?? String(duxt.title))}</title>
114
+ <link>${escape(origin)}</link>
115
+ <description>${escape(
116
+ typeof duxt.landing?.description === 'string'
117
+ ? duxt.landing.description
118
+ : 'Documentation.'
119
+ )}</description>
120
+ <atom:link href="${escape(`${origin}/rss.xml`)}" rel="self" type="application/rss+xml" />
121
+ ${body}
122
+ </channel>
123
+ </rss>
124
+ `;
125
+ });
@@ -0,0 +1,46 @@
1
+ import enDefaults from '../../i18n/locales/en/duxt/defaults.json' with { type: 'json' };
2
+ import { resolveDuxtTexts } from '../../app/utils/duxt-text';
3
+
4
+ /**
5
+ * Resolve the config's text fields on the server, where there is no i18n.
6
+ *
7
+ * `llms.txt` and the feed are Nitro routes: no Vue app, no `useI18n`, and so no
8
+ * translator. Before this, both printed the KEY — a feed whose description was
9
+ * the dotted path itself, and an llms.txt that told a model the same. Falling
10
+ * back to the layer's English messages is the honest answer: it
11
+ * is what `fallbackLocale` already says a missing translation resolves to, and
12
+ * these routes have no locale of their own to serve anyway.
13
+ *
14
+ * Only the layer's own defaults are looked up. A consumer's keys live in the
15
+ * consumer's locale files, which Nitro has no reader for — those pass through
16
+ * as written, exactly as an unregistered key does in the browser.
17
+ */
18
+ const messages = enDefaults as Record<string, unknown>;
19
+
20
+ function lookup(key: string): string | undefined {
21
+ let node: unknown = messages;
22
+
23
+ for (const part of key.split('.')) {
24
+ if (!node || typeof node !== 'object') return undefined;
25
+ node = (node as Record<string, unknown>)[part];
26
+ }
27
+
28
+ return typeof node === 'string' ? node : undefined;
29
+ }
30
+
31
+ export function resolveServerTexts<T>(config: T): T {
32
+ return resolveDuxtTexts(config, 'en-GB', lookup);
33
+ }
34
+
35
+ /**
36
+ * The Markdown body without its frontmatter block.
37
+ *
38
+ * Content's `rawbody` is the file as it sits on disk, frontmatter included. A
39
+ * reader wants the prose; a model handed `---\ntitle: …\n---` reads a page
40
+ * whose first heading is a YAML fence.
41
+ */
42
+ export function stripFrontmatter(body: string): string {
43
+ const match = /^---\r?\n[\s\S]*?\r?\n---\r?\n?/.exec(body);
44
+
45
+ return match ? body.slice(match[0].length) : body;
46
+ }
package/sources-git.ts ADDED
@@ -0,0 +1,113 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import type { DuxtSource } from './sources-resolve';
3
+ import { isLatestRef, newestTag, repoUrl } from './sources-resolve';
4
+
5
+ /**
6
+ * Resolve the `latest` shorthand into the tag it means.
7
+ *
8
+ * Node-only, and separate from `sources-resolve.ts` for the same reason
9
+ * `sources.ts` is: that file is read by the browser half of the layer, and
10
+ * `node:child_process` cannot be bundled for it.
11
+ *
12
+ * Both halves of the build must agree on the answer — `sources.ts` declares the
13
+ * collections, `modules/config.ts` resolves the manifest the theme reads — so
14
+ * the answer is cached per repository for the life of the process. Two calls to
15
+ * `git ls-remote` a second apart could otherwise straddle a release and leave
16
+ * the site with a collection no route points at.
17
+ */
18
+ const cache = new Map<string, string[]>();
19
+
20
+ /**
21
+ * What a repository URL is allowed to look like before it is handed to `git`.
22
+ *
23
+ * An allowlist rather than a check for a leading dash, because the argument
24
+ * reaches a command: `git ls-remote --upload-pack=<anything>` runs that
25
+ * anything, and every value that is not a URL is easier to reject than to
26
+ * reason about. One quantifier over one character class, so the test itself
27
+ * cannot be the next finding.
28
+ */
29
+ const REMOTE_URL = /^(?:https?:\/\/|ssh:\/\/|git@)[\w.~:/?#@!$&'()*+,;=%-]+$/;
30
+
31
+ /** The tags of a remote, or nothing when its URL is not one we will run. */
32
+ function remoteTags(repo: string): string {
33
+ const url = repoUrl(repo);
34
+
35
+ if (!REMOTE_URL.test(url)) {
36
+ throw new Error(`duxt: refusing to read tags from ${JSON.stringify(url)}`);
37
+ }
38
+
39
+ return execFileSync(
40
+ 'git',
41
+ // `--end-of-options` so a URL that survived the test above is still read as
42
+ // a URL and never as an option.
43
+ ['ls-remote', '--tags', '--refs', '--end-of-options', url],
44
+ { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }
45
+ );
46
+ }
47
+
48
+ function tagsOf(repo: string | undefined): string[] {
49
+ const key = repo ?? '.';
50
+ const cached = cache.get(key);
51
+ if (cached) return cached;
52
+
53
+ let tags: string[] = [];
54
+
55
+ try {
56
+ const output = repo
57
+ ? remoteTags(repo)
58
+ : execFileSync('git', ['tag', '--list'], {
59
+ encoding: 'utf8',
60
+ stdio: ['ignore', 'pipe', 'ignore']
61
+ });
62
+
63
+ tags = output
64
+ .split('\n')
65
+ .map((line) => line.trim().split(/\s+/).pop() ?? '')
66
+ .map((ref) => ref.replace(/^refs\/tags\//, ''))
67
+ .filter(Boolean);
68
+ } catch {
69
+ // Reported by the caller, which knows which source asked.
70
+ tags = [];
71
+ }
72
+
73
+ cache.set(key, tags);
74
+ return tags;
75
+ }
76
+
77
+ /**
78
+ * The source list with every `latest` replaced by a concrete tag.
79
+ *
80
+ * Called before `resolveSources` by both build-time entry points, so the
81
+ * resolver itself stays pure and testable — it never learns that git exists.
82
+ */
83
+ export function resolveLatestRefs(sources: DuxtSource[]): DuxtSource[] {
84
+ return sources.map((source) => {
85
+ if (!source.refs?.some(isLatestRef)) return source;
86
+
87
+ const newest = newestTag(tagsOf(source.repo));
88
+
89
+ if (!newest) {
90
+ throw new Error(
91
+ `duxt: refs: ['latest'] on ${source.repo ?? 'this repository'} found ` +
92
+ 'no tags to choose from. Name a tag explicitly, or drop the entry.'
93
+ );
94
+ }
95
+
96
+ return {
97
+ ...source,
98
+ refs: source.refs.map((ref) =>
99
+ isLatestRef(ref)
100
+ ? {
101
+ tag: newest,
102
+ // The URL keeps saying `latest`, so a bookmark survives the next
103
+ // release; only the ref underneath moves. `label` is what the
104
+ // switcher and the prefix are built from.
105
+ label:
106
+ typeof ref === 'object' ? (ref.label ?? 'latest') : 'latest',
107
+ status: typeof ref === 'object' ? ref.status : undefined
108
+ }
109
+ : ref
110
+ )
111
+ };
112
+ });
113
+ }