@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,359 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * A JSON box that knows it is JSON: highlighting, brackets, and the parse error
4
+ * underlined where it is rather than reported after a 400.
5
+ *
6
+ * WHY NOT A TEXTAREA, which is what this was: the request body is the one field
7
+ * in the try-it client a reader types more than a word into, and a textarea
8
+ * says nothing until the server answers. A missing comma is a round trip and a
9
+ * guess; here it is a red squiggle under the character that caused it.
10
+ *
11
+ * WHY NOT MONACO, which is the obvious name: it is an editor for editing files,
12
+ * and it arrives with workers and several megabytes. This layer is a package
13
+ * every consumer site carries, including the ones with no OpenAPI source at
14
+ * all. CodeMirror 6 does the same job for this box at roughly a tenth of it —
15
+ * and it is loaded the way `Mermaid.vue` loads mermaid: on demand, in the
16
+ * browser, never in the bundle a page without it downloads.
17
+ *
18
+ * The TEXTAREA IS STILL HERE, under `<ClientOnly>`'s fallback and after a
19
+ * failed import. The body of a request is not decoration: a reader whose
20
+ * network dropped the chunk, or who has JavaScript half-loaded, still has to be
21
+ * able to type into it.
22
+ */
23
+ import type { EditorView as EditorViewType } from '@codemirror/view';
24
+ import type { DuxtOpenApiKey } from '@duxt/utils/openapi';
25
+
26
+ const model = defineModel<string>({ default: '' });
27
+
28
+ const props = withDefaults(
29
+ defineProps<{
30
+ ariaLabel?: string;
31
+ minHeight?: string;
32
+ /**
33
+ * The keys this document says the body may carry.
34
+ *
35
+ * What turns a JSON box into one that knows the API: the completion list
36
+ * offers them, and the linter marks a required one that is absent and a
37
+ * key the document never described. Empty is a working editor with plain
38
+ * JSON checking and nothing added — which is the honest state for a body
39
+ * whose shape the document does not fix. See `openApiBodyKeys`.
40
+ */
41
+ keys?: DuxtOpenApiKey[];
42
+ }>(),
43
+ { minHeight: '12rem', keys: () => [] }
44
+ );
45
+
46
+ const container = useTemplateRef<HTMLElement>('container');
47
+ const colorMode = useColorMode();
48
+
49
+ /**
50
+ * The keys, read through a ref inside the extensions.
51
+ *
52
+ * A CodeMirror extension is built once and holds whatever it closed over, so
53
+ * reading the prop directly would freeze the schema of whichever media type
54
+ * was selected when the editor mounted. Through the ref, switching the media
55
+ * type above re-lints and re-completes with no rebuild.
56
+ */
57
+ const keysRef = computed(() => props.keys);
58
+
59
+ /** Filled once the editor is up; until then the fallback box is what shows. */
60
+ const ready = ref(false);
61
+ let view: EditorViewType | undefined;
62
+
63
+ /**
64
+ * The palette, taken from the page rather than from a CodeMirror theme.
65
+ *
66
+ * A bundled theme would be a second set of colours beside the one the site
67
+ * already defines, and it would not follow a consumer who redefined a token.
68
+ * `color-mode` swaps the variables underneath, so the editor follows the theme
69
+ * with no second render — which is why there is no light/dark theme here at
70
+ * all, only `dark: …` for the syntax layer's own decision.
71
+ */
72
+ async function mount() {
73
+ if (!import.meta.client || !container.value || view) return;
74
+
75
+ try {
76
+ const [
77
+ { EditorState },
78
+ view_,
79
+ json,
80
+ lint,
81
+ commands,
82
+ language,
83
+ autocomplete,
84
+ { tags }
85
+ ] = await Promise.all([
86
+ import('@codemirror/state'),
87
+ import('@codemirror/view'),
88
+ import('@codemirror/lang-json'),
89
+ import('@codemirror/lint'),
90
+ import('@codemirror/commands'),
91
+ import('@codemirror/language'),
92
+ import('@codemirror/autocomplete'),
93
+ import('@lezer/highlight')
94
+ ]);
95
+
96
+ const { EditorView, keymap, lineNumbers, highlightActiveLine } = view_;
97
+
98
+ const theme = EditorView.theme(
99
+ {
100
+ '&': {
101
+ fontSize: '0.75rem',
102
+ backgroundColor: 'transparent',
103
+ color: 'var(--foreground)'
104
+ },
105
+ '&.cm-focused': { outline: 'none' },
106
+ '.cm-content': {
107
+ fontFamily: 'var(--font-mono, ui-monospace, monospace)',
108
+ padding: '0.75rem 0'
109
+ },
110
+ // CodeMirror's own defaults put the numbers against the border and the
111
+ // text 2px off the gutter. A box a reader types JSON into wants the
112
+ // same breathing room the code blocks on the page have.
113
+ '.cm-line': { padding: '0 0.75rem' },
114
+ '.cm-gutters': {
115
+ backgroundColor: 'transparent',
116
+ color: 'var(--muted-foreground)',
117
+ border: 'none',
118
+ paddingLeft: '0.5rem'
119
+ },
120
+ '.cm-lineNumbers .cm-gutterElement': { paddingRight: '0.5rem' },
121
+ '.cm-activeLine': {
122
+ backgroundColor: 'color-mix(in oklab, var(--muted) 45%, transparent)'
123
+ },
124
+ '.cm-activeLineGutter': { backgroundColor: 'transparent' },
125
+ '.cm-scroller': { overflow: 'auto' },
126
+ '.cm-lintRange-error': {
127
+ textDecoration: 'underline wavy var(--destructive)'
128
+ }
129
+ },
130
+ { dark: colorMode.value === 'dark' }
131
+ );
132
+
133
+ view = new EditorView({
134
+ parent: container.value,
135
+ state: EditorState.create({
136
+ doc: model.value,
137
+ extensions: [
138
+ lineNumbers(),
139
+ highlightActiveLine(),
140
+ language.bracketMatching(),
141
+ language.syntaxHighlighting(
142
+ language.HighlightStyle.define([
143
+ { tag: tags.propertyName, color: 'var(--duxt-cm-key)' },
144
+ { tag: tags.string, color: 'var(--duxt-cm-string)' },
145
+ { tag: tags.number, color: 'var(--duxt-cm-value)' },
146
+ { tag: tags.bool, color: 'var(--duxt-cm-value)' },
147
+ { tag: tags.null, color: 'var(--duxt-cm-value)' },
148
+ { tag: tags.keyword, color: 'var(--duxt-cm-keyword)' },
149
+ { tag: tags.comment, color: 'var(--duxt-cm-comment)' }
150
+ ]),
151
+ { fallback: true }
152
+ ),
153
+ json.json(),
154
+ lint.linter(json.jsonParseLinter()),
155
+
156
+ /**
157
+ * The DOCUMENT's own rules, beside the syntax ones.
158
+ *
159
+ * A second linter rather than one that does both: `jsonParseLinter`
160
+ * answers "is this JSON", this answers "is this the body this
161
+ * endpoint described", and the first has to keep working when the
162
+ * schema says nothing at all. The arithmetic is pure and tested —
163
+ * see `openApiBodyProblems`.
164
+ */
165
+ lint.linter((view) => {
166
+ const text = view.state.doc.toString();
167
+
168
+ return openApiBodyProblems(text, keysRef.value).map((problem) => ({
169
+ from: Math.min(problem.from, text.length),
170
+ to: Math.min(problem.to, text.length),
171
+ severity: problem.severity,
172
+ message: problem.message
173
+ }));
174
+ }),
175
+ lint.lintGutter(),
176
+
177
+ /**
178
+ * The keys the document names, offered WHERE A KEY GOES.
179
+ *
180
+ * Read off the syntax tree rather than off the characters before
181
+ * the cursor, which is what the first attempt did and why it only
182
+ * sometimes worked: matching an open quote fires inside a string
183
+ * VALUE too, so it offered key names where a value goes — and it
184
+ * stayed silent directly after a `{` or a `,`, which is exactly
185
+ * where the next key begins. The tree knows which of the three the
186
+ * cursor is in.
187
+ *
188
+ * A value inside a property whose schema named an `enum` gets that
189
+ * enum instead — a field the document restricted to three words is a
190
+ * field worth being handed those three words.
191
+ */
192
+ autocomplete.autocompletion({
193
+ override: [
194
+ (context) => {
195
+ const keys = keysRef.value;
196
+ if (!keys.length) return null;
197
+
198
+ const tree = language.syntaxTree(context.state);
199
+ const node = tree.resolveInner(context.pos, -1);
200
+
201
+ /**
202
+ * The object the cursor is in, found by WALKING UP.
203
+ *
204
+ * A body being typed is a broken document almost all of the
205
+ * time — a half-written key, no comma yet, no closing brace —
206
+ * and lezer answers with error nodes rather than the tidy
207
+ * `Property` a finished line produces. Asking "is this node a
208
+ * property name" therefore said no exactly while the reader was
209
+ * typing one, which is the whole moment this exists for.
210
+ * Walking up to the nearest object works on the broken document
211
+ * as well as on the finished one.
212
+ */
213
+ let scope = node;
214
+ while (scope.parent && scope.name !== 'Object') {
215
+ scope = scope.parent;
216
+ }
217
+
218
+ if (scope.name !== 'Object') return null;
219
+
220
+ /** Inside a string: its own span is what gets replaced. */
221
+ const inString =
222
+ node.name === 'String' || node.name === 'PropertyName';
223
+ const from = inString ? node.from : context.pos;
224
+ const to = inString ? node.to : context.pos;
225
+
226
+ /**
227
+ * The property this string is the VALUE of, if it is one.
228
+ *
229
+ * Everything else in an object is a key: a finished
230
+ * `PropertyName`, a string with no property around it yet, and
231
+ * the empty spot after `{` or a comma.
232
+ */
233
+ const property =
234
+ node.parent?.name === 'Property' ? node.parent : undefined;
235
+
236
+ const namingKey =
237
+ !property ||
238
+ !property.firstChild ||
239
+ node.from <= property.firstChild.to;
240
+
241
+ if (namingKey) {
242
+ return {
243
+ from,
244
+ to,
245
+ options: keys.map((key) => ({
246
+ label: JSON.stringify(key.name),
247
+ type: 'property',
248
+ detail: key.required
249
+ ? `${key.type} · required`
250
+ : key.type,
251
+ info: key.description
252
+ }))
253
+ };
254
+ }
255
+
256
+ // A value: which property is it the value of?
257
+ if (!inString || !property?.firstChild) return null;
258
+
259
+ const name = context.state.sliceDoc(
260
+ property.firstChild.from,
261
+ property.firstChild.to
262
+ );
263
+
264
+ const options = keys.find(
265
+ (key) => JSON.stringify(key.name) === name
266
+ )?.enum;
267
+
268
+ return options?.length
269
+ ? {
270
+ from,
271
+ to,
272
+ options: options.map((value) => ({
273
+ label: JSON.stringify(value),
274
+ type: 'enum'
275
+ }))
276
+ }
277
+ : null;
278
+ }
279
+ ]
280
+ }),
281
+
282
+ keymap.of([
283
+ ...commands.defaultKeymap,
284
+ ...autocomplete.completionKeymap,
285
+ ...lint.lintKeymap
286
+ ]),
287
+ EditorView.lineWrapping,
288
+ theme,
289
+ EditorView.contentAttributes.of(
290
+ props.ariaLabel ? { 'aria-label': props.ariaLabel } : {}
291
+ ),
292
+ EditorView.updateListener.of((update) => {
293
+ if (update.docChanged) model.value = update.state.doc.toString();
294
+ })
295
+ ]
296
+ })
297
+ });
298
+
299
+ ready.value = true;
300
+ } catch {
301
+ // The chunk did not arrive. The fallback box below is the whole answer:
302
+ // this is an input, and an input that fails to load must still be typable.
303
+ ready.value = false;
304
+ }
305
+ }
306
+
307
+ onMounted(mount);
308
+
309
+ onBeforeUnmount(() => {
310
+ view?.destroy();
311
+ view = undefined;
312
+ });
313
+
314
+ /**
315
+ * A change from OUTSIDE — the form view writing back, or the format button.
316
+ *
317
+ * Guarded against the echo of the editor's own edit: dispatching the document
318
+ * the editor already holds would move the cursor to the end on every keystroke.
319
+ */
320
+ watch(model, (value) => {
321
+ if (!view || value === view.state.doc.toString()) return;
322
+
323
+ view.dispatch({
324
+ changes: { from: 0, to: view.state.doc.length, insert: value }
325
+ });
326
+ });
327
+ </script>
328
+
329
+ <template>
330
+ <div
331
+ class="overflow-hidden rounded-md border border-input bg-transparent shadow-sm focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50"
332
+ >
333
+ <div
334
+ ref="container"
335
+ class="duxt-json-editor"
336
+ :style="{ '--duxt-editor-min-height': minHeight }"
337
+ />
338
+
339
+ <!-- Before the editor is up, and after it failed to arrive. -->
340
+ <UiTextarea
341
+ v-if="!ready"
342
+ v-model="model"
343
+ :aria-label="ariaLabel"
344
+ spellcheck="false"
345
+ class="rounded-none border-0 p-3 font-mono text-xs shadow-none focus-visible:ring-0"
346
+ :style="{ minHeight }"
347
+ />
348
+ </div>
349
+ </template>
350
+
351
+ <style>
352
+ .duxt-json-editor .cm-editor {
353
+ min-height: var(--duxt-editor-min-height);
354
+ }
355
+
356
+ .duxt-json-editor .cm-scroller {
357
+ max-height: 24rem;
358
+ }
359
+ </style>
@@ -0,0 +1,90 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * The words half of a band: eyebrow, heading, paragraph, checked list, link.
4
+ *
5
+ * Extracted because a band may need two of them. A split try-it client is two
6
+ * rows — the form, then the samples — and each row wants its own sentence
7
+ * saying what the reader is looking at; without this they were one block of
8
+ * markup copied twice, which is how the second copy stops matching the first.
9
+ *
10
+ * THE HEADING LEVEL IS A PROP, not a fixed `h2`. The band's own title is the
11
+ * `h2` its `aria-labelledby` points at; a second row inside the same section is
12
+ * a part of it, and an `h2` there would announce a section that does not exist.
13
+ */
14
+ withDefaults(
15
+ defineProps<{
16
+ prose: DuxtResolved<DuxtShowcaseProse>;
17
+ /** The DOM id the band's section is labelled by. Only the `h2` needs one. */
18
+ headingId?: string;
19
+ level?: 2 | 3;
20
+ }>(),
21
+ { level: 2 }
22
+ );
23
+
24
+ const localeLink = useDuxtLink();
25
+ </script>
26
+
27
+ <template>
28
+ <div>
29
+ <p
30
+ v-if="prose.badge"
31
+ class="mb-4 flex items-center gap-2 text-sm font-medium text-primary"
32
+ >
33
+ <span
34
+ v-if="prose.icon"
35
+ class="flex size-7 items-center justify-center rounded-lg border bg-muted/50"
36
+ >
37
+ <Icon :name="prose.icon" class="size-4" />
38
+ </span>
39
+ {{ prose.badge }}
40
+ </p>
41
+
42
+ <component
43
+ :is="`h${level}`"
44
+ :id="headingId"
45
+ class="font-semibold tracking-tight text-balance"
46
+ :class="level === 2 ? 'text-2xl sm:text-3xl' : 'text-xl sm:text-2xl'"
47
+ >
48
+ {{ prose.title }}
49
+ </component>
50
+
51
+ <p
52
+ v-if="prose.description"
53
+ class="mt-4 text-base text-muted-foreground text-pretty"
54
+ >
55
+ {{ prose.description }}
56
+ </p>
57
+
58
+ <ul v-if="prose.bullets?.length" class="mt-6 space-y-3">
59
+ <li
60
+ v-for="bullet in prose.bullets"
61
+ :key="bullet.label"
62
+ class="flex items-start gap-3 text-sm"
63
+ >
64
+ <Icon
65
+ :name="bullet.icon ?? 'lucide:check'"
66
+ class="mt-0.5 size-4 shrink-0 text-primary"
67
+ />
68
+ <span class="text-pretty">{{ bullet.label }}</span>
69
+ </li>
70
+ </ul>
71
+
72
+ <UiButton v-if="prose.action" as-child variant="link" class="mt-6 px-0">
73
+ <NuxtLink
74
+ :to="localeLink(prose.action.to ?? '/')"
75
+ :target="prose.action.external ? '_blank' : undefined"
76
+ :rel="prose.action.external ? 'noopener' : undefined"
77
+ >
78
+ {{ prose.action.label }}
79
+ <Icon
80
+ :name="
81
+ prose.action.external
82
+ ? 'lucide:arrow-up-right'
83
+ : 'lucide:arrow-right'
84
+ "
85
+ class="size-4"
86
+ />
87
+ </NuxtLink>
88
+ </UiButton>
89
+ </div>
90
+ </template>