@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.
- package/LICENSE +21 -0
- package/README.md +151 -0
- package/app/app.config.ts +13 -0
- package/app/app.vue +122 -0
- package/app/assets/css/duxt.css +555 -0
- package/app/assets/css/typeset.css +498 -0
- package/app/components/DuxtBrand.vue +53 -0
- package/app/components/DuxtBreadcrumb.vue +37 -0
- package/app/components/DuxtCodeBlock.vue +143 -0
- package/app/components/DuxtCopyPage.vue +117 -0
- package/app/components/DuxtFooter.vue +86 -0
- package/app/components/DuxtHeader.vue +496 -0
- package/app/components/DuxtJsonEditor.vue +359 -0
- package/app/components/DuxtLandingProse.vue +90 -0
- package/app/components/DuxtLandingShowcase.vue +295 -0
- package/app/components/DuxtLiveWindow.vue +343 -0
- package/app/components/DuxtLocale.vue +86 -0
- package/app/components/DuxtMetaList.vue +76 -0
- package/app/components/DuxtNavigation.vue +94 -0
- package/app/components/DuxtNavigationLink.vue +41 -0
- package/app/components/DuxtOpenApiCallbacks.vue +92 -0
- package/app/components/DuxtOpenApiClient.vue +1339 -0
- package/app/components/DuxtOpenApiMedia.vue +108 -0
- package/app/components/DuxtOpenApiMethod.vue +59 -0
- package/app/components/DuxtOpenApiParameters.vue +114 -0
- package/app/components/DuxtOpenApiResponses.vue +109 -0
- package/app/components/DuxtOpenApiSchema.vue +365 -0
- package/app/components/DuxtOpenApiSecurity.vue +115 -0
- package/app/components/DuxtPageFeedback.vue +56 -0
- package/app/components/DuxtPageInfo.vue +194 -0
- package/app/components/DuxtPageNav.vue +93 -0
- package/app/components/DuxtPreviewSkeleton.vue +262 -0
- package/app/components/DuxtProgress.vue +45 -0
- package/app/components/DuxtSearch.vue +271 -0
- package/app/components/DuxtSections.vue +65 -0
- package/app/components/DuxtShortcuts.vue +46 -0
- package/app/components/DuxtSkipLink.vue +34 -0
- package/app/components/DuxtToc.vue +86 -0
- package/app/components/DuxtTranslationBanner.vue +64 -0
- package/app/components/DuxtVersion.vue +168 -0
- package/app/components/DuxtVersionBanner.vue +109 -0
- package/app/components/OgImage/Duxt.satori.vue +82 -0
- package/app/components/content/Accordion.vue +37 -0
- package/app/components/content/AccordionItem.vue +46 -0
- package/app/components/content/Callout.vue +58 -0
- package/app/components/content/ChangelogGroup.vue +91 -0
- package/app/components/content/ChangelogReleases.vue +520 -0
- package/app/components/content/CodeGroup.vue +183 -0
- package/app/components/content/DevtoolsPanel.vue +107 -0
- package/app/components/content/Field.vue +50 -0
- package/app/components/content/FieldGroup.vue +8 -0
- package/app/components/content/FileTree.vue +92 -0
- package/app/components/content/Mermaid.vue +70 -0
- package/app/components/content/OpenApiOperation.vue +185 -0
- package/app/components/content/OpenApiOperations.vue +72 -0
- package/app/components/content/OpenApiOverview.vue +302 -0
- package/app/components/content/PackageManagers.vue +187 -0
- package/app/components/content/PageCards.vue +48 -0
- package/app/components/content/Partial.vue +65 -0
- package/app/components/content/Preview.vue +173 -0
- package/app/components/content/ProseA.vue +55 -0
- package/app/components/content/ProseH2.vue +53 -0
- package/app/components/content/ProseH3.vue +53 -0
- package/app/components/content/ProseH4.vue +53 -0
- package/app/components/content/ProseImg.vue +87 -0
- package/app/components/content/ProsePre.vue +58 -0
- package/app/components/content/ProseTable.vue +11 -0
- package/app/components/content/Since.vue +21 -0
- package/app/components/content/Steps.vue +20 -0
- package/app/components/content/Tab.vue +23 -0
- package/app/components/content/TabGroup.vue +58 -0
- package/app/components/ui/alert/Alert.vue +21 -0
- package/app/components/ui/alert/AlertDescription.vue +22 -0
- package/app/components/ui/alert/AlertTitle.vue +22 -0
- package/app/components/ui/alert/index.ts +24 -0
- package/app/components/ui/badge/Badge.vue +28 -0
- package/app/components/ui/badge/index.ts +52 -0
- package/app/components/ui/breadcrumb/Breadcrumb.vue +13 -0
- package/app/components/ui/breadcrumb/BreadcrumbEllipsis.vue +22 -0
- package/app/components/ui/breadcrumb/BreadcrumbItem.vue +17 -0
- package/app/components/ui/breadcrumb/BreadcrumbLink.vue +24 -0
- package/app/components/ui/breadcrumb/BreadcrumbList.vue +22 -0
- package/app/components/ui/breadcrumb/BreadcrumbPage.vue +20 -0
- package/app/components/ui/breadcrumb/BreadcrumbSeparator.vue +21 -0
- package/app/components/ui/breadcrumb/index.ts +7 -0
- package/app/components/ui/button/Button.vue +31 -0
- package/app/components/ui/button/index.ts +39 -0
- package/app/components/ui/card/Card.vue +22 -0
- package/app/components/ui/card/CardAction.vue +22 -0
- package/app/components/ui/card/CardContent.vue +14 -0
- package/app/components/ui/card/CardDescription.vue +17 -0
- package/app/components/ui/card/CardFooter.vue +17 -0
- package/app/components/ui/card/CardHeader.vue +22 -0
- package/app/components/ui/card/CardTitle.vue +17 -0
- package/app/components/ui/card/index.ts +7 -0
- package/app/components/ui/collapsible/Collapsible.vue +19 -0
- package/app/components/ui/collapsible/CollapsibleContent.vue +12 -0
- package/app/components/ui/collapsible/CollapsibleTrigger.vue +12 -0
- package/app/components/ui/collapsible/index.ts +3 -0
- package/app/components/ui/command/Command.vue +98 -0
- package/app/components/ui/command/CommandDialog.vue +42 -0
- package/app/components/ui/command/CommandEmpty.vue +31 -0
- package/app/components/ui/command/CommandGroup.vue +52 -0
- package/app/components/ui/command/CommandInput.vue +45 -0
- package/app/components/ui/command/CommandItem.vue +85 -0
- package/app/components/ui/command/CommandList.vue +32 -0
- package/app/components/ui/command/CommandSeparator.vue +23 -0
- package/app/components/ui/command/CommandShortcut.vue +19 -0
- package/app/components/ui/command/index.ts +29 -0
- package/app/components/ui/dialog/Dialog.vue +15 -0
- package/app/components/ui/dialog/DialogClose.vue +12 -0
- package/app/components/ui/dialog/DialogContent.vue +61 -0
- package/app/components/ui/dialog/DialogDescription.vue +25 -0
- package/app/components/ui/dialog/DialogFooter.vue +30 -0
- package/app/components/ui/dialog/DialogHeader.vue +17 -0
- package/app/components/ui/dialog/DialogOverlay.vue +28 -0
- package/app/components/ui/dialog/DialogScrollContent.vue +65 -0
- package/app/components/ui/dialog/DialogTitle.vue +25 -0
- package/app/components/ui/dialog/DialogTrigger.vue +12 -0
- package/app/components/ui/dialog/index.ts +10 -0
- package/app/components/ui/dropdown-menu/DropdownMenu.vue +19 -0
- package/app/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +47 -0
- package/app/components/ui/dropdown-menu/DropdownMenuContent.vue +47 -0
- package/app/components/ui/dropdown-menu/DropdownMenuGroup.vue +12 -0
- package/app/components/ui/dropdown-menu/DropdownMenuItem.vue +41 -0
- package/app/components/ui/dropdown-menu/DropdownMenuLabel.vue +27 -0
- package/app/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
- package/app/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +48 -0
- package/app/components/ui/dropdown-menu/DropdownMenuSeparator.vue +23 -0
- package/app/components/ui/dropdown-menu/DropdownMenuShortcut.vue +19 -0
- package/app/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
- package/app/components/ui/dropdown-menu/DropdownMenuSubContent.vue +34 -0
- package/app/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +34 -0
- package/app/components/ui/dropdown-menu/DropdownMenuTrigger.vue +17 -0
- package/app/components/ui/dropdown-menu/index.ts +16 -0
- package/app/components/ui/input/Input.vue +35 -0
- package/app/components/ui/input/index.ts +1 -0
- package/app/components/ui/navigation-menu/NavigationMenu.vue +42 -0
- package/app/components/ui/navigation-menu/NavigationMenuContent.vue +35 -0
- package/app/components/ui/navigation-menu/NavigationMenuIndicator.vue +32 -0
- package/app/components/ui/navigation-menu/NavigationMenuItem.vue +23 -0
- package/app/components/ui/navigation-menu/NavigationMenuLink.vue +30 -0
- package/app/components/ui/navigation-menu/NavigationMenuList.vue +30 -0
- package/app/components/ui/navigation-menu/NavigationMenuTrigger.vue +31 -0
- package/app/components/ui/navigation-menu/NavigationMenuViewport.vue +30 -0
- package/app/components/ui/navigation-menu/index.ts +14 -0
- package/app/components/ui/scroll-area/ScrollArea.vue +31 -0
- package/app/components/ui/scroll-area/ScrollBar.vue +38 -0
- package/app/components/ui/scroll-area/index.ts +2 -0
- package/app/components/ui/select/Select.vue +15 -0
- package/app/components/ui/select/SelectContent.vue +59 -0
- package/app/components/ui/select/SelectGroup.vue +19 -0
- package/app/components/ui/select/SelectItem.vue +42 -0
- package/app/components/ui/select/SelectItemText.vue +12 -0
- package/app/components/ui/select/SelectLabel.vue +16 -0
- package/app/components/ui/select/SelectScrollDownButton.vue +28 -0
- package/app/components/ui/select/SelectScrollUpButton.vue +28 -0
- package/app/components/ui/select/SelectSeparator.vue +20 -0
- package/app/components/ui/select/SelectTrigger.vue +32 -0
- package/app/components/ui/select/SelectValue.vue +12 -0
- package/app/components/ui/select/index.ts +11 -0
- package/app/components/ui/separator/Separator.vue +30 -0
- package/app/components/ui/separator/index.ts +1 -0
- package/app/components/ui/sheet/Sheet.vue +15 -0
- package/app/components/ui/sheet/SheetClose.vue +12 -0
- package/app/components/ui/sheet/SheetContent.vue +68 -0
- package/app/components/ui/sheet/SheetDescription.vue +23 -0
- package/app/components/ui/sheet/SheetFooter.vue +15 -0
- package/app/components/ui/sheet/SheetHeader.vue +15 -0
- package/app/components/ui/sheet/SheetOverlay.vue +28 -0
- package/app/components/ui/sheet/SheetTitle.vue +23 -0
- package/app/components/ui/sheet/SheetTrigger.vue +12 -0
- package/app/components/ui/sheet/index.ts +8 -0
- package/app/components/ui/sidebar/Sidebar.vue +110 -0
- package/app/components/ui/sidebar/SidebarContent.vue +23 -0
- package/app/components/ui/sidebar/SidebarFooter.vue +18 -0
- package/app/components/ui/sidebar/SidebarGroup.vue +18 -0
- package/app/components/ui/sidebar/SidebarGroupAction.vue +31 -0
- package/app/components/ui/sidebar/SidebarGroupContent.vue +18 -0
- package/app/components/ui/sidebar/SidebarGroupLabel.vue +30 -0
- package/app/components/ui/sidebar/SidebarHeader.vue +18 -0
- package/app/components/ui/sidebar/SidebarInput.vue +19 -0
- package/app/components/ui/sidebar/SidebarInset.vue +23 -0
- package/app/components/ui/sidebar/SidebarMenu.vue +18 -0
- package/app/components/ui/sidebar/SidebarMenuAction.vue +42 -0
- package/app/components/ui/sidebar/SidebarMenuBadge.vue +28 -0
- package/app/components/ui/sidebar/SidebarMenuButton.vue +60 -0
- package/app/components/ui/sidebar/SidebarMenuButtonChild.vue +36 -0
- package/app/components/ui/sidebar/SidebarMenuItem.vue +18 -0
- package/app/components/ui/sidebar/SidebarMenuSkeleton.vue +35 -0
- package/app/components/ui/sidebar/SidebarMenuSub.vue +24 -0
- package/app/components/ui/sidebar/SidebarMenuSubButton.vue +43 -0
- package/app/components/ui/sidebar/SidebarMenuSubItem.vue +18 -0
- package/app/components/ui/sidebar/SidebarProvider.vue +109 -0
- package/app/components/ui/sidebar/SidebarRail.vue +35 -0
- package/app/components/ui/sidebar/SidebarSeparator.vue +19 -0
- package/app/components/ui/sidebar/SidebarTrigger.vue +26 -0
- package/app/components/ui/sidebar/index.ts +62 -0
- package/app/components/ui/sidebar/utils.ts +19 -0
- package/app/components/ui/skeleton/Skeleton.vue +17 -0
- package/app/components/ui/skeleton/index.ts +1 -0
- package/app/components/ui/sonner/Sonner.vue +67 -0
- package/app/components/ui/sonner/index.ts +1 -0
- package/app/components/ui/tabs/Tabs.vue +26 -0
- package/app/components/ui/tabs/TabsContent.vue +23 -0
- package/app/components/ui/tabs/TabsList.vue +28 -0
- package/app/components/ui/tabs/TabsTrigger.vue +30 -0
- package/app/components/ui/tabs/index.ts +4 -0
- package/app/components/ui/textarea/Textarea.vue +32 -0
- package/app/components/ui/textarea/index.ts +1 -0
- package/app/components/ui/tooltip/Tooltip.vue +15 -0
- package/app/components/ui/tooltip/TooltipContent.vue +49 -0
- package/app/components/ui/tooltip/TooltipProvider.vue +14 -0
- package/app/components/ui/tooltip/TooltipTrigger.vue +12 -0
- package/app/components/ui/tooltip/index.ts +4 -0
- package/app/composables/useActiveHeading.ts +90 -0
- package/app/composables/useDuxtAnimatedHeight.ts +155 -0
- package/app/composables/useDuxtBreadcrumb.ts +60 -0
- package/app/composables/useDuxtChoice.ts +28 -0
- package/app/composables/useDuxtCollection.ts +89 -0
- package/app/composables/useDuxtConfig.ts +47 -0
- package/app/composables/useDuxtNavigation.ts +87 -0
- package/app/composables/useDuxtPageFocus.ts +30 -0
- package/app/composables/useDuxtPath.ts +42 -0
- package/app/composables/useDuxtSearch.ts +208 -0
- package/app/composables/useDuxtSection.ts +44 -0
- package/app/composables/useDuxtSectionRow.ts +49 -0
- package/app/composables/useDuxtShortcuts.ts +58 -0
- package/app/composables/useDuxtSiteUrl.ts +27 -0
- package/app/composables/useDuxtToast.ts +25 -0
- package/app/composables/useDuxtVersion.ts +138 -0
- package/app/composables/useFuzzySearch.ts +83 -0
- package/app/composables/usePackageManager.ts +4 -0
- package/app/composables/useRecentPages.ts +52 -0
- package/app/error.vue +133 -0
- package/app/layouts/changelog.vue +85 -0
- package/app/layouts/default.vue +23 -0
- package/app/layouts/docs.vue +62 -0
- package/app/layouts/reference.vue +85 -0
- package/app/lib/utils.ts +7 -0
- package/app/middleware/duxt-section-layout.global.ts +57 -0
- package/app/pages/[...slug].vue +441 -0
- package/app/pages/index.vue +479 -0
- package/app/types/duxt.d.ts +955 -0
- package/app/utils/aside.ts +16 -0
- package/app/utils/changelog.ts +182 -0
- package/app/utils/code-highlight.ts +116 -0
- package/app/utils/duxt-config.ts +185 -0
- package/app/utils/duxt-text.ts +135 -0
- package/app/utils/file-icons.ts +62 -0
- package/app/utils/generated-sections.ts +190 -0
- package/app/utils/generated-toc.ts +216 -0
- package/app/utils/heading-link.ts +32 -0
- package/app/utils/locale-path.ts +45 -0
- package/app/utils/navigation-tree.ts +206 -0
- package/app/utils/nearest-page.ts +72 -0
- package/app/utils/openapi.ts +1028 -0
- package/app/utils/package-command.ts +162 -0
- package/app/utils/request-samples.ts +635 -0
- package/app/utils/section-scope.ts +97 -0
- package/app/utils/sheet-navigation.ts +100 -0
- package/app/utils/source-file.ts +84 -0
- package/app/utils/version-choices.ts +68 -0
- package/app/utils/version-paths.ts +65 -0
- package/bin/duxt-report.mjs +45 -0
- package/components.json +19 -0
- package/content-cache.ts +193 -0
- package/content.config.ts +38 -0
- package/duxt-app-config.ts +124 -0
- package/highlight-langs.ts +68 -0
- package/i18n/i18n.config.ts +16 -0
- package/i18n/locales/de/duxt/changelog.json +17 -0
- package/i18n/locales/de/duxt/code.json +13 -0
- package/i18n/locales/de/duxt/defaults.json +22 -0
- package/i18n/locales/de/duxt/devtools.json +7 -0
- package/i18n/locales/de/duxt/error.json +10 -0
- package/i18n/locales/de/duxt/footer.json +7 -0
- package/i18n/locales/de/duxt/locale.json +7 -0
- package/i18n/locales/de/duxt/nav.json +17 -0
- package/i18n/locales/de/duxt/openapi.json +89 -0
- package/i18n/locales/de/duxt/page.json +34 -0
- package/i18n/locales/de/duxt/search.json +12 -0
- package/i18n/locales/de/duxt/shortcuts.json +11 -0
- package/i18n/locales/de/duxt/theme.json +7 -0
- package/i18n/locales/de/duxt/toc.json +7 -0
- package/i18n/locales/de/duxt/version.json +25 -0
- package/i18n/locales/en/duxt/changelog.json +17 -0
- package/i18n/locales/en/duxt/code.json +13 -0
- package/i18n/locales/en/duxt/defaults.json +22 -0
- package/i18n/locales/en/duxt/devtools.json +7 -0
- package/i18n/locales/en/duxt/error.json +10 -0
- package/i18n/locales/en/duxt/footer.json +7 -0
- package/i18n/locales/en/duxt/locale.json +7 -0
- package/i18n/locales/en/duxt/nav.json +17 -0
- package/i18n/locales/en/duxt/openapi.json +89 -0
- package/i18n/locales/en/duxt/page.json +34 -0
- package/i18n/locales/en/duxt/search.json +12 -0
- package/i18n/locales/en/duxt/shortcuts.json +11 -0
- package/i18n/locales/en/duxt/theme.json +7 -0
- package/i18n/locales/en/duxt/toc.json +7 -0
- package/i18n/locales/en/duxt/version.json +25 -0
- package/i18n/locales/es/duxt/changelog.json +17 -0
- package/i18n/locales/es/duxt/code.json +13 -0
- package/i18n/locales/es/duxt/defaults.json +22 -0
- package/i18n/locales/es/duxt/devtools.json +7 -0
- package/i18n/locales/es/duxt/error.json +10 -0
- package/i18n/locales/es/duxt/footer.json +7 -0
- package/i18n/locales/es/duxt/locale.json +7 -0
- package/i18n/locales/es/duxt/nav.json +17 -0
- package/i18n/locales/es/duxt/openapi.json +89 -0
- package/i18n/locales/es/duxt/page.json +34 -0
- package/i18n/locales/es/duxt/search.json +12 -0
- package/i18n/locales/es/duxt/shortcuts.json +11 -0
- package/i18n/locales/es/duxt/theme.json +7 -0
- package/i18n/locales/es/duxt/toc.json +7 -0
- package/i18n/locales/es/duxt/version.json +25 -0
- package/i18n/locales/fr/duxt/changelog.json +17 -0
- package/i18n/locales/fr/duxt/code.json +13 -0
- package/i18n/locales/fr/duxt/defaults.json +22 -0
- package/i18n/locales/fr/duxt/devtools.json +7 -0
- package/i18n/locales/fr/duxt/error.json +10 -0
- package/i18n/locales/fr/duxt/footer.json +7 -0
- package/i18n/locales/fr/duxt/locale.json +7 -0
- package/i18n/locales/fr/duxt/nav.json +17 -0
- package/i18n/locales/fr/duxt/openapi.json +89 -0
- package/i18n/locales/fr/duxt/page.json +34 -0
- package/i18n/locales/fr/duxt/search.json +12 -0
- package/i18n/locales/fr/duxt/shortcuts.json +11 -0
- package/i18n/locales/fr/duxt/theme.json +7 -0
- package/i18n/locales/fr/duxt/toc.json +7 -0
- package/i18n/locales/fr/duxt/version.json +25 -0
- package/i18n/locales/pt/duxt/changelog.json +17 -0
- package/i18n/locales/pt/duxt/code.json +13 -0
- package/i18n/locales/pt/duxt/defaults.json +22 -0
- package/i18n/locales/pt/duxt/devtools.json +7 -0
- package/i18n/locales/pt/duxt/error.json +10 -0
- package/i18n/locales/pt/duxt/footer.json +7 -0
- package/i18n/locales/pt/duxt/locale.json +7 -0
- package/i18n/locales/pt/duxt/nav.json +17 -0
- package/i18n/locales/pt/duxt/openapi.json +89 -0
- package/i18n/locales/pt/duxt/page.json +34 -0
- package/i18n/locales/pt/duxt/search.json +12 -0
- package/i18n/locales/pt/duxt/shortcuts.json +11 -0
- package/i18n/locales/pt/duxt/theme.json +7 -0
- package/i18n/locales/pt/duxt/toc.json +7 -0
- package/i18n/locales/pt/duxt/version.json +25 -0
- package/i18n/locales/pt-BR/duxt/error.json +8 -0
- package/i18n/locales/pt-BR/duxt/nav.json +10 -0
- package/i18n/locales/pt-BR/duxt/page.json +10 -0
- package/i18n/locales/pt-BR/duxt/search.json +11 -0
- package/i18n/locales/pt-BR/duxt/version.json +13 -0
- package/mdc.config.ts +28 -0
- package/modules/config.ts +440 -0
- package/modules/devtools.ts +126 -0
- package/modules/git-meta.ts +349 -0
- package/modules/redirects.ts +152 -0
- package/modules/validate.ts +137 -0
- package/nuxt.config.ts +530 -0
- package/openapi-model.ts +358 -0
- package/openapi-parse.ts +1052 -0
- package/package.json +161 -0
- package/public/devtools/cache.html +318 -0
- package/public/devtools/checks.html +309 -0
- package/public/devtools/config.html +461 -0
- package/public/devtools/i18n.html +309 -0
- package/public/devtools/pages.html +348 -0
- package/public/devtools/paths.html +315 -0
- package/public/devtools/redirects.html +309 -0
- package/public/devtools/search.html +324 -0
- package/public/devtools/sources.html +309 -0
- package/public/devtools/versions.html +318 -0
- package/report.ts +303 -0
- package/repository-root.ts +26 -0
- package/section-reports.ts +55 -0
- package/sections-changelog.ts +644 -0
- package/sections-openapi.ts +450 -0
- package/sections-resolve.ts +711 -0
- package/sections.ts +157 -0
- package/server/devtools/content.ts +120 -0
- package/server/devtools/context.ts +38 -0
- package/server/devtools/entry-path.ts +30 -0
- package/server/devtools/handler.ts +104 -0
- package/server/devtools/preview.ts +461 -0
- package/server/devtools/render/content.ts +233 -0
- package/server/devtools/render/sources.ts +414 -0
- package/server/devtools/render/system.ts +352 -0
- package/server/devtools/shell.ts +611 -0
- package/server/devtools/sources.ts +122 -0
- package/server/devtools/system.ts +178 -0
- package/server/mcp/tools/list-pages.ts +52 -0
- package/server/mcp/tools/read-page.ts +57 -0
- package/server/mcp/tools/search-docs.ts +74 -0
- package/server/middleware/raw-markdown.ts +86 -0
- package/server/routes/llms-full.txt.get.ts +75 -0
- package/server/routes/llms.txt.get.ts +63 -0
- package/server/routes/rss.xml.get.ts +125 -0
- package/server/utils/duxt-server-text.ts +46 -0
- package/sources-git.ts +113 -0
- package/sources-resolve.ts +908 -0
- package/sources.ts +287 -0
- package/validate-report.ts +494 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = withDefaults(
|
|
3
|
+
defineProps<{
|
|
4
|
+
/** Raw source, used for the copy button and as the body when no slot is given. */
|
|
5
|
+
code?: string;
|
|
6
|
+
language?: string;
|
|
7
|
+
filename?: string;
|
|
8
|
+
/**
|
|
9
|
+
* The block's own controls — the header bar AND the copy button.
|
|
10
|
+
*
|
|
11
|
+
* `false` says a CONTAINER draws them instead: `CodeGroup` puts the file
|
|
12
|
+
* names in a tab bar and the copy button beside them, the way
|
|
13
|
+
* `PackageManagers` does, and a block that kept its own would print the
|
|
14
|
+
* language under the file name and offer a second button for the same
|
|
15
|
+
* text.
|
|
16
|
+
*
|
|
17
|
+
* Both together, deliberately. Switching off only the bar left the copy
|
|
18
|
+
* button in its floating position, where it appears on hover — so a group
|
|
19
|
+
* of fences lost the visible control the same block outside a group has.
|
|
20
|
+
*/
|
|
21
|
+
header?: boolean;
|
|
22
|
+
}>(),
|
|
23
|
+
{ header: true }
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const slots = useSlots();
|
|
27
|
+
|
|
28
|
+
// Content hands ProsePre the highlighted markup in the slot and the raw source
|
|
29
|
+
// in `code`. Rendering `code` when a slot exists throws the highlighting away —
|
|
30
|
+
// which is exactly what happened, and looked like Shiki being switched off.
|
|
31
|
+
const hasBody = computed(() => Boolean(slots.default));
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The other half of that: a block with NO slot never passed through Content at
|
|
35
|
+
* all — it is code this site derived at runtime, an example body off a schema
|
|
36
|
+
* or a response the client just received — and it used to render as flat text
|
|
37
|
+
* beside fences that were coloured, which reads as the highlighter being off
|
|
38
|
+
* for that one box. Highlighted here instead, with the same themes.
|
|
39
|
+
*
|
|
40
|
+
* Skipped where there is a slot, because Content already did it, and where the
|
|
41
|
+
* language is not one this site generates — see `duxtCodeLang`.
|
|
42
|
+
*/
|
|
43
|
+
const { data: highlighted } = await useAsyncData(
|
|
44
|
+
() => `duxt-code-${props.language ?? 'text'}-${props.code ?? ''}`,
|
|
45
|
+
() => {
|
|
46
|
+
const lang = duxtCodeLang(props.language);
|
|
47
|
+
|
|
48
|
+
return !hasBody.value && props.code && lang
|
|
49
|
+
? highlightCode(props.code, lang)
|
|
50
|
+
: // `null`, not `undefined`: Nuxt reads a handler that resolves to
|
|
51
|
+
// nothing as one that failed to return, warns, and repeats the request
|
|
52
|
+
// on the client. Here nothing to highlight is a real answer.
|
|
53
|
+
Promise.resolve(null);
|
|
54
|
+
},
|
|
55
|
+
{ watch: [() => props.code, () => props.language] }
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const icon = computed(() =>
|
|
59
|
+
fileIcon(
|
|
60
|
+
props.filename ?? props.language,
|
|
61
|
+
props.language ? 'lucide:terminal' : 'lucide:file'
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const label = computed(() => props.filename ?? props.language);
|
|
66
|
+
|
|
67
|
+
const copied = ref(false);
|
|
68
|
+
const notify = useDuxtToast();
|
|
69
|
+
const { t } = useI18n();
|
|
70
|
+
const root = useTemplateRef<HTMLElement>('root');
|
|
71
|
+
|
|
72
|
+
async function copy() {
|
|
73
|
+
const text =
|
|
74
|
+
props.code ?? root.value?.querySelector('code')?.textContent ?? '';
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
await navigator.clipboard.writeText(text);
|
|
78
|
+
copied.value = true;
|
|
79
|
+
notify.success(t('duxt.code.copiedToast'));
|
|
80
|
+
setTimeout(() => (copied.value = false), 2000);
|
|
81
|
+
} catch {
|
|
82
|
+
notify.error(
|
|
83
|
+
'Could not copy',
|
|
84
|
+
'The clipboard is unavailable in this context.'
|
|
85
|
+
);
|
|
86
|
+
// Clipboard is unavailable over plain HTTP; a failed copy stays silent.
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<template>
|
|
92
|
+
<div
|
|
93
|
+
class="duxt-code group relative my-6 overflow-hidden rounded-lg border bg-card"
|
|
94
|
+
>
|
|
95
|
+
<div
|
|
96
|
+
v-if="header && label"
|
|
97
|
+
class="duxt-code-header flex min-h-11 items-center gap-2 border-b bg-muted/40 px-3 py-2 text-xs text-muted-foreground"
|
|
98
|
+
>
|
|
99
|
+
<Icon :name="icon" class="size-4 shrink-0" />
|
|
100
|
+
<span class="truncate font-mono">{{ label }}</span>
|
|
101
|
+
|
|
102
|
+
<UiButton
|
|
103
|
+
variant="ghost"
|
|
104
|
+
size="icon"
|
|
105
|
+
class="ml-auto size-7 hover:bg-accent hover:text-foreground"
|
|
106
|
+
:aria-label="copied ? $t('duxt.code.copied') : $t('duxt.code.copy')"
|
|
107
|
+
@click="copy"
|
|
108
|
+
>
|
|
109
|
+
<Icon
|
|
110
|
+
:name="copied ? 'lucide:check' : 'lucide:copy'"
|
|
111
|
+
class="size-3.5"
|
|
112
|
+
/>
|
|
113
|
+
</UiButton>
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<UiButton
|
|
117
|
+
v-else-if="header"
|
|
118
|
+
variant="ghost"
|
|
119
|
+
size="icon"
|
|
120
|
+
class="duxt-code-copy absolute top-2 right-2 size-7 opacity-0 transition-opacity group-hover:opacity-100 hover:bg-accent focus-visible:opacity-100"
|
|
121
|
+
:class="{ 'opacity-100': copied }"
|
|
122
|
+
:aria-label="copied ? $t('duxt.code.copied') : $t('duxt.code.copy')"
|
|
123
|
+
@click="copy"
|
|
124
|
+
>
|
|
125
|
+
<Icon :name="copied ? 'lucide:check' : 'lucide:copy'" class="size-3.5" />
|
|
126
|
+
</UiButton>
|
|
127
|
+
|
|
128
|
+
<div ref="root">
|
|
129
|
+
<slot v-if="hasBody" />
|
|
130
|
+
<!-- eslint-disable-next-line vue/no-v-html -- Shiki's own output, from
|
|
131
|
+
this site's own string; nothing a reader typed reaches it. -->
|
|
132
|
+
<div
|
|
133
|
+
v-else-if="highlighted"
|
|
134
|
+
class="duxt-code-body"
|
|
135
|
+
v-html="highlighted"
|
|
136
|
+
/>
|
|
137
|
+
<pre
|
|
138
|
+
v-else
|
|
139
|
+
class="overflow-x-auto p-4 text-sm"
|
|
140
|
+
><code>{{ code }}</code></pre>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
</template>
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* The top action: hand this page to a model, or read its source.
|
|
4
|
+
*
|
|
5
|
+
* A split control rather than four buttons — the common case is "copy it", and
|
|
6
|
+
* the other three are the same intention through a different door. What all of
|
|
7
|
+
* them hand over is the MARKDOWN, not the rendered page: a model given HTML has
|
|
8
|
+
* to undo a layout to find a heading, and one given the source reads what the
|
|
9
|
+
* author wrote.
|
|
10
|
+
*
|
|
11
|
+
* The external links need an absolute URL, and the origin is read from the
|
|
12
|
+
* browser at click time rather than from config. That is not laziness — it is
|
|
13
|
+
* the only value that is certainly right, including on a preview deployment
|
|
14
|
+
* whose domain nobody wrote down.
|
|
15
|
+
*/
|
|
16
|
+
const props = defineProps<{
|
|
17
|
+
path: string;
|
|
18
|
+
title?: string;
|
|
19
|
+
rawbody?: string;
|
|
20
|
+
}>();
|
|
21
|
+
|
|
22
|
+
const { t } = useI18n();
|
|
23
|
+
const notify = useDuxtToast();
|
|
24
|
+
const localeLink = useDuxtLink();
|
|
25
|
+
|
|
26
|
+
const copied = ref(false);
|
|
27
|
+
|
|
28
|
+
const markdownPath = computed(
|
|
29
|
+
() => `${localeLink(props.path) ?? props.path}.md`
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
/** The prompt both models get: fetch the source, then answer about it. */
|
|
33
|
+
function prompt() {
|
|
34
|
+
const url = `${window.location.origin}${markdownPath.value}`;
|
|
35
|
+
|
|
36
|
+
return t('duxt.page.copy.prompt', { url, title: props.title ?? '' });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function copy() {
|
|
40
|
+
const raw = props.rawbody;
|
|
41
|
+
if (!raw) return;
|
|
42
|
+
|
|
43
|
+
// Without the frontmatter: what is copied should read as the page, not as
|
|
44
|
+
// the file. Same call `llms-full.txt` makes over the same field.
|
|
45
|
+
const text = raw.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, '');
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
await navigator.clipboard.writeText(text);
|
|
49
|
+
copied.value = true;
|
|
50
|
+
setTimeout(() => (copied.value = false), 2000);
|
|
51
|
+
} catch {
|
|
52
|
+
notify.error(t('duxt.page.copyFailed'));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function open(base: string) {
|
|
57
|
+
window.open(
|
|
58
|
+
`${base}${encodeURIComponent(prompt())}`,
|
|
59
|
+
'_blank',
|
|
60
|
+
'noopener,noreferrer'
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<template>
|
|
66
|
+
<div v-if="rawbody" class="flex shrink-0 items-stretch">
|
|
67
|
+
<UiButton
|
|
68
|
+
variant="outline"
|
|
69
|
+
size="sm"
|
|
70
|
+
class="gap-1.5 rounded-r-none border-r-0"
|
|
71
|
+
@click="copy"
|
|
72
|
+
>
|
|
73
|
+
<Icon :name="copied ? 'lucide:check' : 'lucide:copy'" class="size-3.5" />
|
|
74
|
+
{{ copied ? $t('duxt.code.copied') : $t('duxt.page.copy.label') }}
|
|
75
|
+
</UiButton>
|
|
76
|
+
|
|
77
|
+
<UiDropdownMenu>
|
|
78
|
+
<UiDropdownMenuTrigger as-child>
|
|
79
|
+
<UiButton
|
|
80
|
+
variant="outline"
|
|
81
|
+
size="sm"
|
|
82
|
+
class="rounded-l-none px-1.5"
|
|
83
|
+
:aria-label="$t('duxt.page.copy.more')"
|
|
84
|
+
>
|
|
85
|
+
<Icon name="lucide:chevron-down" class="size-3.5 opacity-60" />
|
|
86
|
+
</UiButton>
|
|
87
|
+
</UiDropdownMenuTrigger>
|
|
88
|
+
|
|
89
|
+
<UiDropdownMenuContent align="end" class="w-56">
|
|
90
|
+
<UiDropdownMenuItem as-child>
|
|
91
|
+
<a :href="markdownPath" target="_blank" rel="noopener" class="gap-2">
|
|
92
|
+
<Icon name="lucide:file-code-2" class="size-4" />
|
|
93
|
+
{{ $t('duxt.page.copy.view') }}
|
|
94
|
+
</a>
|
|
95
|
+
</UiDropdownMenuItem>
|
|
96
|
+
|
|
97
|
+
<UiDropdownMenuSeparator />
|
|
98
|
+
|
|
99
|
+
<UiDropdownMenuItem
|
|
100
|
+
class="gap-2"
|
|
101
|
+
@select="open('https://chatgpt.com/?q=')"
|
|
102
|
+
>
|
|
103
|
+
<Icon name="simple-icons:openai" class="size-4" />
|
|
104
|
+
{{ $t('duxt.page.copy.chatgpt') }}
|
|
105
|
+
</UiDropdownMenuItem>
|
|
106
|
+
|
|
107
|
+
<UiDropdownMenuItem
|
|
108
|
+
class="gap-2"
|
|
109
|
+
@select="open('https://claude.ai/new?q=')"
|
|
110
|
+
>
|
|
111
|
+
<Icon name="simple-icons:claude" class="size-4" />
|
|
112
|
+
{{ $t('duxt.page.copy.claude') }}
|
|
113
|
+
</UiDropdownMenuItem>
|
|
114
|
+
</UiDropdownMenuContent>
|
|
115
|
+
</UiDropdownMenu>
|
|
116
|
+
</div>
|
|
117
|
+
</template>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const duxt = useDuxtConfig();
|
|
3
|
+
const localeLink = useDuxtLink();
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The layer's own line, in the middle.
|
|
7
|
+
*
|
|
8
|
+
* Version and repository come from duxt's `package.json`, read at build time —
|
|
9
|
+
* release-please bumps that file, and a second copy of the number is a copy
|
|
10
|
+
* that is wrong from the first release onwards.
|
|
11
|
+
*
|
|
12
|
+
* Switchable, because a layer that cannot be told to stop naming itself is
|
|
13
|
+
* adware. `poweredBy: false` drops it.
|
|
14
|
+
*/
|
|
15
|
+
const poweredBy = computed(() =>
|
|
16
|
+
duxt.poweredBy !== false && duxt.layerVersion
|
|
17
|
+
? { version: duxt.layerVersion, to: duxt.layerRepository }
|
|
18
|
+
: undefined
|
|
19
|
+
);
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<!-- One line, and only what a page footer owes: whose site this is, and the
|
|
24
|
+
links the law asks for. Navigation lives in the header and the sidebar,
|
|
25
|
+
so repeating it down here buys nothing. -->
|
|
26
|
+
<footer class="mt-16 border-t">
|
|
27
|
+
<div
|
|
28
|
+
class="mx-auto flex max-w-[90rem] flex-col gap-3 px-4 py-5 text-sm text-muted-foreground sm:flex-row sm:items-center sm:justify-between lg:px-8"
|
|
29
|
+
>
|
|
30
|
+
<div
|
|
31
|
+
class="flex flex-wrap items-center gap-x-4 gap-y-1 sm:flex-1 sm:basis-0"
|
|
32
|
+
>
|
|
33
|
+
<NuxtLink
|
|
34
|
+
:to="localeLink('/')"
|
|
35
|
+
class="inline-flex items-center gap-2 font-medium text-foreground"
|
|
36
|
+
>
|
|
37
|
+
<DuxtBrand size="sm" />
|
|
38
|
+
</NuxtLink>
|
|
39
|
+
<span v-if="duxt.footer?.copyright">{{ duxt.footer.copyright }}</span>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<!-- The whole phrase is the link, not just the name. It is a bigger
|
|
43
|
+
target for one destination, and in a screen reader's link list
|
|
44
|
+
"Powered by duxt v0.0.0" reads as a sentence where a bare "Powered
|
|
45
|
+
by" beside it would read as nothing at all. -->
|
|
46
|
+
<p v-if="poweredBy" class="sm:flex-1 sm:basis-0 sm:text-center">
|
|
47
|
+
<a
|
|
48
|
+
:href="poweredBy.to"
|
|
49
|
+
target="_blank"
|
|
50
|
+
rel="noopener"
|
|
51
|
+
class="transition-colors hover:text-foreground"
|
|
52
|
+
>
|
|
53
|
+
{{ $t('duxt.footer.poweredBy') }}
|
|
54
|
+
<!-- A real non-breaking space, not a flex gap and not markup
|
|
55
|
+
whitespace. Vue's `condense` deletes a whitespace-only text node
|
|
56
|
+
that contains a newline, which is what left "duxtv0.0.0"; a CSS
|
|
57
|
+
gap puts the space back on screen and nowhere else, so the name
|
|
58
|
+
still copies and reads aloud as one word. Non-breaking because a
|
|
59
|
+
version belongs to the name it follows. -->
|
|
60
|
+
<span class="font-medium text-foreground">duxt</span> <span
|
|
61
|
+
class="font-mono"
|
|
62
|
+
>v{{ poweredBy.version }}</span
|
|
63
|
+
>
|
|
64
|
+
</a>
|
|
65
|
+
</p>
|
|
66
|
+
|
|
67
|
+
<!-- A consumer's legal links belong to the consumer: the layer offers the
|
|
68
|
+
row and ships nothing in it, because an imprint is never the
|
|
69
|
+
template's to claim. -->
|
|
70
|
+
<div
|
|
71
|
+
class="flex flex-wrap items-center gap-x-4 gap-y-1 sm:flex-1 sm:basis-0 sm:justify-end"
|
|
72
|
+
>
|
|
73
|
+
<NuxtLink
|
|
74
|
+
v-for="link in duxt.footer?.legal ?? []"
|
|
75
|
+
:key="link.to"
|
|
76
|
+
:to="localeLink(link.to)"
|
|
77
|
+
:target="link.external ? '_blank' : undefined"
|
|
78
|
+
:rel="link.external ? 'noopener' : undefined"
|
|
79
|
+
class="transition-colors hover:text-foreground"
|
|
80
|
+
>
|
|
81
|
+
{{ link.label }}
|
|
82
|
+
</NuxtLink>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</footer>
|
|
86
|
+
</template>
|