@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,479 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * The landing page: its own route, full width, no sidebar. A consumer that
4
+ * wants a different one drops an `index.vue` of its own — Nuxt's layer
5
+ * override, no configuration.
6
+ *
7
+ * SIX BANDS, each of which draws nothing when its config is absent: the hero,
8
+ * its numbers, the window, a band per feature, the grid, the closing list. A
9
+ * site that sets only a headline gets a headline and a button, not five empty
10
+ * sections.
11
+ *
12
+ * The middle of that is what the page is for. A grid of cards states four claims
13
+ * in four words each; the bands between the window and the grid take one feature
14
+ * at a time and put the feature ITSELF beside the sentence — a live page of the
15
+ * API reference, the config that produced it. A reader who never leaves this
16
+ * page has still seen the thing work.
17
+ *
18
+ * No closing call to action: the hero's buttons ARE the call, and repeating them
19
+ * at the bottom asks a reader who just arrived to decide twice.
20
+ */
21
+ const duxt = useDuxtConfig();
22
+ const localeLink = useDuxtLink();
23
+ const { t } = useI18n();
24
+ const notify = useDuxtToast();
25
+
26
+ /**
27
+ * Where a hero button goes when the config did not say — the same fallback
28
+ * `index.vue` and `DuxtHeader` use, because the layer cannot know what a
29
+ * consumer called its first page.
30
+ */
31
+ const firstSection = computed(() => duxt.sections?.[0]?.to ?? '/');
32
+ const actionTarget = (action: DuxtResolved<DuxtAction>) =>
33
+ action.to ?? firstSection.value;
34
+
35
+ const landing = computed(() => duxt.landing);
36
+
37
+ /**
38
+ * The install command, highlighted on the SERVER for the reason the
39
+ * package-manager block does it there: Shiki is the single biggest thing that
40
+ * could end up in the client bundle, and a line of shell does not need it
41
+ * twice.
42
+ */
43
+ const command = computed(() => landing.value?.command);
44
+ const { data: highlightedCommand } = await useAsyncData(
45
+ () => `landing-command-${command.value ?? ''}`,
46
+ () =>
47
+ command.value ? highlightCode(command.value, 'bash') : Promise.resolve(''),
48
+ { watch: [command] }
49
+ );
50
+
51
+ const copied = ref(false);
52
+ async function copyCommand() {
53
+ if (!command.value) return;
54
+
55
+ try {
56
+ await navigator.clipboard.writeText(command.value);
57
+ copied.value = true;
58
+ // The icon alone is a 3.5 rem change under the reader's own cursor, which
59
+ // is exactly where they are not looking after a click. The toast is the
60
+ // confirmation; the icon is what stays for the two seconds after it.
61
+ notify.success(t('duxt.code.copiedToast'));
62
+ setTimeout(() => (copied.value = false), 2000);
63
+ } catch {
64
+ notify.error(t('duxt.page.copyFailed'));
65
+ }
66
+ }
67
+
68
+ /**
69
+ * The badge, in either of its two shapes. A string is the label and nothing
70
+ * else; an object may carry an icon, a colour and a link.
71
+ */
72
+ const badge = computed(() => {
73
+ const value = landing.value?.badge as
74
+ | string
75
+ | DuxtResolved<DuxtBadge>
76
+ | undefined;
77
+
78
+ if (!value) return undefined;
79
+
80
+ const resolved = typeof value === 'string' ? { label: value } : value;
81
+
82
+ // `{version}` in the label reads the site's own `version`. A release badge
83
+ // wants the number, and a number typed out here is a second copy of what
84
+ // `version` already holds — wrong from the next release onwards.
85
+ return {
86
+ ...resolved,
87
+ label: String(resolved.label ?? '').replace(
88
+ '{version}',
89
+ String(duxt.version ?? '')
90
+ )
91
+ };
92
+ });
93
+
94
+ /**
95
+ * `<component :is>` needs the COMPONENT, not its name: handed the string
96
+ * `'NuxtLink'` Vue renders an unknown `<NuxtLink>` element, which the browser
97
+ * shows and nobody can click.
98
+ */
99
+ const linkComponent = resolveComponent('NuxtLink');
100
+
101
+ /**
102
+ * The tabs of the big window.
103
+ *
104
+ * `demo` is the tabbed form and wins where it is set; `preview` is the same
105
+ * idea with one page, and is what a site that has already configured
106
+ * `index.vue` still has. Neither: the first section, framed — the window is the
107
+ * one band worth drawing on a claim as thin as "there is a site behind this".
108
+ */
109
+ const demoTabs = computed<DuxtResolved<DuxtDemoTab>[]>(() => {
110
+ const tabs = landing.value?.demo?.tabs;
111
+ if (tabs?.length) return tabs;
112
+
113
+ const preview = landing.value?.preview;
114
+ // A preview pointed at the root would frame this very page, which nests the
115
+ // landing page inside itself.
116
+ const to =
117
+ preview?.to && preview.to !== '/' ? preview.to : firstSection.value;
118
+
119
+ return [{ label: t('duxt.defaults.landing.preview'), to }];
120
+ });
121
+
122
+ const demoHeight = computed(
123
+ () => landing.value?.demo?.height ?? landing.value?.preview?.height
124
+ );
125
+
126
+ /**
127
+ * The screenshot half of `preview`, which only the single-page form has.
128
+ *
129
+ * A poster is a picture of ONE page, so a tab bar cannot carry one: it would be
130
+ * right for the first tab and a lie for the other three. A site that configured
131
+ * `demo` has said it wants the live thing anyway.
132
+ */
133
+ const poster = computed(() =>
134
+ landing.value?.demo?.tabs?.length ? undefined : landing.value?.preview
135
+ );
136
+
137
+ /**
138
+ * The bands, each carrying the ROW it starts at rather than its own position.
139
+ *
140
+ * The sides alternate down the page, and a band decides its side from the
141
+ * number it is handed. A split try-it client draws two rows inside one band, so
142
+ * a count of bands puts every band after it back on the side the row above just
143
+ * used — the alternation stops halfway down the page, which is exactly what it
144
+ * did. Counting rows carries it across.
145
+ */
146
+ const bands = computed(() => {
147
+ let row = 0;
148
+
149
+ return (landing.value?.showcase ?? []).map((showcase) => {
150
+ const at = row;
151
+ row += duxtShowcaseRows(showcase);
152
+
153
+ return { showcase, index: at };
154
+ });
155
+ });
156
+
157
+ useSeoMeta({
158
+ title: duxt.title,
159
+ description: landing.value?.description,
160
+ // The landing page is the site, not an article under it.
161
+ ogType: 'website'
162
+ });
163
+
164
+ defineOgImage('Duxt', {
165
+ title: landing.value?.headline ?? duxt.title,
166
+ description: landing.value?.description,
167
+ site: duxt.title,
168
+ version: duxt.version ?? ''
169
+ });
170
+ </script>
171
+
172
+ <template>
173
+ <div>
174
+ <!-- HERO. Three layers behind the words, all of them `aria-hidden` and
175
+ none of them able to take a click: the grid, two colour washes and a
176
+ fade into the page below. They are a background, not content.
177
+
178
+ The washes are `blur-3xl` circles rather than an image: they are
179
+ right in both themes because they are the theme's own primary colour
180
+ at 20% over the theme's own background, and they cost no request. -->
181
+ <section class="relative isolate overflow-hidden">
182
+ <div
183
+ aria-hidden="true"
184
+ class="pointer-events-none absolute inset-0 -z-10"
185
+ >
186
+ <div
187
+ class="absolute inset-0 bg-[linear-gradient(to_right,var(--color-border)_1px,transparent_1px),linear-gradient(to_bottom,var(--color-border)_1px,transparent_1px)] bg-[size:3rem_3rem] opacity-40 [mask-image:radial-gradient(ellipse_at_center,black,transparent_70%)]"
188
+ />
189
+ <div
190
+ class="absolute -top-40 left-1/2 size-[36rem] -translate-x-1/2 rounded-full bg-primary/20 blur-3xl"
191
+ />
192
+ <div
193
+ class="absolute top-20 -right-32 size-[28rem] rounded-full bg-primary/10 blur-3xl"
194
+ />
195
+ <!-- The bottom edge. Without it the grid stops on a hard line across
196
+ the page, which reads as a section border nobody drew. -->
197
+ <div
198
+ class="absolute inset-x-0 bottom-0 h-32 bg-gradient-to-b from-transparent to-background"
199
+ />
200
+ </div>
201
+
202
+ <div
203
+ class="mx-auto max-w-5xl px-4 pt-24 pb-12 text-center sm:pt-32 sm:pb-16"
204
+ >
205
+ <!-- `as-child` around a link when the badge points somewhere: a pill
206
+ a reader can click has to BE the anchor, not sit inside one, or
207
+ the hover and focus rings belong to two different boxes. -->
208
+ <UiBadge
209
+ v-if="badge"
210
+ :variant="badge.variant ?? 'secondary'"
211
+ class="mb-6"
212
+ :as-child="Boolean(badge.to)"
213
+ >
214
+ <NuxtLink
215
+ v-if="badge.to"
216
+ :to="localeLink(badge.to)"
217
+ :target="badge.external ? '_blank' : undefined"
218
+ :rel="badge.external ? 'noopener' : undefined"
219
+ >
220
+ <Icon v-if="badge.icon" :name="badge.icon" class="size-3" />
221
+ {{ badge.label }}
222
+ </NuxtLink>
223
+
224
+ <template v-else>
225
+ <Icon v-if="badge.icon" :name="badge.icon" class="size-3" />
226
+ {{ badge.label }}
227
+ </template>
228
+ </UiBadge>
229
+
230
+ <h1
231
+ class="text-4xl font-semibold tracking-tight text-balance sm:text-6xl lg:text-7xl"
232
+ >
233
+ {{ landing?.headline ?? duxt.title }}
234
+ </h1>
235
+
236
+ <p
237
+ v-if="landing?.description"
238
+ class="mx-auto mt-6 max-w-2xl text-lg text-muted-foreground text-pretty sm:text-xl"
239
+ >
240
+ {{ landing.description }}
241
+ </p>
242
+
243
+ <div class="mt-10 flex flex-wrap items-center justify-center gap-3">
244
+ <UiButton
245
+ v-for="(action, index) in landing?.actions ?? []"
246
+ :key="index"
247
+ as-child
248
+ size="lg"
249
+ :variant="action.variant ?? 'default'"
250
+ >
251
+ <NuxtLink
252
+ :to="localeLink(actionTarget(action))"
253
+ :target="action.external ? '_blank' : undefined"
254
+ :rel="action.external ? 'noopener' : undefined"
255
+ >
256
+ <Icon v-if="action.icon" :name="action.icon" class="size-4" />
257
+ {{ action.label }}
258
+ </NuxtLink>
259
+ </UiButton>
260
+ </div>
261
+
262
+ <!-- The command, if there is one. A <button> around the whole line
263
+ rather than an icon beside it: the line is not selectable text in
264
+ any useful sense on a phone, and the target should be what the
265
+ reader is looking at. -->
266
+ <div v-if="command" class="mt-8 flex justify-center">
267
+ <button
268
+ type="button"
269
+ class="group flex max-w-full cursor-pointer items-center gap-3 rounded-lg border bg-muted/40 px-4 py-2.5 font-mono text-sm transition-colors hover:bg-muted"
270
+ :aria-label="
271
+ copied ? $t('duxt.code.copied') : $t('duxt.code.copyCommand')
272
+ "
273
+ @click="copyCommand"
274
+ >
275
+ <span aria-hidden="true" class="text-muted-foreground select-none"
276
+ >$</span
277
+ >
278
+ <span
279
+ v-if="highlightedCommand"
280
+ class="min-w-0 overflow-x-auto text-left [&_pre]:bg-transparent!"
281
+ v-html="highlightedCommand"
282
+ />
283
+ <span v-else class="min-w-0 overflow-x-auto text-left">{{
284
+ command
285
+ }}</span>
286
+ <Icon
287
+ :name="copied ? 'lucide:check' : 'lucide:copy'"
288
+ class="size-3.5 shrink-0 text-muted-foreground transition-colors group-hover:text-foreground"
289
+ />
290
+ </button>
291
+ </div>
292
+
293
+ <!-- THE NUMBERS. A <dl>, because that is what a value and the words
294
+ naming it are — and it is what puts "7" and "locales" in one entry
295
+ for a screen reader rather than two adjacent strings.
296
+
297
+ WRAPPED, not gridded. A grid needs its column count written down,
298
+ and the count is the SITE's: three true numbers beat four with a
299
+ filler in the fourth, and the next site along may have two or five.
300
+ A row that wraps and centres is right for all of them;
301
+ `sm:grid-cols-4` was right for exactly one and left a hole
302
+ otherwise. -->
303
+ <dl
304
+ v-if="landing?.stats?.length"
305
+ class="mx-auto mt-14 flex max-w-3xl flex-wrap items-start justify-center gap-x-14 gap-y-8"
306
+ >
307
+ <div
308
+ v-for="stat in landing.stats"
309
+ :key="stat.value"
310
+ class="min-w-28 text-center"
311
+ >
312
+ <dt class="sr-only">{{ stat.label }}</dt>
313
+ <dd>
314
+ <span
315
+ class="block text-2xl font-semibold tracking-tight sm:text-3xl"
316
+ >
317
+ {{ stat.value }}
318
+ </span>
319
+ <span
320
+ aria-hidden="true"
321
+ class="mt-1 flex items-center justify-center gap-1.5 text-xs text-muted-foreground"
322
+ >
323
+ <Icon v-if="stat.icon" :name="stat.icon" class="size-3.5" />
324
+ {{ stat.label }}
325
+ </span>
326
+ </dd>
327
+ </div>
328
+ </dl>
329
+ </div>
330
+ </section>
331
+
332
+ <!-- THE LIVE DEMO. Not a picture of the documentation — the
333
+ documentation, in a frame, operable, with a tab bar over it: the
334
+ reader flips between the guide, the API reference and the changelog
335
+ without leaving this page. -->
336
+ <section
337
+ class="mx-auto max-w-[90rem] px-4 pb-12 sm:pb-16 lg:px-8"
338
+ aria-labelledby="duxt-demo"
339
+ >
340
+ <h2 id="duxt-demo" class="sr-only">
341
+ {{ $t('duxt.defaults.landing.demoTitle') }}
342
+ </h2>
343
+
344
+ <DuxtLiveWindow
345
+ :tabs="demoTabs"
346
+ :height="demoHeight"
347
+ :poster="poster?.src"
348
+ :poster-dark="poster?.srcDark"
349
+ :poster-alt="poster?.alt"
350
+ :live="poster?.live ?? true"
351
+ prefetch
352
+ />
353
+ </section>
354
+
355
+ <!-- THE BANDS. Separated by their own spacing rather than by a rule: a
356
+ line across the page between two halves of one argument cuts the
357
+ argument up. -->
358
+ <DuxtLandingShowcase
359
+ v-for="band in bands"
360
+ :key="band.showcase.title"
361
+ :showcase="band.showcase"
362
+ :index="band.index"
363
+ />
364
+
365
+ <section
366
+ v-if="landing?.features?.length"
367
+ class="mx-auto max-w-[90rem] px-4 py-12 sm:py-16 lg:px-8"
368
+ aria-labelledby="duxt-features"
369
+ >
370
+ <!-- The cards are h3s and the hero above them is the h1: without a
371
+ heading here the document skips a level, which is what a screen
372
+ reader's heading list reads as a missing section. -->
373
+ <h2 id="duxt-features" class="sr-only">
374
+ {{ $t('duxt.defaults.landing.featuresTitle') }}
375
+ </h2>
376
+
377
+ <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
378
+ <!-- A card with a `to` is a LINK, not a card containing one: a reader
379
+ aims at the card, and a hit area that is only the title is a hit
380
+ area that gets missed. -->
381
+ <component
382
+ :is="feature.to ? linkComponent : 'div'"
383
+ v-for="feature in landing.features"
384
+ :key="feature.title"
385
+ :to="feature.to ? localeLink(feature.to) : undefined"
386
+ :target="feature.external ? '_blank' : undefined"
387
+ :rel="feature.external ? 'noopener' : undefined"
388
+ class="group"
389
+ >
390
+ <UiCard
391
+ class="h-full transition-colors"
392
+ :class="
393
+ feature.to
394
+ ? 'group-hover:border-foreground/20 group-hover:bg-muted/30'
395
+ : ''
396
+ "
397
+ >
398
+ <UiCardHeader>
399
+ <span
400
+ v-if="feature.icon"
401
+ class="mb-1 flex size-9 items-center justify-center rounded-lg border bg-muted/50"
402
+ >
403
+ <Icon :name="feature.icon" class="size-4.5 text-primary" />
404
+ </span>
405
+
406
+ <UiCardTitle class="flex items-center gap-1.5 text-base">
407
+ {{ feature.title }}
408
+ <Icon
409
+ v-if="feature.to"
410
+ :name="
411
+ feature.external
412
+ ? 'lucide:arrow-up-right'
413
+ : 'lucide:arrow-right'
414
+ "
415
+ class="size-3.5 text-muted-foreground transition-transform group-hover:translate-x-0.5"
416
+ />
417
+ </UiCardTitle>
418
+
419
+ <UiCardDescription class="text-pretty">
420
+ {{ feature.description }}
421
+ </UiCardDescription>
422
+ </UiCardHeader>
423
+ </UiCard>
424
+ </component>
425
+ </div>
426
+ </section>
427
+
428
+ <!-- THE REST. One line each, no cards and no links: these are real and
429
+ worth naming, and a card apiece would say they matter as much as the
430
+ four above.
431
+
432
+ A <ul>, and the entries are paragraphs rather than headings: this is a
433
+ list of things, not a part of the document with sections under it — and
434
+ where the site names no heading for it, an outline entry per item would
435
+ be six sections a reader cannot navigate to. -->
436
+ <!-- `duxt-flush-footer`: the tint runs into the footer instead of stopping
437
+ four rems above it — see the rule in `duxt.css`. -->
438
+ <section
439
+ v-if="landing?.highlights?.length"
440
+ class="duxt-flush-footer border-t bg-muted/20"
441
+ :aria-labelledby="landing.highlightsTitle ? 'duxt-highlights' : undefined"
442
+ >
443
+ <div class="mx-auto max-w-[90rem] px-4 py-12 sm:py-16 lg:px-8">
444
+ <h2
445
+ v-if="landing.highlightsTitle"
446
+ id="duxt-highlights"
447
+ class="text-center text-2xl font-semibold tracking-tight"
448
+ >
449
+ {{ landing.highlightsTitle }}
450
+ </h2>
451
+
452
+ <ul
453
+ class="grid gap-x-8 gap-y-6 sm:grid-cols-2 lg:grid-cols-3"
454
+ :class="landing.highlightsTitle ? 'mt-10' : ''"
455
+ >
456
+ <li
457
+ v-for="item in landing.highlights"
458
+ :key="item.title"
459
+ class="flex items-start gap-3"
460
+ >
461
+ <Icon
462
+ :name="item.icon ?? 'lucide:check'"
463
+ class="mt-0.5 size-4.5 shrink-0 text-primary"
464
+ />
465
+ <div>
466
+ <p class="text-sm font-medium">{{ item.title }}</p>
467
+ <p
468
+ v-if="item.description"
469
+ class="mt-1 text-sm text-muted-foreground text-pretty"
470
+ >
471
+ {{ item.description }}
472
+ </p>
473
+ </div>
474
+ </li>
475
+ </ul>
476
+ </div>
477
+ </section>
478
+ </div>
479
+ </template>