@lupinum/ginko-docs 0.4.0-rc.9 → 0.4.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/CHANGELOG.md +78 -0
- package/LICENSE +1 -1
- package/README.md +206 -54
- package/app/app.config.ts +42 -55
- package/app/assets/docs.css +555 -0
- package/app/components/DocsBanner.vue +29 -0
- package/app/components/DocsExample.vue +43 -0
- package/app/components/DocsFooter.vue +19 -0
- package/app/components/DocsHeader.vue +112 -0
- package/app/components/DocsLanding.vue +55 -0
- package/app/components/DocsLanguage.vue +29 -0
- package/app/components/DocsNavTree.vue +38 -0
- package/app/components/DocsPage.vue +84 -0
- package/app/components/DocsPageActions.vue +47 -0
- package/app/components/DocsPost.vue +58 -0
- package/app/components/DocsSearch.vue +134 -0
- package/app/components/DocsShell.vue +20 -0
- package/app/components/DocsSidebar.vue +18 -0
- package/app/components/DocsTable.vue +11 -0
- package/app/components/DocsThemeToggle.vue +45 -0
- package/app/components/DocsToc.vue +73 -0
- package/app/composables/useDocs.ts +52 -0
- package/app/composables/useDocsBlog.ts +32 -0
- package/app/composables/useDocsCopy.ts +17 -0
- package/app/composables/useDocsPopover.ts +36 -0
- package/app/composables/useDocsSite.ts +10 -0
- package/app/docs-pages/blog.vue +47 -0
- package/app/docs-pages/changelog.vue +27 -0
- package/app/docs-pages/doc.vue +14 -0
- package/app/docs-pages/docs.vue +9 -0
- package/app/docs-pages/index.vue +12 -0
- package/app/docs-pages/post.vue +8 -0
- package/app/error.vue +23 -115
- package/app/layouts/default.vue +25 -7
- package/app/lib/blogTypes.ts +8 -0
- package/app/lib/docsFirst.ts +11 -0
- package/app/lib/docsInit.ts +18 -0
- package/app/lib/docsNav.ts +36 -0
- package/app/lib/docsPage.ts +44 -0
- package/app/lib/markdownComponents.ts +16 -0
- package/app/lib/previewToc.ts +18 -0
- package/dist/config.d.mts +232 -0
- package/dist/config.d.ts +232 -0
- package/dist/config.mjs +114 -0
- package/dist/pages.d.mts +5 -0
- package/dist/pages.d.ts +5 -0
- package/dist/pages.mjs +36 -0
- package/dist/shared/ginko-docs.BwbF7JBR.mjs +4 -0
- package/i18n/de.json +1 -0
- package/i18n/en.json +1 -0
- package/icons/README.md +2 -0
- package/icons/bluesky.svg +1 -0
- package/icons/claude.svg +1 -0
- package/icons/discord.svg +1 -0
- package/icons/github.svg +1 -0
- package/icons/linkedin.svg +1 -0
- package/icons/mastodon.svg +1 -0
- package/icons/openai.svg +1 -0
- package/icons/x.svg +1 -0
- package/icons/youtube.svg +1 -0
- package/nuxt.config.ts +34 -209
- package/package.json +43 -76
- package/public/_docs/fonts/LICENSE +188 -0
- package/public/_docs/fonts/inter-latin-wght-normal.woff2 +0 -0
- package/public/_docs/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
- package/public/_docs/fonts/jetbrains-mono-latin-500-normal.woff2 +0 -0
- package/server/feeds/blog-locale.get.ts +9 -0
- package/server/feeds/blog.get.ts +4 -0
- package/server/lib/blogFeed.ts +35 -0
- package/server/lib/rss.ts +57 -0
- package/server/mcp/handler.ts +108 -0
- package/server/routes/__ginko/docs-mcp.ts +35 -0
- package/shared/paths.ts +4 -0
- package/app/app.vue +0 -98
- package/app/assets/css/prose.css +0 -3240
- package/app/assets/css/tailwind.css +0 -394
- package/app/assets/css/theme-palettes.css +0 -309
- package/app/assets/css/theme-presets.css +0 -141
- package/app/components/OgImage/GinkoDocs.satori.vue +0 -238
- package/app/components/content/DocumentPageShell.vue +0 -55
- package/app/components/content/Feedback.vue +0 -102
- package/app/components/content/ImageZoomDialog.vue +0 -84
- package/app/components/content/PageMarkdownCopy.vue +0 -104
- package/app/components/content/imageZoom.ts +0 -25
- package/app/components/mdc/MdcAccordion.vue +0 -67
- package/app/components/mdc/MdcAccordionItem.vue +0 -42
- package/app/components/mdc/MdcApi.vue +0 -159
- package/app/components/mdc/MdcAside.vue +0 -23
- package/app/components/mdc/MdcCallout.vue +0 -61
- package/app/components/mdc/MdcCard.vue +0 -175
- package/app/components/mdc/MdcCards.vue +0 -30
- package/app/components/mdc/MdcCenter.vue +0 -71
- package/app/components/mdc/MdcCodeGroup.vue +0 -197
- package/app/components/mdc/MdcCodeTree.vue +0 -234
- package/app/components/mdc/MdcCollapse.vue +0 -61
- package/app/components/mdc/MdcColumn.vue +0 -70
- package/app/components/mdc/MdcDropcap.vue +0 -84
- package/app/components/mdc/MdcError.vue +0 -23
- package/app/components/mdc/MdcExcerpt.vue +0 -26
- package/app/components/mdc/MdcFigure.vue +0 -85
- package/app/components/mdc/MdcFiles.vue +0 -120
- package/app/components/mdc/MdcIdea.vue +0 -17
- package/app/components/mdc/MdcInfo.vue +0 -17
- package/app/components/mdc/MdcInlineToc.vue +0 -51
- package/app/components/mdc/MdcKbd.vue +0 -10
- package/app/components/mdc/MdcLayout.vue +0 -57
- package/app/components/mdc/MdcNote.vue +0 -17
- package/app/components/mdc/MdcQuiz.vue +0 -241
- package/app/components/mdc/MdcQuizQuestion.vue +0 -221
- package/app/components/mdc/MdcReadMore.vue +0 -70
- package/app/components/mdc/MdcSteps.vue +0 -59
- package/app/components/mdc/MdcSuccess.vue +0 -23
- package/app/components/mdc/MdcTab.vue +0 -17
- package/app/components/mdc/MdcTabs.vue +0 -150
- package/app/components/mdc/MdcTimeline.vue +0 -17
- package/app/components/mdc/MdcTimelineItem.vue +0 -40
- package/app/components/mdc/MdcWarning.vue +0 -23
- package/app/components/mdc/api.utils.ts +0 -132
- package/app/components/mdc/code-tree.utils.ts +0 -22
- package/app/components/mdc/icons.ts +0 -10
- package/app/components/mdc/quiz.utils.ts +0 -38
- package/app/components/prose/ProseA.vue +0 -27
- package/app/components/prose/ProseBlockquote.vue +0 -30
- package/app/components/prose/ProseCode.vue +0 -14
- package/app/components/prose/ProseEm.vue +0 -14
- package/app/components/prose/ProseH1.vue +0 -18
- package/app/components/prose/ProseH2.vue +0 -29
- package/app/components/prose/ProseH3.vue +0 -29
- package/app/components/prose/ProseH4.vue +0 -29
- package/app/components/prose/ProseH5.vue +0 -15
- package/app/components/prose/ProseH6.vue +0 -15
- package/app/components/prose/ProseHr.vue +0 -12
- package/app/components/prose/ProseImg.vue +0 -55
- package/app/components/prose/ProseLi.vue +0 -14
- package/app/components/prose/ProseOl.vue +0 -14
- package/app/components/prose/ProseP.vue +0 -14
- package/app/components/prose/ProsePre.vue +0 -180
- package/app/components/prose/ProseStrong.vue +0 -14
- package/app/components/prose/ProseTable.vue +0 -18
- package/app/components/prose/ProseTbody.vue +0 -14
- package/app/components/prose/ProseTd.vue +0 -14
- package/app/components/prose/ProseTh.vue +0 -14
- package/app/components/prose/ProseThead.vue +0 -14
- package/app/components/prose/ProseTr.vue +0 -14
- package/app/components/prose/ProseUl.vue +0 -14
- package/app/components/site/ModeToggle.vue +0 -81
- package/app/components/site/SiteBanner.vue +0 -97
- package/app/components/site/SiteFooter.vue +0 -90
- package/app/components/site/SiteHeader.vue +0 -371
- package/app/components/site/SiteHeroCode.vue +0 -173
- package/app/components/site/SiteInteractionLayer.vue +0 -42
- package/app/components/site/SiteLocaleSwitcher.vue +0 -190
- package/app/components/site/SiteLogoMark.vue +0 -12
- package/app/components/site/SiteSkipLink.vue +0 -14
- package/app/components/site/SiteSocialLinks.vue +0 -33
- package/app/components/site/header-utils.ts +0 -3
- package/app/components/site/mode-toggle.utils.ts +0 -18
- package/app/components/ui/badge/Badge.vue +0 -28
- package/app/components/ui/badge/index.ts +0 -24
- package/app/components/ui/button/Button.vue +0 -31
- package/app/components/ui/button/index.ts +0 -35
- package/app/components/ui/collapsible/Collapsible.vue +0 -15
- package/app/components/ui/collapsible/CollapsibleContent.vue +0 -25
- package/app/components/ui/collapsible/CollapsibleTrigger.vue +0 -12
- package/app/components/ui/collapsible/index.ts +0 -3
- package/app/components/ui/dropdown-menu/DropdownMenu.vue +0 -15
- package/app/components/ui/dropdown-menu/DropdownMenuContent.vue +0 -50
- package/app/components/ui/dropdown-menu/DropdownMenuItem.vue +0 -41
- package/app/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +0 -15
- package/app/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +0 -37
- package/app/components/ui/dropdown-menu/DropdownMenuSeparator.vue +0 -23
- package/app/components/ui/dropdown-menu/DropdownMenuTrigger.vue +0 -14
- package/app/components/ui/dropdown-menu/index.ts +0 -7
- package/app/components/ui/kbd/Kbd.vue +0 -23
- package/app/components/ui/kbd/index.ts +0 -21
- package/app/components/ui/scroll-area/ScrollArea.vue +0 -39
- package/app/components/ui/scroll-area/ScrollBar.vue +0 -33
- package/app/components/ui/scroll-area/index.ts +0 -2
- package/app/components/ui/separator/Separator.vue +0 -27
- package/app/components/ui/separator/index.ts +0 -1
- package/app/components/ui/sheet/Sheet.vue +0 -15
- package/app/components/ui/sheet/SheetContent.vue +0 -59
- package/app/components/ui/sheet/SheetDescription.vue +0 -21
- package/app/components/ui/sheet/SheetOverlay.vue +0 -26
- package/app/components/ui/sheet/SheetTitle.vue +0 -21
- package/app/components/ui/sheet/SheetTrigger.vue +0 -12
- package/app/components/ui/sheet/index.ts +0 -5
- package/app/components/ui/tabs/Tabs.vue +0 -24
- package/app/components/ui/tabs/TabsList.vue +0 -26
- package/app/components/ui/tabs/TabsTrigger.vue +0 -28
- package/app/components/ui/tabs/index.ts +0 -3
- package/app/composables/site-navigation.utils.ts +0 -133
- package/app/composables/useCanonicalUrl.ts +0 -9
- package/app/composables/useContentRouteAlternates.ts +0 -35
- package/app/composables/useGinkoAnalytics.ts +0 -52
- package/app/composables/useGinkoDocsConfig.ts +0 -6
- package/app/composables/useGinkoOgImage.ts +0 -20
- package/app/composables/useLocalizedPath.ts +0 -12
- package/app/composables/useLocalizedRouteSwitch.ts +0 -31
- package/app/composables/useMetaKey.ts +0 -18
- package/app/composables/usePageMarkdownActions.ts +0 -79
- package/app/composables/useProseAppearance.ts +0 -24
- package/app/composables/useSchemaJsonLd.ts +0 -25
- package/app/composables/useSiteNavigation.ts +0 -64
- package/app/config/site.utils.ts +0 -36
- package/app/features/docs/components/DocsBreadcrumb.vue +0 -37
- package/app/features/docs/components/DocsContributeLinks.vue +0 -75
- package/app/features/docs/components/DocsMobileToc.vue +0 -108
- package/app/features/docs/components/DocsPageContent.vue +0 -234
- package/app/features/docs/components/DocsPageNav.vue +0 -57
- package/app/features/docs/components/DocsSidebar.vue +0 -145
- package/app/features/docs/components/DocsSidebarDropdown.vue +0 -70
- package/app/features/docs/components/DocsSidebarItem.vue +0 -122
- package/app/features/docs/components/DocsSidebarList.vue +0 -35
- package/app/features/docs/components/DocsSidebarRow.vue +0 -27
- package/app/features/docs/components/DocsSidebarTabs.vue +0 -59
- package/app/features/docs/components/DocsToc.vue +0 -106
- package/app/features/docs/composables/useDocsNavigation.ts +0 -29
- package/app/features/docs/composables/useDocsNavigationData.ts +0 -18
- package/app/features/docs/composables/useRevealActive.ts +0 -58
- package/app/features/docs/composables/useScrollspy.ts +0 -135
- package/app/features/docs/docs-navigation.ts +0 -157
- package/app/features/docs/toc-context.ts +0 -6
- package/app/features/search/command-center.ts +0 -110
- package/app/features/search/components/SiteCommandCenter.vue +0 -359
- package/app/features/search/components/SiteSearchPageHighlight.vue +0 -126
- package/app/features/search/useCommandCenter.ts +0 -292
- package/app/layouts/blog.vue +0 -15
- package/app/layouts/docs.vue +0 -20
- package/app/lib/errors.ts +0 -37
- package/app/lib/schema-org.ts +0 -38
- package/app/pages/blog/[slug].vue +0 -228
- package/app/pages/blog/index.vue +0 -130
- package/app/pages/docs/[...slug].vue +0 -10
- package/app/pages/docs/index.vue +0 -19
- package/app/pages/index.vue +0 -278
- package/app/plugins/ginko-docs-theme.ts +0 -14
- package/app/plugins/ssr-width.ts +0 -6
- package/app/utils/content.ts +0 -67
- package/app/utils/file-icons.ts +0 -90
- package/app/utils/index.ts +0 -7
- package/app/utils/repository.ts +0 -20
- package/components.ts +0 -9
- package/content-collections.ts +0 -89
- package/content.js +0 -200
- package/content.ts +0 -104
- package/i18n/i18n.config.ts +0 -10
- package/i18n/locales.ts +0 -81
- package/i18n/messages/global/banner.ts +0 -8
- package/i18n/messages/global/blog.ts +0 -18
- package/i18n/messages/global/command.ts +0 -49
- package/i18n/messages/global/docs.ts +0 -36
- package/i18n/messages/global/errors.ts +0 -36
- package/i18n/messages/global/feedback.ts +0 -11
- package/i18n/messages/global/index.ts +0 -21
- package/i18n/messages/global/nav.ts +0 -26
- package/i18n/messages/global/site.ts +0 -4
- package/i18n/messages/global/theme.ts +0 -9
- package/i18n/messages/index.ts +0 -20
- package/i18n/messages/localize.ts +0 -35
- package/i18n/routes.ts +0 -33
- package/icon-bundle.ts +0 -116
- package/index.d.ts +0 -37
- package/modules/analytics-boundary.ts +0 -23
- package/modules/feature-routing.ts +0 -68
- package/modules/syntax-highlighting.ts +0 -120
- package/public/fonts/public-sans/LICENSE +0 -93
- package/public/fonts/public-sans/README.md +0 -12
- package/public/fonts/public-sans/public-sans-400-normal-latin.woff +0 -0
- package/public/fonts/public-sans/public-sans-500-normal-latin.woff +0 -0
- package/public/fonts/public-sans/public-sans-600-normal-latin.woff +0 -0
- package/public/fonts/public-sans/public-sans-700-normal-latin.woff +0 -0
- package/runtime/generate-favicons.mjs +0 -124
- package/runtime/server/agent-markdown.ts +0 -19
- package/server/api/_ginko-docs/redirects.get.ts +0 -28
- package/server/mcp/tools/get-page.ts +0 -14
- package/server/mcp/tools/list-pages.ts +0 -10
- package/server/middleware/redirects.ts +0 -22
- package/server/plugins/agent-markdown.ts +0 -6
- package/server/plugins/sitemap-policy.ts +0 -12
- package/server/routes/.well-known/ai-catalog.json.get.ts +0 -10
- package/server/routes/[locale]/blog/rss.xml.get.ts +0 -13
- package/server/routes/blog/rss.xml.get.ts +0 -5
- package/server/routes/mcp/server-card.get.ts +0 -14
- package/server/utils/blog-feed.ts +0 -51
- package/server/utils/feed.ts +0 -70
- package/server/utils/mcp-server-card.ts +0 -45
- package/server/utils/redirects.ts +0 -38
- package/server/utils/redirects.utils.ts +0 -58
- package/server/utils/sitemap.ts +0 -45
- package/shared/route-slugs.ts +0 -5
- package/shared/theme-palettes.ts +0 -37
- package/shared/theme-presets.ts +0 -3
- package/shared/types/app-config.ts +0 -172
- package/shared/types/nuxt-config.ts +0 -14
- package/tags.ts +0 -192
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { default as DropdownMenu } from "./DropdownMenu.vue";
|
|
2
|
-
export { default as DropdownMenuContent } from "./DropdownMenuContent.vue";
|
|
3
|
-
export { default as DropdownMenuItem } from "./DropdownMenuItem.vue";
|
|
4
|
-
export { default as DropdownMenuRadioGroup } from "./DropdownMenuRadioGroup.vue";
|
|
5
|
-
export { default as DropdownMenuRadioItem } from "./DropdownMenuRadioItem.vue";
|
|
6
|
-
export { default as DropdownMenuSeparator } from "./DropdownMenuSeparator.vue";
|
|
7
|
-
export { default as DropdownMenuTrigger } from "./DropdownMenuTrigger.vue";
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "#ginko-docs/utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<kbd
|
|
12
|
-
:class="
|
|
13
|
-
cn(
|
|
14
|
-
'pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm bg-muted px-1 font-sans text-xs font-medium text-muted-foreground select-none',
|
|
15
|
-
'[&_svg:not([class*=\'size-\'])]:size-3',
|
|
16
|
-
'[[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10',
|
|
17
|
-
props.class,
|
|
18
|
-
)
|
|
19
|
-
"
|
|
20
|
-
>
|
|
21
|
-
<slot />
|
|
22
|
-
</kbd>
|
|
23
|
-
</template>
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { VariantProps } from "class-variance-authority";
|
|
2
|
-
import { cva } from "class-variance-authority";
|
|
3
|
-
|
|
4
|
-
export { default as Kbd } from "./Kbd.vue";
|
|
5
|
-
|
|
6
|
-
export const kbdVariants = cva(
|
|
7
|
-
"bg-muted text-muted-foreground ring-1 ring-border pointer-events-none inline-flex w-fit items-center justify-center gap-1 rounded-sm font-sans font-medium select-none [&_svg:not([class*='size-'])]:size-3 [[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10",
|
|
8
|
-
{
|
|
9
|
-
variants: {
|
|
10
|
-
size: {
|
|
11
|
-
sm: "h-5 min-w-5 px-1 text-xs",
|
|
12
|
-
md: "h-7 min-w-7 px-1.5 text-sm",
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
defaultVariants: {
|
|
16
|
-
size: "sm",
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
export type KbdVariants = VariantProps<typeof kbdVariants>;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { ScrollAreaRootProps } from "reka-ui";
|
|
3
|
-
import type { HTMLAttributes } from "vue";
|
|
4
|
-
import { reactiveOmit } from "@vueuse/core";
|
|
5
|
-
import { ScrollAreaCorner, ScrollAreaRoot, ScrollAreaViewport } from "reka-ui";
|
|
6
|
-
import { cn } from "#ginko-docs/utils";
|
|
7
|
-
import ScrollBar from "./ScrollBar.vue";
|
|
8
|
-
|
|
9
|
-
const props = defineProps<
|
|
10
|
-
ScrollAreaRootProps & {
|
|
11
|
-
class?: HTMLAttributes["class"];
|
|
12
|
-
viewportClass?: HTMLAttributes["class"];
|
|
13
|
-
}
|
|
14
|
-
>();
|
|
15
|
-
|
|
16
|
-
const delegatedProps = reactiveOmit(props, "class", "viewportClass");
|
|
17
|
-
</script>
|
|
18
|
-
|
|
19
|
-
<template>
|
|
20
|
-
<ScrollAreaRoot
|
|
21
|
-
data-slot="scroll-area"
|
|
22
|
-
v-bind="delegatedProps"
|
|
23
|
-
:class="cn('relative', props.class)"
|
|
24
|
-
>
|
|
25
|
-
<ScrollAreaViewport
|
|
26
|
-
data-slot="scroll-area-viewport"
|
|
27
|
-
:class="
|
|
28
|
-
cn(
|
|
29
|
-
'size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1',
|
|
30
|
-
props.viewportClass,
|
|
31
|
-
)
|
|
32
|
-
"
|
|
33
|
-
>
|
|
34
|
-
<slot />
|
|
35
|
-
</ScrollAreaViewport>
|
|
36
|
-
<ScrollBar />
|
|
37
|
-
<ScrollAreaCorner />
|
|
38
|
-
</ScrollAreaRoot>
|
|
39
|
-
</template>
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { ScrollAreaScrollbarProps } from "reka-ui";
|
|
3
|
-
import type { HTMLAttributes } from "vue";
|
|
4
|
-
import { reactiveOmit } from "@vueuse/core";
|
|
5
|
-
import { ScrollAreaScrollbar, ScrollAreaThumb } from "reka-ui";
|
|
6
|
-
import { cn } from "#ginko-docs/utils";
|
|
7
|
-
|
|
8
|
-
const props = withDefaults(
|
|
9
|
-
defineProps<ScrollAreaScrollbarProps & { class?: HTMLAttributes["class"] }>(),
|
|
10
|
-
{
|
|
11
|
-
orientation: "vertical",
|
|
12
|
-
},
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
const delegatedProps = reactiveOmit(props, "class");
|
|
16
|
-
</script>
|
|
17
|
-
|
|
18
|
-
<template>
|
|
19
|
-
<ScrollAreaScrollbar
|
|
20
|
-
data-slot="scroll-area-scrollbar"
|
|
21
|
-
v-bind="delegatedProps"
|
|
22
|
-
:class="
|
|
23
|
-
cn(
|
|
24
|
-
'flex touch-none p-px transition-colors select-none',
|
|
25
|
-
orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent',
|
|
26
|
-
orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent',
|
|
27
|
-
props.class,
|
|
28
|
-
)
|
|
29
|
-
"
|
|
30
|
-
>
|
|
31
|
-
<ScrollAreaThumb data-slot="scroll-area-thumb" class="relative flex-1 rounded-full bg-border" />
|
|
32
|
-
</ScrollAreaScrollbar>
|
|
33
|
-
</template>
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { SeparatorProps } from "reka-ui";
|
|
3
|
-
import type { HTMLAttributes } from "vue";
|
|
4
|
-
import { reactiveOmit } from "@vueuse/core";
|
|
5
|
-
import { Separator } from "reka-ui";
|
|
6
|
-
import { cn } from "#ginko-docs/utils";
|
|
7
|
-
|
|
8
|
-
const props = withDefaults(defineProps<SeparatorProps & { class?: HTMLAttributes["class"] }>(), {
|
|
9
|
-
orientation: "horizontal",
|
|
10
|
-
decorative: true,
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
const delegatedProps = reactiveOmit(props, "class");
|
|
14
|
-
</script>
|
|
15
|
-
|
|
16
|
-
<template>
|
|
17
|
-
<Separator
|
|
18
|
-
data-slot="separator"
|
|
19
|
-
v-bind="delegatedProps"
|
|
20
|
-
:class="
|
|
21
|
-
cn(
|
|
22
|
-
'shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
|
|
23
|
-
props.class,
|
|
24
|
-
)
|
|
25
|
-
"
|
|
26
|
-
/>
|
|
27
|
-
</template>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as Separator } from "./Separator.vue";
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { DialogRootEmits, DialogRootProps } from "reka-ui";
|
|
3
|
-
import { DialogRoot, useForwardPropsEmits } from "reka-ui";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<DialogRootProps>();
|
|
6
|
-
const emits = defineEmits<DialogRootEmits>();
|
|
7
|
-
|
|
8
|
-
const forwarded = useForwardPropsEmits(props, emits);
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<template>
|
|
12
|
-
<DialogRoot v-slot="slotProps" data-slot="sheet" v-bind="forwarded">
|
|
13
|
-
<slot v-bind="slotProps" />
|
|
14
|
-
</DialogRoot>
|
|
15
|
-
</template>
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { DialogContentEmits, DialogContentProps } from "reka-ui";
|
|
3
|
-
import type { HTMLAttributes } from "vue";
|
|
4
|
-
import { reactiveOmit } from "@vueuse/core";
|
|
5
|
-
import { DialogClose, DialogContent, DialogPortal, useForwardPropsEmits } from "reka-ui";
|
|
6
|
-
import { cn } from "#ginko-docs/utils";
|
|
7
|
-
import SheetOverlay from "./SheetOverlay.vue";
|
|
8
|
-
|
|
9
|
-
interface SheetContentProps extends DialogContentProps {
|
|
10
|
-
class?: HTMLAttributes["class"];
|
|
11
|
-
side?: "top" | "right" | "bottom" | "left";
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
defineOptions({
|
|
15
|
-
inheritAttrs: false,
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const props = withDefaults(defineProps<SheetContentProps>(), {
|
|
19
|
-
side: "right",
|
|
20
|
-
});
|
|
21
|
-
const emits = defineEmits<DialogContentEmits>();
|
|
22
|
-
|
|
23
|
-
const delegatedProps = reactiveOmit(props, "class", "side");
|
|
24
|
-
|
|
25
|
-
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
26
|
-
</script>
|
|
27
|
-
|
|
28
|
-
<template>
|
|
29
|
-
<DialogPortal>
|
|
30
|
-
<SheetOverlay />
|
|
31
|
-
<DialogContent
|
|
32
|
-
data-slot="sheet-content"
|
|
33
|
-
:class="
|
|
34
|
-
cn(
|
|
35
|
-
'fixed z-[70] flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:animate-out data-[state=closed]:duration-200 data-[state=open]:animate-in data-[state=open]:duration-200',
|
|
36
|
-
side === 'right' &&
|
|
37
|
-
'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm',
|
|
38
|
-
side === 'left' &&
|
|
39
|
-
'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm',
|
|
40
|
-
side === 'top' &&
|
|
41
|
-
'inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
|
|
42
|
-
side === 'bottom' &&
|
|
43
|
-
'inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
|
|
44
|
-
props.class,
|
|
45
|
-
)
|
|
46
|
-
"
|
|
47
|
-
v-bind="{ ...$attrs, ...forwarded }"
|
|
48
|
-
>
|
|
49
|
-
<slot />
|
|
50
|
-
|
|
51
|
-
<DialogClose
|
|
52
|
-
class="absolute top-4 right-4 inline-flex size-8 items-center justify-center rounded-md text-muted-foreground transition-colors outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none"
|
|
53
|
-
>
|
|
54
|
-
<Icon name="lucide:x" class="size-4" aria-hidden="true" />
|
|
55
|
-
<span class="sr-only">Close</span>
|
|
56
|
-
</DialogClose>
|
|
57
|
-
</DialogContent>
|
|
58
|
-
</DialogPortal>
|
|
59
|
-
</template>
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { DialogDescriptionProps } from "reka-ui";
|
|
3
|
-
import type { HTMLAttributes } from "vue";
|
|
4
|
-
import { reactiveOmit } from "@vueuse/core";
|
|
5
|
-
import { DialogDescription } from "reka-ui";
|
|
6
|
-
import { cn } from "#ginko-docs/utils";
|
|
7
|
-
|
|
8
|
-
const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes["class"] }>();
|
|
9
|
-
|
|
10
|
-
const delegatedProps = reactiveOmit(props, "class");
|
|
11
|
-
</script>
|
|
12
|
-
|
|
13
|
-
<template>
|
|
14
|
-
<DialogDescription
|
|
15
|
-
data-slot="sheet-description"
|
|
16
|
-
:class="cn('text-sm text-muted-foreground', props.class)"
|
|
17
|
-
v-bind="delegatedProps"
|
|
18
|
-
>
|
|
19
|
-
<slot />
|
|
20
|
-
</DialogDescription>
|
|
21
|
-
</template>
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { DialogOverlayProps } from "reka-ui";
|
|
3
|
-
import type { HTMLAttributes } from "vue";
|
|
4
|
-
import { reactiveOmit } from "@vueuse/core";
|
|
5
|
-
import { DialogOverlay } from "reka-ui";
|
|
6
|
-
import { cn } from "#ginko-docs/utils";
|
|
7
|
-
|
|
8
|
-
const props = defineProps<DialogOverlayProps & { class?: HTMLAttributes["class"] }>();
|
|
9
|
-
|
|
10
|
-
const delegatedProps = reactiveOmit(props, "class");
|
|
11
|
-
</script>
|
|
12
|
-
|
|
13
|
-
<template>
|
|
14
|
-
<DialogOverlay
|
|
15
|
-
data-slot="sheet-overlay"
|
|
16
|
-
:class="
|
|
17
|
-
cn(
|
|
18
|
-
'fixed inset-0 z-[60] bg-overlay data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',
|
|
19
|
-
props.class,
|
|
20
|
-
)
|
|
21
|
-
"
|
|
22
|
-
v-bind="delegatedProps"
|
|
23
|
-
>
|
|
24
|
-
<slot />
|
|
25
|
-
</DialogOverlay>
|
|
26
|
-
</template>
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { DialogTitleProps } from "reka-ui";
|
|
3
|
-
import type { HTMLAttributes } from "vue";
|
|
4
|
-
import { reactiveOmit } from "@vueuse/core";
|
|
5
|
-
import { DialogTitle } from "reka-ui";
|
|
6
|
-
import { cn } from "#ginko-docs/utils";
|
|
7
|
-
|
|
8
|
-
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes["class"] }>();
|
|
9
|
-
|
|
10
|
-
const delegatedProps = reactiveOmit(props, "class");
|
|
11
|
-
</script>
|
|
12
|
-
|
|
13
|
-
<template>
|
|
14
|
-
<DialogTitle
|
|
15
|
-
data-slot="sheet-title"
|
|
16
|
-
:class="cn('font-semibold text-foreground', props.class)"
|
|
17
|
-
v-bind="delegatedProps"
|
|
18
|
-
>
|
|
19
|
-
<slot />
|
|
20
|
-
</DialogTitle>
|
|
21
|
-
</template>
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { DialogTriggerProps } from "reka-ui";
|
|
3
|
-
import { DialogTrigger } from "reka-ui";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<DialogTriggerProps>();
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<template>
|
|
9
|
-
<DialogTrigger data-slot="sheet-trigger" v-bind="props">
|
|
10
|
-
<slot />
|
|
11
|
-
</DialogTrigger>
|
|
12
|
-
</template>
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export { default as Sheet } from "./Sheet.vue";
|
|
2
|
-
export { default as SheetContent } from "./SheetContent.vue";
|
|
3
|
-
export { default as SheetDescription } from "./SheetDescription.vue";
|
|
4
|
-
export { default as SheetTitle } from "./SheetTitle.vue";
|
|
5
|
-
export { default as SheetTrigger } from "./SheetTrigger.vue";
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { TabsRootEmits, TabsRootProps } from "reka-ui";
|
|
3
|
-
import type { HTMLAttributes } from "vue";
|
|
4
|
-
import { reactiveOmit } from "@vueuse/core";
|
|
5
|
-
import { TabsRoot, useForwardPropsEmits } from "reka-ui";
|
|
6
|
-
import { cn } from "#ginko-docs/utils";
|
|
7
|
-
|
|
8
|
-
const props = defineProps<TabsRootProps & { class?: HTMLAttributes["class"] }>();
|
|
9
|
-
const emits = defineEmits<TabsRootEmits>();
|
|
10
|
-
|
|
11
|
-
const delegatedProps = reactiveOmit(props, "class");
|
|
12
|
-
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
<template>
|
|
16
|
-
<TabsRoot
|
|
17
|
-
v-slot="slotProps"
|
|
18
|
-
data-slot="tabs"
|
|
19
|
-
v-bind="forwarded"
|
|
20
|
-
:class="cn('flex flex-col gap-2', props.class)"
|
|
21
|
-
>
|
|
22
|
-
<slot v-bind="slotProps" />
|
|
23
|
-
</TabsRoot>
|
|
24
|
-
</template>
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { TabsListProps } from "reka-ui";
|
|
3
|
-
import type { HTMLAttributes } from "vue";
|
|
4
|
-
import { reactiveOmit } from "@vueuse/core";
|
|
5
|
-
import { TabsList } from "reka-ui";
|
|
6
|
-
import { cn } from "#ginko-docs/utils";
|
|
7
|
-
|
|
8
|
-
const props = defineProps<TabsListProps & { class?: HTMLAttributes["class"] }>();
|
|
9
|
-
|
|
10
|
-
const delegatedProps = reactiveOmit(props, "class");
|
|
11
|
-
</script>
|
|
12
|
-
|
|
13
|
-
<template>
|
|
14
|
-
<TabsList
|
|
15
|
-
data-slot="tabs-list"
|
|
16
|
-
v-bind="delegatedProps"
|
|
17
|
-
:class="
|
|
18
|
-
cn(
|
|
19
|
-
'inline-flex h-9 w-fit items-center justify-center rounded-lg bg-muted p-[3px] text-muted-foreground',
|
|
20
|
-
props.class,
|
|
21
|
-
)
|
|
22
|
-
"
|
|
23
|
-
>
|
|
24
|
-
<slot />
|
|
25
|
-
</TabsList>
|
|
26
|
-
</template>
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { TabsTriggerProps } from "reka-ui";
|
|
3
|
-
import type { HTMLAttributes } from "vue";
|
|
4
|
-
import { reactiveOmit } from "@vueuse/core";
|
|
5
|
-
import { TabsTrigger, useForwardProps } from "reka-ui";
|
|
6
|
-
import { cn } from "#ginko-docs/utils";
|
|
7
|
-
|
|
8
|
-
const props = defineProps<TabsTriggerProps & { class?: HTMLAttributes["class"] }>();
|
|
9
|
-
|
|
10
|
-
const delegatedProps = reactiveOmit(props, "class");
|
|
11
|
-
|
|
12
|
-
const forwardedProps = useForwardProps(delegatedProps);
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
<template>
|
|
16
|
-
<TabsTrigger
|
|
17
|
-
data-slot="tabs-trigger"
|
|
18
|
-
:class="
|
|
19
|
-
cn(
|
|
20
|
-
'inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap text-foreground transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:shadow-sm dark:text-muted-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:data-[state=active]:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4',
|
|
21
|
-
props.class,
|
|
22
|
-
)
|
|
23
|
-
"
|
|
24
|
-
v-bind="forwardedProps"
|
|
25
|
-
>
|
|
26
|
-
<slot />
|
|
27
|
-
</TabsTrigger>
|
|
28
|
-
</template>
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
GinkoDocsAppConfig,
|
|
3
|
-
GinkoDocsLink,
|
|
4
|
-
GinkoDocsSocialPlatform,
|
|
5
|
-
} from "../../shared/types/app-config";
|
|
6
|
-
import { getLocalizedSiteText } from "../config/site.utils";
|
|
7
|
-
|
|
8
|
-
export interface NavItem {
|
|
9
|
-
label: string;
|
|
10
|
-
href: string;
|
|
11
|
-
external?: boolean;
|
|
12
|
-
icon?: string;
|
|
13
|
-
description?: string;
|
|
14
|
-
/** Set on social links so features can find a platform without matching its icon. */
|
|
15
|
-
platform?: GinkoDocsSocialPlatform;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface MainNavContext {
|
|
19
|
-
locale: string;
|
|
20
|
-
docsPath: string;
|
|
21
|
-
blogPath: string;
|
|
22
|
-
blogExists: boolean;
|
|
23
|
-
docsLabel: string;
|
|
24
|
-
blogLabel: string;
|
|
25
|
-
docsDescription?: string;
|
|
26
|
-
blogDescription?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const isExternalHref = (href: string) => /^https?:\/\//.test(href);
|
|
30
|
-
|
|
31
|
-
export function resolveMainNav(
|
|
32
|
-
links: GinkoDocsAppConfig["nav"]["links"],
|
|
33
|
-
ctx: MainNavContext,
|
|
34
|
-
): NavItem[] {
|
|
35
|
-
if (Array.isArray(links)) {
|
|
36
|
-
return links.map((link: GinkoDocsLink) => {
|
|
37
|
-
const href = getLocalizedSiteText(link.to, ctx.locale);
|
|
38
|
-
return {
|
|
39
|
-
label: getLocalizedSiteText(link.label, ctx.locale),
|
|
40
|
-
href,
|
|
41
|
-
external: isExternalHref(href),
|
|
42
|
-
icon: link.icon,
|
|
43
|
-
description: link.description
|
|
44
|
-
? getLocalizedSiteText(link.description, ctx.locale)
|
|
45
|
-
: undefined,
|
|
46
|
-
};
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const items: NavItem[] = [
|
|
51
|
-
{
|
|
52
|
-
label: ctx.docsLabel,
|
|
53
|
-
href: ctx.docsPath,
|
|
54
|
-
icon: "lucide:book-open",
|
|
55
|
-
description: ctx.docsDescription,
|
|
56
|
-
},
|
|
57
|
-
];
|
|
58
|
-
if (ctx.blogExists) {
|
|
59
|
-
items.push({
|
|
60
|
-
label: ctx.blogLabel,
|
|
61
|
-
href: ctx.blogPath,
|
|
62
|
-
icon: "lucide:file-text",
|
|
63
|
-
description: ctx.blogDescription,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
return items;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** Brand names are not translated, so the labels are literals. */
|
|
70
|
-
const socialDefaults: Record<GinkoDocsSocialPlatform, { label: string; icon: string }> = {
|
|
71
|
-
github: { label: "GitHub", icon: "ginko-social:github" },
|
|
72
|
-
discord: { label: "Discord", icon: "ginko-social:discord" },
|
|
73
|
-
linkedin: { label: "LinkedIn", icon: "lucide:linkedin" },
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export function resolveSocialLinks(social: GinkoDocsAppConfig["social"]): NavItem[] {
|
|
77
|
-
// Config order is render order, so a site can list Discord ahead of GitHub.
|
|
78
|
-
return Object.entries(social).flatMap<NavItem>(([key, entry]) => {
|
|
79
|
-
const platform = key as GinkoDocsSocialPlatform;
|
|
80
|
-
const defaults = socialDefaults[platform];
|
|
81
|
-
if (!defaults || !entry) return [];
|
|
82
|
-
|
|
83
|
-
const link = typeof entry === "string" ? { href: entry } : entry;
|
|
84
|
-
if (!link.href) return [];
|
|
85
|
-
|
|
86
|
-
return [
|
|
87
|
-
{
|
|
88
|
-
label: link.label ?? defaults.label,
|
|
89
|
-
href: link.href,
|
|
90
|
-
external: true,
|
|
91
|
-
icon: link.icon ?? defaults.icon,
|
|
92
|
-
platform,
|
|
93
|
-
},
|
|
94
|
-
];
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export interface BannerContext {
|
|
99
|
-
locale: string;
|
|
100
|
-
defaultText: string;
|
|
101
|
-
defaultLinkLabel: string;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export interface ResolvedBanner {
|
|
105
|
-
show: boolean;
|
|
106
|
-
text: string;
|
|
107
|
-
linkLabel: string;
|
|
108
|
-
linkHref?: string;
|
|
109
|
-
storageKey: string;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export function bannerStorageKey(id: string) {
|
|
113
|
-
return `ginko-docs:banner:${id}`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function resolveBanner(
|
|
117
|
-
config: GinkoDocsAppConfig["banner"],
|
|
118
|
-
ctx: BannerContext,
|
|
119
|
-
): ResolvedBanner {
|
|
120
|
-
const text = config.text ? getLocalizedSiteText(config.text, ctx.locale) : ctx.defaultText;
|
|
121
|
-
const linkHref = config.link?.to ? getLocalizedSiteText(config.link.to, ctx.locale) : undefined;
|
|
122
|
-
const linkLabel = config.link?.label
|
|
123
|
-
? getLocalizedSiteText(config.link.label, ctx.locale)
|
|
124
|
-
: ctx.defaultLinkLabel;
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
show: config.enabled,
|
|
128
|
-
text,
|
|
129
|
-
linkLabel,
|
|
130
|
-
linkHref,
|
|
131
|
-
storageKey: bannerStorageKey(config.id),
|
|
132
|
-
};
|
|
133
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { computed } from "vue";
|
|
2
|
-
import { useAppConfig, useRoute } from "#imports";
|
|
3
|
-
|
|
4
|
-
export function useCanonicalUrl() {
|
|
5
|
-
const route = useRoute();
|
|
6
|
-
const config = useAppConfig().ginkoDocs;
|
|
7
|
-
|
|
8
|
-
return computed(() => new URL(route.path, config.site.url).toString());
|
|
9
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { ContentAlternate } from "@lupinum/ginko-content/client";
|
|
2
|
-
import { computed, watch, type Ref } from "vue";
|
|
3
|
-
import { useRoute, useState } from "#imports";
|
|
4
|
-
|
|
5
|
-
type ContentRouteAlternatesState = {
|
|
6
|
-
sourcePath: string;
|
|
7
|
-
alternates: ContentAlternate[];
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export function useContentRouteAlternates() {
|
|
11
|
-
const route = useRoute();
|
|
12
|
-
const state = useState<ContentRouteAlternatesState>("content-route-alternates", () => ({
|
|
13
|
-
sourcePath: "",
|
|
14
|
-
alternates: [],
|
|
15
|
-
}));
|
|
16
|
-
|
|
17
|
-
const current = computed(() =>
|
|
18
|
-
state.value.sourcePath === route.path ? state.value.alternates : [],
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
function sync(page: Ref<{ route?: { alternates?: ContentAlternate[] } } | null | undefined>) {
|
|
22
|
-
watch(
|
|
23
|
-
page,
|
|
24
|
-
(document) => {
|
|
25
|
-
state.value = {
|
|
26
|
-
sourcePath: route.path,
|
|
27
|
-
alternates: document?.route?.alternates ?? [],
|
|
28
|
-
};
|
|
29
|
-
},
|
|
30
|
-
{ immediate: true },
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return { current, sync };
|
|
35
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { useScriptPlausibleAnalytics } from "#imports";
|
|
2
|
-
import { useGinkoDocsConfig } from "./useGinkoDocsConfig";
|
|
3
|
-
|
|
4
|
-
const PLAUSIBLE_INITIALIZER =
|
|
5
|
-
"window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};plausible.init()";
|
|
6
|
-
|
|
7
|
-
export type AnalyticsProps = Record<string, string>;
|
|
8
|
-
|
|
9
|
-
export interface GinkoAnalytics {
|
|
10
|
-
enabled: boolean;
|
|
11
|
-
track: (event: string, props?: AnalyticsProps) => void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Plausible analytics via the Nuxt Scripts registry script. Fully disabled
|
|
16
|
-
* unless `ginkoDocs.analytics.plausible.scriptId` is configured. Without an
|
|
17
|
-
* ID, no script loads and `track()` is a no-op, so callers never guard.
|
|
18
|
-
*/
|
|
19
|
-
export function useGinkoAnalytics(): GinkoAnalytics {
|
|
20
|
-
const config = useGinkoDocsConfig();
|
|
21
|
-
const scriptId = config.analytics?.plausible?.scriptId?.trim();
|
|
22
|
-
|
|
23
|
-
if (!scriptId) {
|
|
24
|
-
return { enabled: false, track: () => {} };
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const src = `https://plausible.io/js/pa-${scriptId}.js`;
|
|
28
|
-
useHead({
|
|
29
|
-
script: [
|
|
30
|
-
{ key: "plausibleAnalytics", src, async: true },
|
|
31
|
-
{ key: "plausibleAnalyticsInit", innerHTML: PLAUSIBLE_INITIALIZER },
|
|
32
|
-
],
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
const script = useScriptPlausibleAnalytics({
|
|
36
|
-
scriptId,
|
|
37
|
-
// Plausible verifies its exact snippet in server-rendered HTML. The head
|
|
38
|
-
// entry above provides it; Nuxt Scripts reuses the same keyed script for
|
|
39
|
-
// its typed proxy and lifecycle instead of adding a second tracker.
|
|
40
|
-
scriptOptions: { bundle: false },
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
enabled: true,
|
|
45
|
-
track: (event, props) => {
|
|
46
|
-
if (!import.meta.client) return;
|
|
47
|
-
const plausible = script.proxy.plausible;
|
|
48
|
-
if (typeof plausible !== "function") return;
|
|
49
|
-
plausible(event, props ? { props } : undefined);
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
}
|