@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,414 @@
1
+ import { reservedSegments, sourcesForRoute } from '../../../sources-resolve';
2
+ import { splitLocalePath } from '../../../app/utils/locale-path';
3
+ import { code, dim, escape, row, stat, stats, table, tag } from '../shell';
4
+
5
+ /**
6
+ * The three panels that answer "what did my `sources` list turn into".
7
+ *
8
+ * They share one idea: the resolver is pure and already tested, so none of this
9
+ * reimplements it — the panels call the same functions the theme calls and
10
+ * print what came back. A panel that computed its own answer would be able to
11
+ * disagree with the site, which is the one thing a debugging view must not do.
12
+ *
13
+ * Data in, HTML out. The queries that produce that data live in
14
+ * `../sources.ts`, and keeping the two apart is what lets the documentation
15
+ * render these very panels from fixtures instead of shipping screenshots.
16
+ */
17
+
18
+ export interface FoundPage {
19
+ path: string;
20
+ title?: string;
21
+ id?: string;
22
+ }
23
+
24
+ /** The sources table — what a consumer wrote, as the site resolved it. */
25
+ export function renderSources(
26
+ sources: DuxtResolvedSource[],
27
+ appConfigFile?: string
28
+ ): string {
29
+ const reserved = reservedSegments(sources);
30
+
31
+ const rows = sources.map((source) =>
32
+ row([
33
+ code(source.prefix || '/'),
34
+ // A generated section is a collection like any other, which is what makes
35
+ // the rest of the layer work on it unchanged — and what made it
36
+ // indistinguishable here from a docs tree whose folder happens to be
37
+ // called CHANGELOG.md. The type is the one thing that tells them apart,
38
+ // so it is said rather than left to be inferred from the Folder column.
39
+ source.generated
40
+ ? `${code(source.collection)} ${tag(source.generated.type)}`
41
+ : code(source.collection),
42
+ source.repositoryUrl
43
+ ? `<a class="file" href="${escape(source.repositoryUrl)}" target="_blank">${escape(source.repository)}</a>`
44
+ : (escape(source.repository) ?? dim('this repository')),
45
+ code(source.path),
46
+ source.ref
47
+ ? `${escape(source.ref)} ${dim(`(${source.refKind})`)}`
48
+ : dim('checkout'),
49
+ `${escape(source.version ?? '—')}${source.isDefault ? ` ${tag('default')}` : ''}`,
50
+ source.status === 'current'
51
+ ? tag('current', 'ok')
52
+ : tag(source.status, source.status === 'eol' ? 'error' : 'warn'),
53
+ (reserved.get(source.collection)
54
+ ? [...reserved.get(source.collection)!]
55
+ : []
56
+ )
57
+ .map((segment) => code(segment))
58
+ .join(' ') || dim('—')
59
+ ])
60
+ );
61
+
62
+ const configured = appConfigFile
63
+ ? `<p class="hint">Configured in ${escape(appConfigFile)}.</p>`
64
+ : '';
65
+
66
+ const repos = new Set(
67
+ sources.map((source) => source.repository ?? 'this repository')
68
+ );
69
+ const generated = sources.filter((source) => source.generated);
70
+ // DISTINCT versions, not entries carrying one. A version is a collection per
71
+ // language and per generated section, so counting rows told a site with two
72
+ // versions in two languages that it had four — and eight once it declared a
73
+ // reference beside them. Keyed with the repository, because two projects may
74
+ // both call a version `v2`.
75
+ const versioned = new Set(
76
+ sources
77
+ .filter((source) => source.version)
78
+ .map((source) => `${repoKey(source)}\u0000${source.version}`)
79
+ );
80
+ const notCurrent = sources.filter((source) => source.status !== 'current');
81
+
82
+ const summary = stats([
83
+ stat(sources.length, sources.length === 1 ? 'collection' : 'collections'),
84
+ stat(repos.size, repos.size === 1 ? 'repository' : 'repositories'),
85
+ stat(versioned.size, 'versions'),
86
+ stat(
87
+ generated.length,
88
+ generated.length === 1 ? 'generated section' : 'generated sections'
89
+ ),
90
+ // Not "the default version": with two repositories there are two defaults,
91
+ // and the figure worth seeing is how many versions carry a warning the
92
+ // reader will meet — deprecated, eol, or a branch still moving.
93
+ stat(notCurrent.length, 'not current', notCurrent.length ? 'warn' : 'ok')
94
+ ]);
95
+
96
+ return `${summary}${table(
97
+ [
98
+ 'Prefix',
99
+ 'Collection',
100
+ 'Repository',
101
+ 'Folder / artefact',
102
+ 'Ref',
103
+ 'Version',
104
+ 'Status',
105
+ 'Reserved segments'
106
+ ],
107
+ rows,
108
+ 'No sources resolved at all — `duxt.sources` is empty or unreadable.'
109
+ )}${configured}`;
110
+ }
111
+
112
+ export interface PathsData {
113
+ /** The URL as the reader pasted it, locale segment and all. */
114
+ input: string;
115
+ locales: string[];
116
+ /** Where the locale chain ends — vue-i18n's own fallback. */
117
+ fallbackLocale?: string | string[];
118
+ sources: DuxtResolvedSource[];
119
+ /** The page the claiming collection holds at that path, if it holds one. */
120
+ found: FoundPage | null;
121
+ /** Every page path the site serves, by collection. */
122
+ byCollection: Map<string, string[]>;
123
+ }
124
+
125
+ /**
126
+ * The path debugger.
127
+ *
128
+ * Every version bug this repo had was a disagreement between what a URL looks
129
+ * like and which source claims it — `/workflows/v0.7.0` 404ing, and
130
+ * `/workflows/v0.7.0/v0.7.0` being generated. Both were arithmetic on prefixes
131
+ * that nothing printed. This prints it.
132
+ */
133
+ export function renderPaths({
134
+ input,
135
+ locales,
136
+ fallbackLocale,
137
+ sources,
138
+ found,
139
+ byCollection
140
+ }: PathsData): string {
141
+ const form = `<form method="get">
142
+ <input type="text" name="path" value="${escape(input)}" placeholder="/workflows/v0.7.0/guides/add-a-body" autofocus>
143
+ <button type="submit">Resolve</button>
144
+ </form>`;
145
+
146
+ if (!input) {
147
+ return `${form}<div class="note">Paste a URL as the browser shows it — locale segment included. The steps below are the ones the theme walks on every request.</div>`;
148
+ }
149
+
150
+ const steps: string[] = [];
151
+
152
+ // 1. The locale segment, which is interface and not content — but which is
153
+ // kept, because it decides WHICH COLLECTION serves the path below.
154
+ const { locale, path: documentationPath } = splitLocalePath(input, locales);
155
+ steps.push(
156
+ documentationPath === input
157
+ ? `No locale segment. Documentation path is ${code(input)}.`
158
+ : `Locale segment stripped: ${code(input)} → ${code(documentationPath)}, language ${code(locale!)}. ${dim('The locale translates the interface, never the content tree — but it does pick the collection.')}`
159
+ );
160
+
161
+ // 2. Which source claims it: longest prefix, then the language. Both at once,
162
+ // because a translation carries the SAME prefix as its original — taking
163
+ // the prefix alone answers with whichever collection sorted first.
164
+ const chain = sourcesForRoute(
165
+ documentationPath,
166
+ locale,
167
+ sources,
168
+ fallbackLocale
169
+ );
170
+ const source = chain[0];
171
+
172
+ if (!source) {
173
+ steps.push(
174
+ `${tag('stops here', 'error')} No source claims this path, and none serves the root. Add a source without a prefix, or check the Sources panel.`
175
+ );
176
+
177
+ return `${form}<ol class="steps">${steps.map((step) => `<li>${step}</li>`).join('')}</ol>`;
178
+ }
179
+
180
+ steps.push(
181
+ `Longest matching prefix is ${code(source.prefix || '/')} → collection ${code(source.collection)}${source.version ? `, version ${code(source.version)}` : ''}${source.locale ? `, language ${code(source.locale)}` : ''}.`
182
+ );
183
+
184
+ // 2b. Where a page missing from that collection goes next. Nothing else
185
+ // shows the chain, and the fallback is the half of translation support
186
+ // that has no visible symptom until a page is silently English.
187
+ if (chain.length > 1) {
188
+ steps.push(
189
+ `Falls back to ${chain
190
+ .slice(1)
191
+ .map((other) => code(other.collection))
192
+ .join(
193
+ ' → '
194
+ )}. ${dim('A page is translated whole or not at all, so this is a chain of collections rather than a merge.')}`
195
+ );
196
+ }
197
+
198
+ // 3. Does that collection hold the page.
199
+ if (found) {
200
+ steps.push(
201
+ `${tag('found', 'ok')} ${escape(found.title ?? documentationPath)} — ${escape(found.id ?? '')}`
202
+ );
203
+ } else {
204
+ steps.push(
205
+ `${tag('stops here', 'error')} Collection ${code(source.collection)} has no page at ${code(documentationPath)}.`
206
+ );
207
+ }
208
+
209
+ const body = `<ol class="steps">${steps.map((step) => `<li>${step}</li>`).join('')}</ol>`;
210
+
211
+ // 4. Whether it exists elsewhere. A page missing from one version and present
212
+ // in another is the fallback's case; a page missing everywhere is a typo.
213
+ const rest = source.prefix
214
+ ? documentationPath.slice(source.prefix.length)
215
+ : documentationPath;
216
+
217
+ // Only versions of the SAME repository: `/duxt/guide` and `/workflows/guide`
218
+ // are two projects that happen to share a folder name, and putting them in
219
+ // one table invents a comparison nobody asked for.
220
+ const siblings = sources.filter(
221
+ (other) =>
222
+ (other.repo ?? other.repository) === (source.repo ?? source.repository)
223
+ );
224
+
225
+ const elsewhere = siblings.map((other) => {
226
+ const candidate = `${other.prefix}${rest}` || '/';
227
+ const has = byCollection.get(other.collection)?.includes(candidate);
228
+
229
+ return row([
230
+ code(other.prefix || '/'),
231
+ escape(other.version ?? '—'),
232
+ // A translation shares its original's prefix and version, so without the
233
+ // language the two are one row printed twice.
234
+ other.locale
235
+ ? `${escape(other.locale)}${other.isDefaultLocale ? ` ${tag('original')}` : ''}`
236
+ : dim('—'),
237
+ code(candidate),
238
+ has ? tag('present', 'ok') : tag('missing', 'muted')
239
+ ]);
240
+ });
241
+
242
+ const near = found
243
+ ? ''
244
+ : `<h2>Nearest paths in ${escape(source.collection)}</h2>${table(
245
+ ['Path'],
246
+ nearest(
247
+ byCollection.get(source.collection) ?? [],
248
+ documentationPath
249
+ ).map((path) => row([code(path)]))
250
+ )}`;
251
+
252
+ return `${form}${body}<h2>The same page in other sources</h2>${table(['Prefix', 'Version', 'Language', 'Would be', 'State'], elsewhere)}${near}`;
253
+ }
254
+
255
+ /** The handful of paths that share the longest leading run with the miss. */
256
+ function nearest(paths: string[], target: string): string[] {
257
+ const score = (path: string) => {
258
+ let index = 0;
259
+ while (index < path.length && path[index] === target[index]) index += 1;
260
+ return index;
261
+ };
262
+
263
+ return [...paths].sort((a, b) => score(b) - score(a)).slice(0, 8);
264
+ }
265
+
266
+ /**
267
+ * Which version — and which language — carries which page.
268
+ *
269
+ * Nothing else shows this. The fallback's whole job is the gap between two
270
+ * columns of this table, and until now the only way to find one was to open a
271
+ * URL and see a 404. A translation falls back exactly the same way, so the
272
+ * missing `de` page is the same question one axis over.
273
+ */
274
+ export function renderVersions(
275
+ sources: DuxtResolvedSource[],
276
+ byCollection: Map<string, string[]>
277
+ ): string {
278
+ // Two groupings, one grid. Versions of different repositories share no paths
279
+ // and would invent gaps that are not gaps — and a locale is that same case
280
+ // one level down: `de` and `en` are two collections of the SAME version, so
281
+ // comparing them as versions drew a matrix of identical columns whose
282
+ // headings were all empty, because a translation carries neither a version
283
+ // nor a prefix of its own. Each axis therefore holds the other fixed.
284
+ //
285
+ // A GENERATED SECTION is the same argument a third time, and the one that
286
+ // reads worst when it is got wrong. A docs page and an endpoint page are
287
+ // never the same page — they share no path — so a grid holding both drew a
288
+ // column per collection rather than per version (`v2 | v1.9 | v2 | v1.9`,
289
+ // with nothing saying which pair was the reference) and filled every
290
+ // cross-quadrant cell with the `·` that means MISSING, for pages that were
291
+ // never meant to be there. Each declaration therefore gets a grid of its own.
292
+ const versions = groupBy(
293
+ sources,
294
+ (source) =>
295
+ `${repoKey(source)}\u0000${source.locale ?? ''}\u0000${sectionKey(source)}`
296
+ );
297
+ const locales = groupBy(
298
+ sources,
299
+ (source) =>
300
+ `${repoKey(source)}\u0000${source.version ?? ''}\u0000${sectionKey(source)}`
301
+ );
302
+
303
+ const sections = [
304
+ ...versions.map((group) =>
305
+ matrix(
306
+ group,
307
+ byCollection,
308
+ (source) =>
309
+ `${escape(source.version || source.ref || source.prefix || '—')}${source.isDefault ? ' *' : ''}`,
310
+ badges(group[0]!, group[0]!.locale),
311
+ '* the version served without a version segment.'
312
+ )
313
+ ),
314
+ ...locales.map((group) =>
315
+ matrix(
316
+ group,
317
+ byCollection,
318
+ (source) =>
319
+ `${escape(source.locale ?? '—')}${source.isDefaultLocale ? ' *' : ''}`,
320
+ badges(group[0]!, group[0]!.version),
321
+ '* the language served from the source path itself, without a folder.'
322
+ )
323
+ )
324
+ ];
325
+
326
+ return (
327
+ sections.join('') ||
328
+ '<div class="note">No source is published at more than one version or in more than one language, so there is no matrix to draw. Add a second entry to <code>refs</code> or to <code>locales</code> to see one.</div>'
329
+ );
330
+ }
331
+
332
+ const repoKey = (source: DuxtResolvedSource) =>
333
+ source.repo ?? source.repository ?? '';
334
+
335
+ /**
336
+ * Which grid a source belongs in: the docs tree, or one named declaration.
337
+ *
338
+ * The DECLARATION rather than the label or the type, because that is the
339
+ * identity `resolveGeneratedSections` recorded for exactly this question — two
340
+ * sections of one repository may share both of the others.
341
+ */
342
+ const sectionKey = (source: DuxtResolvedSource) =>
343
+ source.generated ? String(source.generated.declaration) : '';
344
+
345
+ /** What this grid holds, beside the repository it is named after. */
346
+ const badges = (source: DuxtResolvedSource, held?: string) =>
347
+ `${held ? tag(held, 'muted') : ''}${
348
+ source.generated ? ` ${tag(source.generated.label, 'muted')}` : ''
349
+ }`.trim();
350
+
351
+ /** The groups worth a table: a single column compares nothing. */
352
+ function groupBy(
353
+ sources: DuxtResolvedSource[],
354
+ key: (source: DuxtResolvedSource) => string
355
+ ): DuxtResolvedSource[][] {
356
+ const groups = new Map<string, DuxtResolvedSource[]>();
357
+
358
+ for (const source of sources) {
359
+ const list = groups.get(key(source)) ?? [];
360
+ list.push(source);
361
+ groups.set(key(source), list);
362
+ }
363
+
364
+ return [...groups.values()].filter((group) => group.length > 1);
365
+ }
366
+
367
+ /**
368
+ * One grid: every page of the group down the side, the group's members across.
369
+ *
370
+ * The column heading falls through by truthiness rather than `??`, because
371
+ * `prefix` is an EMPTY STRING for the source served without a segment — `??`
372
+ * keeps it, and the column then has no name at all. That is what the Versions
373
+ * tab showed as a row of bare asterisks.
374
+ */
375
+ function matrix(
376
+ group: DuxtResolvedSource[],
377
+ byCollection: Map<string, string[]>,
378
+ label: (source: DuxtResolvedSource) => string,
379
+ badge: string,
380
+ footnote: string
381
+ ): string {
382
+ const { repo, repository } = group[0]!;
383
+ const logical = new Set<string>();
384
+
385
+ for (const source of group) {
386
+ for (const path of byCollection.get(source.collection) ?? []) {
387
+ logical.add(source.prefix ? path.slice(source.prefix.length) : path);
388
+ }
389
+ }
390
+
391
+ const rows = [...logical].sort().map((path) => {
392
+ const cells = group.map((source) => {
393
+ const has = byCollection
394
+ .get(source.collection)
395
+ ?.includes(`${source.prefix}${path}` || '/');
396
+
397
+ return has ? '<td class="mark yes">✓</td>' : '<td class="mark no">·</td>';
398
+ });
399
+
400
+ return `<tr><td>${code(path || '/')}</td>${cells.join('')}</tr>`;
401
+ });
402
+
403
+ // Through `table()` like every other panel. Built by hand it was the one
404
+ // table in the tab without the scroll container, the border and the column
405
+ // scopes — visibly a different component for no reason.
406
+ // The repository's real name before its URL slug: `acme/sdk` says which
407
+ // project this grid is about, `sdk` only says which segment it took.
408
+ return `<h2>${escape(repository || repo || 'This repository')}${badge ? ` ${badge}` : ''}</h2>${table(
409
+ ['Page', ...group.map(label)],
410
+ rows,
411
+ 'This repository resolved to sources but to no pages at all.',
412
+ 'matrix'
413
+ )}<p class="hint">${escape(footnote)}</p>`;
414
+ }