@lupinum/ginko-docs 0.4.0-rc.8 → 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,12 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<hr :class="cn(props.class)" />
|
|
12
|
-
</template>
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { computed, resolveComponent } from "vue";
|
|
4
|
-
import { Motion } from "motion-v";
|
|
5
|
-
import { useI18n } from "#imports";
|
|
6
|
-
import ImageZoomDialog from "#ginko-docs/components/content/ImageZoomDialog.vue";
|
|
7
|
-
import { useGinkoDocsConfig } from "#ginko-docs/composables/useGinkoDocsConfig";
|
|
8
|
-
import { cn } from "../../utils";
|
|
9
|
-
|
|
10
|
-
const props = defineProps<{
|
|
11
|
-
src?: string;
|
|
12
|
-
alt?: string;
|
|
13
|
-
title?: string;
|
|
14
|
-
width?: string | number;
|
|
15
|
-
height?: string | number;
|
|
16
|
-
class?: HTMLAttributes["class"];
|
|
17
|
-
}>();
|
|
18
|
-
|
|
19
|
-
const { t } = useI18n();
|
|
20
|
-
const config = useGinkoDocsConfig();
|
|
21
|
-
const zoomEnabled = computed(() => config.images?.zoom !== false);
|
|
22
|
-
|
|
23
|
-
// External images skip NuxtImg; the layer ships no ipx domain allowlist.
|
|
24
|
-
const isLocalAsset = computed(() => Boolean(props.src?.startsWith("/")));
|
|
25
|
-
const imageComponent = computed(() => (isLocalAsset.value ? resolveComponent("NuxtImg") : "img"));
|
|
26
|
-
const imageAttrs = computed(() => ({
|
|
27
|
-
src: props.src,
|
|
28
|
-
alt: props.alt ?? "",
|
|
29
|
-
title: props.title,
|
|
30
|
-
width: props.width,
|
|
31
|
-
height: props.height,
|
|
32
|
-
loading: "lazy" as const,
|
|
33
|
-
decoding: "async" as const,
|
|
34
|
-
class: cn("content-prose-image", props.class),
|
|
35
|
-
...(isLocalAsset.value ? { sizes: "100vw md:704px" } : {}),
|
|
36
|
-
}));
|
|
37
|
-
</script>
|
|
38
|
-
|
|
39
|
-
<template>
|
|
40
|
-
<ImageZoomDialog v-if="src && zoomEnabled" :src="src" :alt="alt" :label="title">
|
|
41
|
-
<template #trigger="{ layoutId, transition }">
|
|
42
|
-
<!-- A button is phrasing content, so a bare markdown image stays valid inside its paragraph. -->
|
|
43
|
-
<button
|
|
44
|
-
type="button"
|
|
45
|
-
class="block max-w-full cursor-zoom-in rounded-[var(--radius)] focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
|
|
46
|
-
:aria-label="`${t('docs.zoomImage')}: ${alt ?? ''}`"
|
|
47
|
-
>
|
|
48
|
-
<Motion as-child :layout-id="layoutId" :transition="transition">
|
|
49
|
-
<component :is="imageComponent" v-bind="imageAttrs" />
|
|
50
|
-
</Motion>
|
|
51
|
-
</button>
|
|
52
|
-
</template>
|
|
53
|
-
</ImageZoomDialog>
|
|
54
|
-
<component :is="imageComponent" v-else-if="src" v-bind="imageAttrs" />
|
|
55
|
-
</template>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<li :class="cn(props.class)">
|
|
12
|
-
<slot />
|
|
13
|
-
</li>
|
|
14
|
-
</template>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<ol :class="cn(props.class)">
|
|
12
|
-
<slot />
|
|
13
|
-
</ol>
|
|
14
|
-
</template>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<p :class="cn(props.class)">
|
|
12
|
-
<slot />
|
|
13
|
-
</p>
|
|
14
|
-
</template>
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { ComputedRef, HTMLAttributes } from "vue";
|
|
3
|
-
import { computed, inject, onMounted, ref, useId } from "vue";
|
|
4
|
-
import { useClipboard, useEventListener, useResizeObserver } from "@vueuse/core";
|
|
5
|
-
import { useI18n } from "#imports";
|
|
6
|
-
import { cn } from "../../utils";
|
|
7
|
-
import { useProseAppearance } from "../../composables/useProseAppearance";
|
|
8
|
-
import {
|
|
9
|
-
EXTENSION_ICONS,
|
|
10
|
-
FALLBACK_FILE_ICON,
|
|
11
|
-
FILENAME_ICONS,
|
|
12
|
-
LANGUAGE_ICONS,
|
|
13
|
-
filenameExtension,
|
|
14
|
-
normalizedFilename,
|
|
15
|
-
} from "../../utils/file-icons";
|
|
16
|
-
|
|
17
|
-
const props = defineProps<{
|
|
18
|
-
code?: string;
|
|
19
|
-
language?: string | null;
|
|
20
|
-
filename?: string | null;
|
|
21
|
-
highlights?: number[];
|
|
22
|
-
meta?: string | null;
|
|
23
|
-
icon?: string | null;
|
|
24
|
-
inGroup?: boolean;
|
|
25
|
-
class?: HTMLAttributes["class"];
|
|
26
|
-
appearance?: "quiet" | "tint";
|
|
27
|
-
}>();
|
|
28
|
-
// Instance prop wins, then a surrounding ::collapse wrapper, then config.
|
|
29
|
-
const wrapperAppearance = inject<ComputedRef<"quiet" | "tint"> | null>(
|
|
30
|
-
"contentCodeAppearance",
|
|
31
|
-
null,
|
|
32
|
-
);
|
|
33
|
-
const appearance = useProseAppearance("code", () => props.appearance ?? wrapperAppearance?.value);
|
|
34
|
-
|
|
35
|
-
const { copy, copied } = useClipboard();
|
|
36
|
-
const { t } = useI18n();
|
|
37
|
-
const codeElement = ref<HTMLElement | null>(null);
|
|
38
|
-
// Landmarks with role="region" need unique accessible names; the same
|
|
39
|
-
// filename can appear in several code blocks on one page.
|
|
40
|
-
const regionId = useId();
|
|
41
|
-
|
|
42
|
-
const HIDDEN_LANGUAGES = new Set(["text", "plaintext", "txt", "plain"]);
|
|
43
|
-
|
|
44
|
-
function parseIconFromMeta(meta: string | null | undefined): string | null {
|
|
45
|
-
if (!meta) return null;
|
|
46
|
-
const match = meta.match(/(?:^|\s)icon=(\S+)/);
|
|
47
|
-
return match?.[1] ?? null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function normalizedLanguage(language: string | null | undefined): string | null {
|
|
51
|
-
return language?.trim().toLowerCase() || null;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const label = computed(() => {
|
|
55
|
-
if (props.filename) return props.filename;
|
|
56
|
-
|
|
57
|
-
const language = normalizedLanguage(props.language);
|
|
58
|
-
if (language && !HIDDEN_LANGUAGES.has(language)) return props.language;
|
|
59
|
-
|
|
60
|
-
return "";
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const iconName = computed(() => {
|
|
64
|
-
const explicitIcon = props.icon || parseIconFromMeta(props.meta);
|
|
65
|
-
if (explicitIcon) return explicitIcon;
|
|
66
|
-
|
|
67
|
-
const filename = normalizedFilename(props.filename);
|
|
68
|
-
if (filename && FILENAME_ICONS[filename]) return FILENAME_ICONS[filename];
|
|
69
|
-
|
|
70
|
-
const extension = filenameExtension(props.filename);
|
|
71
|
-
if (extension && EXTENSION_ICONS[extension]) return EXTENSION_ICONS[extension];
|
|
72
|
-
|
|
73
|
-
const language = normalizedLanguage(props.language);
|
|
74
|
-
if (language && LANGUAGE_ICONS[language]) return LANGUAGE_ICONS[language];
|
|
75
|
-
|
|
76
|
-
return FALLBACK_FILE_ICON;
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
async function copyCode() {
|
|
80
|
-
await copy(props.code || codeElement.value?.innerText || "");
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// A right-edge fade signals horizontally clipped code; it disappears once the
|
|
84
|
-
// reader reaches the end of the line.
|
|
85
|
-
const scrollElement = ref<HTMLElement | null>(null);
|
|
86
|
-
const canScrollRight = ref(false);
|
|
87
|
-
|
|
88
|
-
function measureOverflow() {
|
|
89
|
-
const el = scrollElement.value;
|
|
90
|
-
if (!el) return;
|
|
91
|
-
canScrollRight.value =
|
|
92
|
-
el.scrollWidth - el.clientWidth > 2 && el.scrollLeft + el.clientWidth < el.scrollWidth - 2;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
onMounted(measureOverflow);
|
|
96
|
-
useEventListener(scrollElement, "scroll", measureOverflow, { passive: true });
|
|
97
|
-
useResizeObserver(scrollElement, measureOverflow);
|
|
98
|
-
</script>
|
|
99
|
-
|
|
100
|
-
<template>
|
|
101
|
-
<figure
|
|
102
|
-
dir="ltr"
|
|
103
|
-
data-fd-codeblock
|
|
104
|
-
:data-appearance="appearance"
|
|
105
|
-
tabindex="-1"
|
|
106
|
-
:class="
|
|
107
|
-
cn(
|
|
108
|
-
'content-codeblock group shiki not-prose relative',
|
|
109
|
-
props.inGroup
|
|
110
|
-
? 'content-codeblock-in-group'
|
|
111
|
-
: label
|
|
112
|
-
? 'content-codeblock-with-caption'
|
|
113
|
-
: 'content-codeblock-plain',
|
|
114
|
-
)
|
|
115
|
-
"
|
|
116
|
-
>
|
|
117
|
-
<figcaption v-if="label && !props.inGroup" data-fd-caption>
|
|
118
|
-
<Icon :name="iconName" mode="svg" class="content-codeblock-caption-icon" aria-hidden="true" />
|
|
119
|
-
<span class="flex-1 truncate">{{ label }}</span>
|
|
120
|
-
<button
|
|
121
|
-
type="button"
|
|
122
|
-
class="content-codeblock-copy-button ml-auto"
|
|
123
|
-
:aria-label="copied ? t('docs.copiedText') : t('docs.copyText')"
|
|
124
|
-
@click="copyCode"
|
|
125
|
-
>
|
|
126
|
-
<Icon
|
|
127
|
-
:name="copied ? 'lucide:check' : 'lucide:clipboard'"
|
|
128
|
-
mode="svg"
|
|
129
|
-
class="size-3.5"
|
|
130
|
-
aria-hidden="true"
|
|
131
|
-
/>
|
|
132
|
-
</button>
|
|
133
|
-
</figcaption>
|
|
134
|
-
|
|
135
|
-
<div v-if="!label && !props.inGroup" class="absolute top-2 right-2 z-10" data-fd-copy-float>
|
|
136
|
-
<button
|
|
137
|
-
type="button"
|
|
138
|
-
class="content-codeblock-copy-button content-codeblock-copy-button-floating"
|
|
139
|
-
:aria-label="copied ? t('docs.copiedText') : t('docs.copyText')"
|
|
140
|
-
@click="copyCode"
|
|
141
|
-
>
|
|
142
|
-
<Icon
|
|
143
|
-
:name="copied ? 'lucide:check' : 'lucide:clipboard'"
|
|
144
|
-
mode="svg"
|
|
145
|
-
class="size-3.5"
|
|
146
|
-
aria-hidden="true"
|
|
147
|
-
/>
|
|
148
|
-
</button>
|
|
149
|
-
</div>
|
|
150
|
-
|
|
151
|
-
<div class="content-codeblock-scroll-wrap">
|
|
152
|
-
<div
|
|
153
|
-
ref="scrollElement"
|
|
154
|
-
role="region"
|
|
155
|
-
tabindex="0"
|
|
156
|
-
:aria-label="
|
|
157
|
-
(label ? `${t('docs.codeSample')}: ${label}` : t('docs.codeSample')) + ` (${regionId})`
|
|
158
|
-
"
|
|
159
|
-
:class="
|
|
160
|
-
cn(
|
|
161
|
-
'fd-scroll-container max-h-[600px] overflow-auto focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none focus-visible:ring-inset',
|
|
162
|
-
!label && !props.inGroup && 'content-codeblock-inline-copy',
|
|
163
|
-
)
|
|
164
|
-
"
|
|
165
|
-
>
|
|
166
|
-
<pre
|
|
167
|
-
ref="codeElement"
|
|
168
|
-
:class="cn('w-max min-w-full', props.class)"
|
|
169
|
-
v-bind="$attrs"
|
|
170
|
-
><slot /></pre>
|
|
171
|
-
</div>
|
|
172
|
-
|
|
173
|
-
<div
|
|
174
|
-
class="content-codeblock-overflow-fade"
|
|
175
|
-
:data-hidden="!canScrollRight"
|
|
176
|
-
aria-hidden="true"
|
|
177
|
-
/>
|
|
178
|
-
</div>
|
|
179
|
-
</figure>
|
|
180
|
-
</template>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<strong :class="cn(props.class)">
|
|
12
|
-
<slot />
|
|
13
|
-
</strong>
|
|
14
|
-
</template>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<div :class="cn('content-table', props.class)">
|
|
12
|
-
<div class="content-table-scroll">
|
|
13
|
-
<table>
|
|
14
|
-
<slot />
|
|
15
|
-
</table>
|
|
16
|
-
</div>
|
|
17
|
-
</div>
|
|
18
|
-
</template>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<tbody :class="cn(props.class)">
|
|
12
|
-
<slot />
|
|
13
|
-
</tbody>
|
|
14
|
-
</template>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<td :class="cn(props.class)">
|
|
12
|
-
<slot />
|
|
13
|
-
</td>
|
|
14
|
-
</template>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<th :class="cn(props.class)">
|
|
12
|
-
<slot />
|
|
13
|
-
</th>
|
|
14
|
-
</template>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<thead :class="cn(props.class)">
|
|
12
|
-
<slot />
|
|
13
|
-
</thead>
|
|
14
|
-
</template>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<tr :class="cn(props.class)">
|
|
12
|
-
<slot />
|
|
13
|
-
</tr>
|
|
14
|
-
</template>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
class?: HTMLAttributes["class"];
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<ul :class="cn(props.class)">
|
|
12
|
-
<slot />
|
|
13
|
-
</ul>
|
|
14
|
-
</template>
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { HTMLAttributes } from "vue";
|
|
3
|
-
import { computed } from "vue";
|
|
4
|
-
import { useColorMode, useI18n } from "#imports";
|
|
5
|
-
import { cn } from "#ginko-docs/utils";
|
|
6
|
-
import { headerUtilityButtonClass } from "#ginko-docs/components/site/header-utils";
|
|
7
|
-
import {
|
|
8
|
-
nextColorModePreference,
|
|
9
|
-
themeToggleIcon,
|
|
10
|
-
themeToggleLabelKey,
|
|
11
|
-
} from "#ginko-docs/components/site/mode-toggle.utils";
|
|
12
|
-
|
|
13
|
-
const props = withDefaults(
|
|
14
|
-
defineProps<{
|
|
15
|
-
variant?: "icon" | "menu-row";
|
|
16
|
-
class?: HTMLAttributes["class"];
|
|
17
|
-
}>(),
|
|
18
|
-
{
|
|
19
|
-
variant: "icon",
|
|
20
|
-
},
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
const colorMode = useColorMode();
|
|
24
|
-
const { t } = useI18n();
|
|
25
|
-
|
|
26
|
-
const isDark = computed(() => colorMode.value === "dark");
|
|
27
|
-
const toggleIcon = computed(() => themeToggleIcon(isDark.value));
|
|
28
|
-
const toggleLabel = computed(() => t(themeToggleLabelKey(isDark.value)));
|
|
29
|
-
|
|
30
|
-
function toggleColorMode() {
|
|
31
|
-
const currentRendered = isDark.value ? "dark" : "light";
|
|
32
|
-
colorMode.preference = nextColorModePreference(currentRendered);
|
|
33
|
-
}
|
|
34
|
-
</script>
|
|
35
|
-
|
|
36
|
-
<template>
|
|
37
|
-
<button
|
|
38
|
-
v-if="variant === 'menu-row'"
|
|
39
|
-
type="button"
|
|
40
|
-
role="switch"
|
|
41
|
-
:aria-checked="isDark"
|
|
42
|
-
:aria-label="toggleLabel"
|
|
43
|
-
:class="
|
|
44
|
-
cn(
|
|
45
|
-
'flex h-14 w-full items-center justify-between rounded-none px-5 text-base font-semibold hover:bg-transparent',
|
|
46
|
-
props.class,
|
|
47
|
-
)
|
|
48
|
-
"
|
|
49
|
-
@click="toggleColorMode"
|
|
50
|
-
>
|
|
51
|
-
<span class="flex min-w-0 items-center gap-4">
|
|
52
|
-
<span
|
|
53
|
-
class="flex size-11 shrink-0 items-center justify-center rounded-lg bg-muted/60 text-foreground"
|
|
54
|
-
>
|
|
55
|
-
<Icon :name="toggleIcon" class="size-5" aria-hidden="true" />
|
|
56
|
-
</span>
|
|
57
|
-
<span class="truncate">{{ t("theme.label") }}</span>
|
|
58
|
-
</span>
|
|
59
|
-
<span
|
|
60
|
-
class="relative inline-flex h-6 w-11 shrink-0 rounded-full border border-border bg-muted/60 transition-colors"
|
|
61
|
-
:class="isDark ? 'bg-foreground/80' : ''"
|
|
62
|
-
aria-hidden="true"
|
|
63
|
-
>
|
|
64
|
-
<span
|
|
65
|
-
class="absolute top-0.5 size-5 rounded-full bg-background shadow-xs transition-transform motion-reduce:transition-none"
|
|
66
|
-
:class="isDark ? 'translate-x-[1.375rem]' : 'translate-x-0.5'"
|
|
67
|
-
/>
|
|
68
|
-
</span>
|
|
69
|
-
</button>
|
|
70
|
-
<button
|
|
71
|
-
v-else
|
|
72
|
-
type="button"
|
|
73
|
-
role="switch"
|
|
74
|
-
:aria-checked="isDark"
|
|
75
|
-
:aria-label="toggleLabel"
|
|
76
|
-
:class="cn(headerUtilityButtonClass, props.class)"
|
|
77
|
-
@click="toggleColorMode"
|
|
78
|
-
>
|
|
79
|
-
<Icon :name="toggleIcon" class="size-[18px]" aria-hidden="true" />
|
|
80
|
-
</button>
|
|
81
|
-
</template>
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { useLocalStorage } from "@vueuse/core";
|
|
3
|
-
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from "vue";
|
|
4
|
-
import { useI18n } from "#imports";
|
|
5
|
-
import { useGinkoDocsConfig } from "#ginko-docs/composables/useGinkoDocsConfig";
|
|
6
|
-
import { useSiteNavigation } from "#ginko-docs/composables/useSiteNavigation";
|
|
7
|
-
|
|
8
|
-
const props = defineProps<{
|
|
9
|
-
landing?: boolean;
|
|
10
|
-
}>();
|
|
11
|
-
|
|
12
|
-
const { banner } = useSiteNavigation();
|
|
13
|
-
const { t } = useI18n();
|
|
14
|
-
const config = useGinkoDocsConfig();
|
|
15
|
-
|
|
16
|
-
const dismissed = useLocalStorage(banner.value.storageKey, false);
|
|
17
|
-
// Avoid a hydration mismatch: localStorage is client-only, so reveal after mount.
|
|
18
|
-
const hydrated = ref(false);
|
|
19
|
-
onMounted(() => {
|
|
20
|
-
hydrated.value = true;
|
|
21
|
-
});
|
|
22
|
-
const visible = computed(
|
|
23
|
-
() =>
|
|
24
|
-
banner.value.show &&
|
|
25
|
-
(!props.landing || config.banner.showOnLanding) &&
|
|
26
|
-
(!hydrated.value ? true : !dismissed.value),
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
// The banner scrolls away above the sticky header, so sticky consumers
|
|
30
|
-
// (docs sidebar/TOC heights, mobile menu top) need its *currently visible*
|
|
31
|
-
// height. This component is the single writer of --site-banner-height.
|
|
32
|
-
const bannerElement = ref<HTMLElement | null>(null);
|
|
33
|
-
let rafId: number | null = null;
|
|
34
|
-
let lastHeight = -1;
|
|
35
|
-
|
|
36
|
-
function updateBannerHeightVar() {
|
|
37
|
-
rafId = null;
|
|
38
|
-
const element = bannerElement.value;
|
|
39
|
-
const height = element
|
|
40
|
-
? Math.max(0, Math.min(element.getBoundingClientRect().bottom, element.offsetHeight))
|
|
41
|
-
: 0;
|
|
42
|
-
if (height === lastHeight) return;
|
|
43
|
-
lastHeight = height;
|
|
44
|
-
document.documentElement.style.setProperty("--site-banner-height", `${height}px`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function scheduleBannerHeightVar() {
|
|
48
|
-
if (rafId !== null) return;
|
|
49
|
-
rafId = requestAnimationFrame(updateBannerHeightVar);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
watch(visible, () => {
|
|
53
|
-
void nextTick(scheduleBannerHeightVar);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
onMounted(() => {
|
|
57
|
-
window.addEventListener("scroll", scheduleBannerHeightVar, { passive: true });
|
|
58
|
-
window.addEventListener("resize", scheduleBannerHeightVar, { passive: true });
|
|
59
|
-
scheduleBannerHeightVar();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
onBeforeUnmount(() => {
|
|
63
|
-
window.removeEventListener("scroll", scheduleBannerHeightVar);
|
|
64
|
-
window.removeEventListener("resize", scheduleBannerHeightVar);
|
|
65
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
66
|
-
document.documentElement.style.setProperty("--site-banner-height", "0px");
|
|
67
|
-
});
|
|
68
|
-
</script>
|
|
69
|
-
|
|
70
|
-
<template>
|
|
71
|
-
<div
|
|
72
|
-
v-if="visible"
|
|
73
|
-
ref="bannerElement"
|
|
74
|
-
role="region"
|
|
75
|
-
:aria-label="banner.text"
|
|
76
|
-
class="relative z-30 bg-brand px-10 py-2.5 text-center text-sm leading-5 font-medium text-brand-foreground"
|
|
77
|
-
>
|
|
78
|
-
<span class="mx-auto block max-w-[min(100%,52rem)]">
|
|
79
|
-
{{ banner.text }}
|
|
80
|
-
<NuxtLink
|
|
81
|
-
v-if="banner.linkHref"
|
|
82
|
-
:to="banner.linkHref"
|
|
83
|
-
class="ml-1.5 inline-block underline underline-offset-2 opacity-90 transition-opacity hover:opacity-100"
|
|
84
|
-
>
|
|
85
|
-
{{ banner.linkLabel }}
|
|
86
|
-
</NuxtLink>
|
|
87
|
-
</span>
|
|
88
|
-
<button
|
|
89
|
-
type="button"
|
|
90
|
-
class="absolute top-1/2 right-2 flex size-8 -translate-y-1/2 items-center justify-center rounded p-1 opacity-70 transition-opacity hover:opacity-100 focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-brand-foreground/50 focus-visible:outline-none"
|
|
91
|
-
:aria-label="t('banner.dismiss')"
|
|
92
|
-
@click="dismissed = true"
|
|
93
|
-
>
|
|
94
|
-
<Icon name="lucide:x" class="size-3.5" aria-hidden="true" />
|
|
95
|
-
</button>
|
|
96
|
-
</div>
|
|
97
|
-
</template>
|