@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,365 @@
1
+ <script setup lang="ts">
2
+ import type { DuxtOpenApiSchema } from '../../openapi-model';
3
+
4
+ /**
5
+ * One schema, drawn as the tree it is — and recursive, because schemas are.
6
+ *
7
+ * The three things that make this more than an `<li>` per property:
8
+ *
9
+ * - **A `$ref` keeps its name.** The parser followed the reference and kept
10
+ * what it was followed through, so `Pet` is shown as `Pet` AND expanded. A
11
+ * reference drawn only as its expansion loses the vocabulary the API's own
12
+ * documentation uses everywhere else.
13
+ * - **A cycle stops.** `Pet.friends: Pet[]` is ordinary, and the parser marked
14
+ * the second `Pet` as circular rather than expanding it; this draws that as
15
+ * the reference it is instead of recursing until the browser gives out.
16
+ * - **Composition is drawn as composition.** `oneOf` and `anyOf` are branches a
17
+ * reader has to choose between, so they are labelled and nested rather than
18
+ * flattened into one list of properties that no single response ever has.
19
+ *
20
+ * `DEPTH` is a floor under all of that: a deeply self-referential document
21
+ * would otherwise render until the tab stops responding, and a truncated tree
22
+ * that says it is truncated is the honest answer.
23
+ */
24
+ const props = withDefaults(
25
+ defineProps<{
26
+ schema?: DuxtOpenApiSchema;
27
+ /** The property name this schema sits under, when it has one. */
28
+ name?: string;
29
+ required?: boolean;
30
+ /** Which way the body this schema describes travels — see `excluded`. */
31
+ direction: DuxtOpenApiDirection;
32
+ depth?: number;
33
+ }>(),
34
+ { depth: 0 }
35
+ );
36
+
37
+ const DEPTH = 8;
38
+
39
+ const schema = computed(() => props.schema);
40
+ const deep = computed(() => props.depth >= DEPTH);
41
+
42
+ const type = computed(() => openApiTypeLabel(schema.value));
43
+ const constraints = computed(() => openApiConstraints(schema.value));
44
+
45
+ const branches = computed(() =>
46
+ (
47
+ [
48
+ ['oneOf', schema.value?.oneOf],
49
+ ['anyOf', schema.value?.anyOf],
50
+ ['allOf', schema.value?.allOf]
51
+ ] as const
52
+ ).filter(([, list]) => list?.length)
53
+ );
54
+
55
+ /** The array's element schema, drawn under the array rather than beside it. */
56
+ const items = computed(() =>
57
+ schema.value?.types?.includes('array') || schema.value?.items
58
+ ? schema.value?.items
59
+ : undefined
60
+ );
61
+
62
+ // `true` never reaches here: the parser turns "any further property is
63
+ // allowed" into an empty schema, so the only two answers left are a schema
64
+ // that constrains them and `false`, which forbids them outright.
65
+ const additional = computed(() => {
66
+ const value = schema.value?.additionalProperties;
67
+
68
+ return value === false || value === undefined ? undefined : value;
69
+ });
70
+
71
+ const nested = computed(
72
+ () =>
73
+ Boolean(schema.value?.properties?.length) ||
74
+ Boolean(branches.value.length) ||
75
+ Boolean(items.value) ||
76
+ Boolean(additional.value) ||
77
+ Boolean(schema.value?.not)
78
+ );
79
+
80
+ const { t } = useI18n();
81
+
82
+ /**
83
+ * Type, format, constraints and flags as ONE grey run, `·` between them.
84
+ *
85
+ * They were a line of chips under the name, and a field cost two or three
86
+ * lines: name and type, a red "required", then two boxes saying `min length 1`
87
+ * and `max length 120`. An object with eight fields filled a screen with
88
+ * twenty-four lines of furniture around eight facts. Set as one run —
89
+ * `string · min 1 · max 120` — a field is a line, which is what it is.
90
+ *
91
+ * The enum stays in the run as alternatives (`round | square | other`) rather
92
+ * than as one chip per value: they are one fact about the field, not five.
93
+ */
94
+ const meta = computed(() => {
95
+ const parts: string[] = [type.value];
96
+
97
+ if (schema.value?.name) parts.push(schema.value.name);
98
+
99
+ for (const constraint of constraints.value) {
100
+ const label = t(`duxt.openapi.constraints.${constraint.key}`);
101
+
102
+ parts.push(
103
+ constraint.value === 'true' ? label : `${label} ${constraint.value}`
104
+ );
105
+ }
106
+
107
+ const options = schema.value?.enum ?? [];
108
+ if (options.length) parts.push(options.map(openApiJson).join(' | '));
109
+
110
+ if (schema.value?.readOnly) parts.push(t('duxt.openapi.readOnly'));
111
+ if (schema.value?.writeOnly) parts.push(t('duxt.openapi.writeOnly'));
112
+ if (schema.value?.deprecated) parts.push(t('duxt.openapi.deprecated'));
113
+
114
+ return parts.filter(Boolean);
115
+ });
116
+
117
+ /**
118
+ * How many fields lie behind this row — the number the chip shows, and the
119
+ * number the open-by-default rule reads.
120
+ *
121
+ * Through an ARRAY, because `items: Widget[]` is a row a reader opens to see a
122
+ * widget: the array itself has no properties and the seven behind it are what
123
+ * the click is worth.
124
+ */
125
+ const size = computed(() => {
126
+ const inner = items.value ?? schema.value;
127
+
128
+ if (inner?.properties?.length) return inner.properties.length;
129
+ if (branches.value.length) {
130
+ return branches.value.reduce(
131
+ (all, [, list]) => all + (list?.length ?? 0),
132
+ 0
133
+ );
134
+ }
135
+
136
+ return nested.value ? 1 : 0;
137
+ });
138
+
139
+ /**
140
+ * ONE THRESHOLD FOR TWO RULES: five fields is where a row starts closed, and
141
+ * five is where the count is worth printing. Below it the chip would say
142
+ * something nobody weighed a decision on ("1"), and the row would hide a line
143
+ * and a half.
144
+ */
145
+ const MANY = 5;
146
+
147
+ /**
148
+ * A row can only close if it HAS a row: the media type's own schema, an array's
149
+ * item and a branch of a `oneOf` arrive without a name, so there is nothing to
150
+ * click and they are always drawn open.
151
+ */
152
+ const collapsible = computed(
153
+ () =>
154
+ Boolean(props.name) &&
155
+ nested.value &&
156
+ !deep.value &&
157
+ !schema.value?.circular
158
+ );
159
+
160
+ const open = computed(() => size.value < MANY);
161
+ </script>
162
+
163
+ <template>
164
+ <!-- `details` only where there is a name to click: everything else is drawn
165
+ open, because a summary nobody can aim at is a summary nobody can open.
166
+ The TAG varies, the row does not — one block of markup either way, so a
167
+ collapsed and an expanded field cannot drift apart. -->
168
+ <component
169
+ :is="collapsible ? 'details' : 'div'"
170
+ :open="collapsible ? open : undefined"
171
+ class="min-w-0"
172
+ >
173
+ <component
174
+ :is="collapsible ? 'summary' : 'div'"
175
+ :class="collapsible ? 'duxt-schema-row' : ''"
176
+ >
177
+ <span class="flex flex-wrap items-baseline gap-x-2 gap-y-1">
178
+ <!-- The mark is lucide's own `plus` and `minus`, one shown per state.
179
+ It was two pseudo-elements before, and at 16 pixels the percentage
180
+ insets that positioned them rounded to different thicknesses — a
181
+ cross with one heavy stroke. An icon set that already draws this
182
+ pair with round caps and one stroke width draws it better than an
183
+ arithmetic of insets ever will.
184
+
185
+ The TILE around it is what says "control" while nothing is being
186
+ hovered, which a bare glyph in grey never did. -->
187
+ <span v-if="collapsible" aria-hidden="true" class="duxt-schema-tile">
188
+ <Icon name="lucide:plus" class="duxt-schema-plus size-2.5" />
189
+ <Icon name="lucide:minus" class="duxt-schema-minus size-2.5" />
190
+ </span>
191
+
192
+ <code v-if="name" class="font-mono text-sm font-medium text-foreground">
193
+ {{ name }}<!-- `required` FOLLOWS THE DIRECTION. A property may be
194
+ `readOnly` and listed under `required`, which is the ordinary way to
195
+ describe a field the server assigns — and OpenAPI then means it is
196
+ required in the response, never in the request. Marking it required
197
+ on a request body asked the reader to invent an id.
198
+
199
+ A STAR, not the word: on a body with eight required fields, eight
200
+ red words are a page that shouts, and a warning colour that appears
201
+ everywhere warns of nothing. The word survives for a screen reader,
202
+ which cannot see that the star is red. --><span
203
+ v-if="required && !excluded(schema ?? {}, direction)"
204
+ class="font-semibold text-destructive"
205
+ :title="$t('duxt.openapi.required')"
206
+ >*<span class="sr-only">
207
+ {{ $t('duxt.openapi.required') }}</span
208
+ ></span
209
+ >
210
+ </code>
211
+
212
+ <!-- One run, `·` between: see `meta`. -->
213
+ <span class="font-mono text-xs text-muted-foreground">
214
+ <template v-for="(part, index) in meta" :key="index"
215
+ ><span v-if="index" aria-hidden="true" class="px-1 opacity-50"
216
+ >·</span
217
+ >{{ part }}</template
218
+ >
219
+ </span>
220
+
221
+ <!-- Only past the threshold, and it is the SAME threshold that closed
222
+ the row: a chip therefore always means "this is bigger than you
223
+ read in passing" rather than "this opens", which the tile already
224
+ said. -->
225
+ <span
226
+ v-if="collapsible && size >= MANY"
227
+ class="ml-auto rounded-md bg-muted px-1.5 font-mono text-[0.6875rem] text-muted-foreground tabular-nums"
228
+ :aria-label="$t('duxt.openapi.fields', { count: size })"
229
+ >
230
+ {{ size }}
231
+ </span>
232
+ </span>
233
+
234
+ <span v-if="schema?.title" class="mt-1 block text-sm font-medium">
235
+ {{ schema.title }}
236
+ </span>
237
+
238
+ <span
239
+ v-if="schema?.description"
240
+ class="mt-1 block text-sm text-muted-foreground"
241
+ >
242
+ {{ schema.description }}
243
+ </span>
244
+
245
+ <!-- A reference this build could not follow. Said out loud rather than
246
+ drawn as an empty object, which is what it would otherwise look
247
+ like. -->
248
+ <span
249
+ v-if="schema?.external"
250
+ class="mt-1 block text-sm text-muted-foreground"
251
+ >
252
+ {{ $t('duxt.openapi.externalRef') }}
253
+ <code class="font-mono text-xs">{{ schema.ref }}</code>
254
+ </span>
255
+
256
+ <span
257
+ v-else-if="schema?.circular"
258
+ class="mt-1 block text-sm text-muted-foreground"
259
+ >
260
+ {{ $t('duxt.openapi.circular') }}
261
+ </span>
262
+ </component>
263
+
264
+ <p v-if="nested && deep" class="mt-2 text-sm text-muted-foreground">
265
+ {{ $t('duxt.openapi.truncated') }}
266
+ </p>
267
+
268
+ <template v-else-if="!schema?.circular">
269
+ <ul
270
+ v-if="schema?.properties?.length"
271
+ class="mt-3 space-y-3 border-l pl-4"
272
+ >
273
+ <li v-for="property in schema.properties" :key="property.name">
274
+ <DuxtOpenApiSchema
275
+ :schema="property.schema"
276
+ :name="property.name"
277
+ :required="property.required"
278
+ :direction="direction"
279
+ :depth="depth + 1"
280
+ />
281
+ </li>
282
+ </ul>
283
+
284
+ <div v-if="items" class="mt-3 border-l pl-4">
285
+ <p class="mb-1 text-xs font-medium text-muted-foreground">
286
+ {{ $t('duxt.openapi.items') }}
287
+ </p>
288
+ <DuxtOpenApiSchema
289
+ :schema="items"
290
+ :direction="direction"
291
+ :depth="depth + 1"
292
+ />
293
+ </div>
294
+
295
+ <div v-if="additional" class="mt-3 border-l pl-4">
296
+ <p class="mb-1 text-xs font-medium text-muted-foreground">
297
+ {{ $t('duxt.openapi.additionalProperties') }}
298
+ </p>
299
+ <DuxtOpenApiSchema
300
+ :schema="additional"
301
+ :direction="direction"
302
+ :depth="depth + 1"
303
+ />
304
+ </div>
305
+
306
+ <p
307
+ v-else-if="schema?.additionalProperties === false"
308
+ class="mt-2 text-xs text-muted-foreground"
309
+ >
310
+ {{ $t('duxt.openapi.noAdditionalProperties') }}
311
+ </p>
312
+
313
+ <div
314
+ v-for="[kind, list] in branches"
315
+ :key="kind"
316
+ class="mt-3 border-l pl-4"
317
+ >
318
+ <p class="mb-1 text-xs font-medium text-muted-foreground">
319
+ {{ $t(`duxt.openapi.composition.${kind}`) }}
320
+ </p>
321
+ <ul class="space-y-3">
322
+ <li v-for="(branch, index) in list" :key="index">
323
+ <DuxtOpenApiSchema
324
+ :schema="branch"
325
+ :direction="direction"
326
+ :depth="depth + 1"
327
+ />
328
+ </li>
329
+ </ul>
330
+ </div>
331
+
332
+ <div v-if="schema?.not" class="mt-3 border-l pl-4">
333
+ <p class="mb-1 text-xs font-medium text-muted-foreground">
334
+ {{ $t('duxt.openapi.composition.not') }}
335
+ </p>
336
+ <DuxtOpenApiSchema
337
+ :schema="schema.not"
338
+ :direction="direction"
339
+ :depth="depth + 1"
340
+ />
341
+ </div>
342
+
343
+ <p v-if="schema?.externalDocs" class="mt-2 text-sm">
344
+ <a
345
+ :href="schema.externalDocs.url"
346
+ rel="noopener noreferrer"
347
+ target="_blank"
348
+ class="text-primary underline underline-offset-4"
349
+ >
350
+ {{ schema.externalDocs.description ?? $t('duxt.openapi.moreInfo') }}
351
+ </a>
352
+ </p>
353
+
354
+ <!-- The discriminator names the property a reader picks a branch by, and
355
+ without it a `oneOf` of ten shapes is a guessing game. -->
356
+ <p
357
+ v-if="schema?.discriminator"
358
+ class="mt-2 text-xs text-muted-foreground"
359
+ >
360
+ {{ $t('duxt.openapi.discriminator') }}
361
+ <code class="font-mono">{{ schema.discriminator.propertyName }}</code>
362
+ </p>
363
+ </template>
364
+ </component>
365
+ </template>
@@ -0,0 +1,115 @@
1
+ <script setup lang="ts">
2
+ import type { DuxtOpenApiSecurity } from '../../openapi-model';
3
+
4
+ /**
5
+ * What a request has to prove before the endpoint answers it.
6
+ *
7
+ * The two levels of `security` mean different things and are drawn as such: the
8
+ * outer list is ALTERNATIVES — any one of them suffices — and every scheme
9
+ * inside one entry is required together. Flattening them into a single list is
10
+ * the mistake that tells a reader to send an API key AND an OAuth token when
11
+ * either would have done.
12
+ *
13
+ * An EMPTY outer list is a statement, not an absence: the operation opted out
14
+ * of the document's own requirement, and saying "no authentication" out loud is
15
+ * the answer a reader came for.
16
+ */
17
+ const props = defineProps<{ security?: DuxtOpenApiSecurity }>();
18
+
19
+ const alternatives = computed(() => props.security ?? []);
20
+ const open = computed(() => props.security?.length === 0);
21
+ </script>
22
+
23
+ <template>
24
+ <section v-if="security" class="mt-8">
25
+ <h2 class="duxt-label">
26
+ {{ $t('duxt.openapi.security') }}
27
+ </h2>
28
+
29
+ <p v-if="open" class="mt-2 text-sm text-muted-foreground">
30
+ {{ $t('duxt.openapi.noAuth') }}
31
+ </p>
32
+
33
+ <!-- Rows a hairline apart, not a card each. A card says "one object" and
34
+ these are alternatives inside one requirement — three cards down a page
35
+ that also boxes its parameters and its responses is a page made of
36
+ frames rather than of text. -->
37
+ <ul v-else class="mt-3 divide-y divide-border/60 border-t border-border/60">
38
+ <li
39
+ v-for="(alternative, index) in alternatives"
40
+ :key="index"
41
+ class="py-3"
42
+ >
43
+ <p
44
+ v-if="alternatives.length > 1"
45
+ class="mb-2 text-xs text-muted-foreground"
46
+ >
47
+ {{ $t('duxt.openapi.anyOfThese') }}
48
+ </p>
49
+
50
+ <ul class="space-y-3">
51
+ <li v-for="requirement in alternative" :key="requirement.key">
52
+ <div class="flex flex-wrap items-baseline gap-2">
53
+ <code class="font-mono text-sm font-medium">
54
+ {{ requirement.key }}
55
+ </code>
56
+ <span class="text-xs text-muted-foreground">
57
+ {{ requirement.scheme?.type }}
58
+ <template v-if="requirement.scheme?.scheme">
59
+ · {{ requirement.scheme.scheme }}
60
+ </template>
61
+ <template v-if="requirement.scheme?.name">
62
+ · {{ requirement.scheme.name }}
63
+ </template>
64
+ <template v-if="requirement.scheme?.in">
65
+ · {{ $t(`duxt.openapi.in.${requirement.scheme.in}`) }}
66
+ </template>
67
+ </span>
68
+ </div>
69
+
70
+ <p
71
+ v-if="requirement.scheme?.description"
72
+ class="mt-1 text-sm text-muted-foreground"
73
+ >
74
+ {{ requirement.scheme.description }}
75
+ </p>
76
+
77
+ <div
78
+ v-if="requirement.scopes?.length"
79
+ class="mt-1.5 flex flex-wrap gap-1.5"
80
+ >
81
+ <span
82
+ v-for="scope in requirement.scopes"
83
+ :key="scope"
84
+ class="rounded bg-muted px-1.5 py-0.5 font-mono text-[0.6875rem]"
85
+ >
86
+ {{ scope }}
87
+ </span>
88
+ </div>
89
+
90
+ <!-- The flows carry the URLs a reader has to visit to get a token
91
+ at all, which is the whole of what an OAuth section is for. -->
92
+ <dl
93
+ v-if="requirement.scheme?.flows?.length"
94
+ class="mt-2 space-y-1 text-xs text-muted-foreground"
95
+ >
96
+ <div
97
+ v-for="flow in requirement.scheme.flows"
98
+ :key="flow.name"
99
+ class="flex flex-wrap gap-x-2"
100
+ >
101
+ <dt class="font-medium">{{ flow.name }}</dt>
102
+ <dd v-if="flow.authorizationUrl" class="font-mono break-all">
103
+ {{ flow.authorizationUrl }}
104
+ </dd>
105
+ <dd v-if="flow.tokenUrl" class="font-mono break-all">
106
+ {{ flow.tokenUrl }}
107
+ </dd>
108
+ </div>
109
+ </dl>
110
+ </li>
111
+ </ul>
112
+ </li>
113
+ </ul>
114
+ </section>
115
+ </template>
@@ -0,0 +1,56 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * "Was this page helpful?"
4
+ *
5
+ * A SLOT WITH AN EVENT AND NO BACKEND, and that is the whole design. The layer
6
+ * stores nothing and sends nothing: it has no business knowing where a
7
+ * consumer's analytics live, and a documentation theme that phones home by
8
+ * default is not one to publish. The answer lives in this component's own state
9
+ * for the length of the visit and nowhere else.
10
+ *
11
+ * A consumer that wants the answer kept listens for it:
12
+ *
13
+ * <DuxtPageFeedback @feedback="(helpful) => track(helpful)" />
14
+ */
15
+ const emit = defineEmits<{ feedback: [helpful: boolean] }>();
16
+
17
+ const answered = ref<boolean | undefined>();
18
+
19
+ // A new page is a new question. Without this the answer given on one page
20
+ // follows the reader to the next.
21
+ const route = useRoute();
22
+ watch(
23
+ () => route.fullPath,
24
+ () => (answered.value = undefined)
25
+ );
26
+
27
+ function answer(helpful: boolean) {
28
+ answered.value = helpful;
29
+ emit('feedback', helpful);
30
+ }
31
+ </script>
32
+
33
+ <template>
34
+ <slot :answered="answered" :answer="answer">
35
+ <div
36
+ class="mt-10 flex flex-wrap items-center gap-3 rounded-lg border px-4 py-3 text-sm"
37
+ >
38
+ <span>{{ $t('duxt.page.helpful.question') }}</span>
39
+
40
+ <template v-if="answered === undefined">
41
+ <UiButton size="sm" variant="outline" @click="answer(true)">
42
+ <Icon name="lucide:thumbs-up" class="size-3.5" />
43
+ {{ $t('duxt.page.helpful.yes') }}
44
+ </UiButton>
45
+ <UiButton size="sm" variant="outline" @click="answer(false)">
46
+ <Icon name="lucide:thumbs-down" class="size-3.5" />
47
+ {{ $t('duxt.page.helpful.no') }}
48
+ </UiButton>
49
+ </template>
50
+
51
+ <span v-else role="status" class="text-muted-foreground">
52
+ {{ $t('duxt.page.helpful.thanks') }}
53
+ </span>
54
+ </div>
55
+ </slot>
56
+ </template>