@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.
Files changed (296) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/LICENSE +1 -1
  3. package/README.md +206 -54
  4. package/app/app.config.ts +42 -55
  5. package/app/assets/docs.css +555 -0
  6. package/app/components/DocsBanner.vue +29 -0
  7. package/app/components/DocsExample.vue +43 -0
  8. package/app/components/DocsFooter.vue +19 -0
  9. package/app/components/DocsHeader.vue +112 -0
  10. package/app/components/DocsLanding.vue +55 -0
  11. package/app/components/DocsLanguage.vue +29 -0
  12. package/app/components/DocsNavTree.vue +38 -0
  13. package/app/components/DocsPage.vue +84 -0
  14. package/app/components/DocsPageActions.vue +47 -0
  15. package/app/components/DocsPost.vue +58 -0
  16. package/app/components/DocsSearch.vue +134 -0
  17. package/app/components/DocsShell.vue +20 -0
  18. package/app/components/DocsSidebar.vue +18 -0
  19. package/app/components/DocsTable.vue +11 -0
  20. package/app/components/DocsThemeToggle.vue +45 -0
  21. package/app/components/DocsToc.vue +73 -0
  22. package/app/composables/useDocs.ts +52 -0
  23. package/app/composables/useDocsBlog.ts +32 -0
  24. package/app/composables/useDocsCopy.ts +17 -0
  25. package/app/composables/useDocsPopover.ts +36 -0
  26. package/app/composables/useDocsSite.ts +10 -0
  27. package/app/docs-pages/blog.vue +47 -0
  28. package/app/docs-pages/changelog.vue +27 -0
  29. package/app/docs-pages/doc.vue +14 -0
  30. package/app/docs-pages/docs.vue +9 -0
  31. package/app/docs-pages/index.vue +12 -0
  32. package/app/docs-pages/post.vue +8 -0
  33. package/app/error.vue +23 -115
  34. package/app/layouts/default.vue +25 -7
  35. package/app/lib/blogTypes.ts +8 -0
  36. package/app/lib/docsFirst.ts +11 -0
  37. package/app/lib/docsInit.ts +18 -0
  38. package/app/lib/docsNav.ts +36 -0
  39. package/app/lib/docsPage.ts +44 -0
  40. package/app/lib/markdownComponents.ts +16 -0
  41. package/app/lib/previewToc.ts +18 -0
  42. package/dist/config.d.mts +232 -0
  43. package/dist/config.d.ts +232 -0
  44. package/dist/config.mjs +114 -0
  45. package/dist/pages.d.mts +5 -0
  46. package/dist/pages.d.ts +5 -0
  47. package/dist/pages.mjs +36 -0
  48. package/dist/shared/ginko-docs.BwbF7JBR.mjs +4 -0
  49. package/i18n/de.json +1 -0
  50. package/i18n/en.json +1 -0
  51. package/icons/README.md +2 -0
  52. package/icons/bluesky.svg +1 -0
  53. package/icons/claude.svg +1 -0
  54. package/icons/discord.svg +1 -0
  55. package/icons/github.svg +1 -0
  56. package/icons/linkedin.svg +1 -0
  57. package/icons/mastodon.svg +1 -0
  58. package/icons/openai.svg +1 -0
  59. package/icons/x.svg +1 -0
  60. package/icons/youtube.svg +1 -0
  61. package/nuxt.config.ts +34 -209
  62. package/package.json +43 -76
  63. package/public/_docs/fonts/LICENSE +188 -0
  64. package/public/_docs/fonts/inter-latin-wght-normal.woff2 +0 -0
  65. package/public/_docs/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
  66. package/public/_docs/fonts/jetbrains-mono-latin-500-normal.woff2 +0 -0
  67. package/server/feeds/blog-locale.get.ts +9 -0
  68. package/server/feeds/blog.get.ts +4 -0
  69. package/server/lib/blogFeed.ts +35 -0
  70. package/server/lib/rss.ts +57 -0
  71. package/server/mcp/handler.ts +108 -0
  72. package/server/routes/__ginko/docs-mcp.ts +35 -0
  73. package/shared/paths.ts +4 -0
  74. package/app/app.vue +0 -98
  75. package/app/assets/css/prose.css +0 -3240
  76. package/app/assets/css/tailwind.css +0 -394
  77. package/app/assets/css/theme-palettes.css +0 -309
  78. package/app/assets/css/theme-presets.css +0 -141
  79. package/app/components/OgImage/GinkoDocs.satori.vue +0 -238
  80. package/app/components/content/DocumentPageShell.vue +0 -55
  81. package/app/components/content/Feedback.vue +0 -102
  82. package/app/components/content/ImageZoomDialog.vue +0 -84
  83. package/app/components/content/PageMarkdownCopy.vue +0 -104
  84. package/app/components/content/imageZoom.ts +0 -25
  85. package/app/components/mdc/MdcAccordion.vue +0 -67
  86. package/app/components/mdc/MdcAccordionItem.vue +0 -42
  87. package/app/components/mdc/MdcApi.vue +0 -159
  88. package/app/components/mdc/MdcAside.vue +0 -23
  89. package/app/components/mdc/MdcCallout.vue +0 -61
  90. package/app/components/mdc/MdcCard.vue +0 -175
  91. package/app/components/mdc/MdcCards.vue +0 -30
  92. package/app/components/mdc/MdcCenter.vue +0 -71
  93. package/app/components/mdc/MdcCodeGroup.vue +0 -197
  94. package/app/components/mdc/MdcCodeTree.vue +0 -234
  95. package/app/components/mdc/MdcCollapse.vue +0 -61
  96. package/app/components/mdc/MdcColumn.vue +0 -70
  97. package/app/components/mdc/MdcDropcap.vue +0 -84
  98. package/app/components/mdc/MdcError.vue +0 -23
  99. package/app/components/mdc/MdcExcerpt.vue +0 -26
  100. package/app/components/mdc/MdcFigure.vue +0 -85
  101. package/app/components/mdc/MdcFiles.vue +0 -120
  102. package/app/components/mdc/MdcIdea.vue +0 -17
  103. package/app/components/mdc/MdcInfo.vue +0 -17
  104. package/app/components/mdc/MdcInlineToc.vue +0 -51
  105. package/app/components/mdc/MdcKbd.vue +0 -10
  106. package/app/components/mdc/MdcLayout.vue +0 -57
  107. package/app/components/mdc/MdcNote.vue +0 -17
  108. package/app/components/mdc/MdcQuiz.vue +0 -241
  109. package/app/components/mdc/MdcQuizQuestion.vue +0 -221
  110. package/app/components/mdc/MdcReadMore.vue +0 -70
  111. package/app/components/mdc/MdcSteps.vue +0 -59
  112. package/app/components/mdc/MdcSuccess.vue +0 -23
  113. package/app/components/mdc/MdcTab.vue +0 -17
  114. package/app/components/mdc/MdcTabs.vue +0 -150
  115. package/app/components/mdc/MdcTimeline.vue +0 -17
  116. package/app/components/mdc/MdcTimelineItem.vue +0 -40
  117. package/app/components/mdc/MdcWarning.vue +0 -23
  118. package/app/components/mdc/api.utils.ts +0 -132
  119. package/app/components/mdc/code-tree.utils.ts +0 -22
  120. package/app/components/mdc/icons.ts +0 -10
  121. package/app/components/mdc/quiz.utils.ts +0 -38
  122. package/app/components/prose/ProseA.vue +0 -27
  123. package/app/components/prose/ProseBlockquote.vue +0 -30
  124. package/app/components/prose/ProseCode.vue +0 -14
  125. package/app/components/prose/ProseEm.vue +0 -14
  126. package/app/components/prose/ProseH1.vue +0 -18
  127. package/app/components/prose/ProseH2.vue +0 -29
  128. package/app/components/prose/ProseH3.vue +0 -29
  129. package/app/components/prose/ProseH4.vue +0 -29
  130. package/app/components/prose/ProseH5.vue +0 -15
  131. package/app/components/prose/ProseH6.vue +0 -15
  132. package/app/components/prose/ProseHr.vue +0 -12
  133. package/app/components/prose/ProseImg.vue +0 -55
  134. package/app/components/prose/ProseLi.vue +0 -14
  135. package/app/components/prose/ProseOl.vue +0 -14
  136. package/app/components/prose/ProseP.vue +0 -14
  137. package/app/components/prose/ProsePre.vue +0 -180
  138. package/app/components/prose/ProseStrong.vue +0 -14
  139. package/app/components/prose/ProseTable.vue +0 -18
  140. package/app/components/prose/ProseTbody.vue +0 -14
  141. package/app/components/prose/ProseTd.vue +0 -14
  142. package/app/components/prose/ProseTh.vue +0 -14
  143. package/app/components/prose/ProseThead.vue +0 -14
  144. package/app/components/prose/ProseTr.vue +0 -14
  145. package/app/components/prose/ProseUl.vue +0 -14
  146. package/app/components/site/ModeToggle.vue +0 -81
  147. package/app/components/site/SiteBanner.vue +0 -97
  148. package/app/components/site/SiteFooter.vue +0 -90
  149. package/app/components/site/SiteHeader.vue +0 -371
  150. package/app/components/site/SiteHeroCode.vue +0 -173
  151. package/app/components/site/SiteInteractionLayer.vue +0 -42
  152. package/app/components/site/SiteLocaleSwitcher.vue +0 -190
  153. package/app/components/site/SiteLogoMark.vue +0 -12
  154. package/app/components/site/SiteSkipLink.vue +0 -14
  155. package/app/components/site/SiteSocialLinks.vue +0 -33
  156. package/app/components/site/header-utils.ts +0 -3
  157. package/app/components/site/mode-toggle.utils.ts +0 -18
  158. package/app/components/ui/badge/Badge.vue +0 -28
  159. package/app/components/ui/badge/index.ts +0 -24
  160. package/app/components/ui/button/Button.vue +0 -31
  161. package/app/components/ui/button/index.ts +0 -35
  162. package/app/components/ui/collapsible/Collapsible.vue +0 -15
  163. package/app/components/ui/collapsible/CollapsibleContent.vue +0 -25
  164. package/app/components/ui/collapsible/CollapsibleTrigger.vue +0 -12
  165. package/app/components/ui/collapsible/index.ts +0 -3
  166. package/app/components/ui/dropdown-menu/DropdownMenu.vue +0 -15
  167. package/app/components/ui/dropdown-menu/DropdownMenuContent.vue +0 -50
  168. package/app/components/ui/dropdown-menu/DropdownMenuItem.vue +0 -41
  169. package/app/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +0 -15
  170. package/app/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +0 -37
  171. package/app/components/ui/dropdown-menu/DropdownMenuSeparator.vue +0 -23
  172. package/app/components/ui/dropdown-menu/DropdownMenuTrigger.vue +0 -14
  173. package/app/components/ui/dropdown-menu/index.ts +0 -7
  174. package/app/components/ui/kbd/Kbd.vue +0 -23
  175. package/app/components/ui/kbd/index.ts +0 -21
  176. package/app/components/ui/scroll-area/ScrollArea.vue +0 -39
  177. package/app/components/ui/scroll-area/ScrollBar.vue +0 -33
  178. package/app/components/ui/scroll-area/index.ts +0 -2
  179. package/app/components/ui/separator/Separator.vue +0 -27
  180. package/app/components/ui/separator/index.ts +0 -1
  181. package/app/components/ui/sheet/Sheet.vue +0 -15
  182. package/app/components/ui/sheet/SheetContent.vue +0 -59
  183. package/app/components/ui/sheet/SheetDescription.vue +0 -21
  184. package/app/components/ui/sheet/SheetOverlay.vue +0 -26
  185. package/app/components/ui/sheet/SheetTitle.vue +0 -21
  186. package/app/components/ui/sheet/SheetTrigger.vue +0 -12
  187. package/app/components/ui/sheet/index.ts +0 -5
  188. package/app/components/ui/tabs/Tabs.vue +0 -24
  189. package/app/components/ui/tabs/TabsList.vue +0 -26
  190. package/app/components/ui/tabs/TabsTrigger.vue +0 -28
  191. package/app/components/ui/tabs/index.ts +0 -3
  192. package/app/composables/site-navigation.utils.ts +0 -133
  193. package/app/composables/useCanonicalUrl.ts +0 -9
  194. package/app/composables/useContentRouteAlternates.ts +0 -35
  195. package/app/composables/useGinkoAnalytics.ts +0 -52
  196. package/app/composables/useGinkoDocsConfig.ts +0 -6
  197. package/app/composables/useGinkoOgImage.ts +0 -20
  198. package/app/composables/useLocalizedPath.ts +0 -12
  199. package/app/composables/useLocalizedRouteSwitch.ts +0 -31
  200. package/app/composables/useMetaKey.ts +0 -18
  201. package/app/composables/usePageMarkdownActions.ts +0 -79
  202. package/app/composables/useProseAppearance.ts +0 -24
  203. package/app/composables/useSchemaJsonLd.ts +0 -25
  204. package/app/composables/useSiteNavigation.ts +0 -64
  205. package/app/config/site.utils.ts +0 -36
  206. package/app/features/docs/components/DocsBreadcrumb.vue +0 -37
  207. package/app/features/docs/components/DocsContributeLinks.vue +0 -75
  208. package/app/features/docs/components/DocsMobileToc.vue +0 -108
  209. package/app/features/docs/components/DocsPageContent.vue +0 -234
  210. package/app/features/docs/components/DocsPageNav.vue +0 -57
  211. package/app/features/docs/components/DocsSidebar.vue +0 -145
  212. package/app/features/docs/components/DocsSidebarDropdown.vue +0 -70
  213. package/app/features/docs/components/DocsSidebarItem.vue +0 -122
  214. package/app/features/docs/components/DocsSidebarList.vue +0 -35
  215. package/app/features/docs/components/DocsSidebarRow.vue +0 -27
  216. package/app/features/docs/components/DocsSidebarTabs.vue +0 -59
  217. package/app/features/docs/components/DocsToc.vue +0 -106
  218. package/app/features/docs/composables/useDocsNavigation.ts +0 -29
  219. package/app/features/docs/composables/useDocsNavigationData.ts +0 -18
  220. package/app/features/docs/composables/useRevealActive.ts +0 -58
  221. package/app/features/docs/composables/useScrollspy.ts +0 -135
  222. package/app/features/docs/docs-navigation.ts +0 -157
  223. package/app/features/docs/toc-context.ts +0 -6
  224. package/app/features/search/command-center.ts +0 -110
  225. package/app/features/search/components/SiteCommandCenter.vue +0 -359
  226. package/app/features/search/components/SiteSearchPageHighlight.vue +0 -126
  227. package/app/features/search/useCommandCenter.ts +0 -292
  228. package/app/layouts/blog.vue +0 -15
  229. package/app/layouts/docs.vue +0 -20
  230. package/app/lib/errors.ts +0 -37
  231. package/app/lib/schema-org.ts +0 -38
  232. package/app/pages/blog/[slug].vue +0 -228
  233. package/app/pages/blog/index.vue +0 -130
  234. package/app/pages/docs/[...slug].vue +0 -10
  235. package/app/pages/docs/index.vue +0 -19
  236. package/app/pages/index.vue +0 -278
  237. package/app/plugins/ginko-docs-theme.ts +0 -14
  238. package/app/plugins/ssr-width.ts +0 -6
  239. package/app/utils/content.ts +0 -67
  240. package/app/utils/file-icons.ts +0 -90
  241. package/app/utils/index.ts +0 -7
  242. package/app/utils/repository.ts +0 -20
  243. package/components.ts +0 -9
  244. package/content-collections.ts +0 -89
  245. package/content.js +0 -200
  246. package/content.ts +0 -104
  247. package/i18n/i18n.config.ts +0 -10
  248. package/i18n/locales.ts +0 -81
  249. package/i18n/messages/global/banner.ts +0 -8
  250. package/i18n/messages/global/blog.ts +0 -18
  251. package/i18n/messages/global/command.ts +0 -49
  252. package/i18n/messages/global/docs.ts +0 -36
  253. package/i18n/messages/global/errors.ts +0 -36
  254. package/i18n/messages/global/feedback.ts +0 -11
  255. package/i18n/messages/global/index.ts +0 -21
  256. package/i18n/messages/global/nav.ts +0 -26
  257. package/i18n/messages/global/site.ts +0 -4
  258. package/i18n/messages/global/theme.ts +0 -9
  259. package/i18n/messages/index.ts +0 -20
  260. package/i18n/messages/localize.ts +0 -35
  261. package/i18n/routes.ts +0 -33
  262. package/icon-bundle.ts +0 -116
  263. package/index.d.ts +0 -37
  264. package/modules/analytics-boundary.ts +0 -23
  265. package/modules/feature-routing.ts +0 -68
  266. package/modules/syntax-highlighting.ts +0 -120
  267. package/public/fonts/public-sans/LICENSE +0 -93
  268. package/public/fonts/public-sans/README.md +0 -12
  269. package/public/fonts/public-sans/public-sans-400-normal-latin.woff +0 -0
  270. package/public/fonts/public-sans/public-sans-500-normal-latin.woff +0 -0
  271. package/public/fonts/public-sans/public-sans-600-normal-latin.woff +0 -0
  272. package/public/fonts/public-sans/public-sans-700-normal-latin.woff +0 -0
  273. package/runtime/generate-favicons.mjs +0 -124
  274. package/runtime/server/agent-markdown.ts +0 -19
  275. package/server/api/_ginko-docs/redirects.get.ts +0 -28
  276. package/server/mcp/tools/get-page.ts +0 -14
  277. package/server/mcp/tools/list-pages.ts +0 -10
  278. package/server/middleware/redirects.ts +0 -22
  279. package/server/plugins/agent-markdown.ts +0 -6
  280. package/server/plugins/sitemap-policy.ts +0 -12
  281. package/server/routes/.well-known/ai-catalog.json.get.ts +0 -10
  282. package/server/routes/[locale]/blog/rss.xml.get.ts +0 -13
  283. package/server/routes/blog/rss.xml.get.ts +0 -5
  284. package/server/routes/mcp/server-card.get.ts +0 -14
  285. package/server/utils/blog-feed.ts +0 -51
  286. package/server/utils/feed.ts +0 -70
  287. package/server/utils/mcp-server-card.ts +0 -45
  288. package/server/utils/redirects.ts +0 -38
  289. package/server/utils/redirects.utils.ts +0 -58
  290. package/server/utils/sitemap.ts +0 -45
  291. package/shared/route-slugs.ts +0 -5
  292. package/shared/theme-palettes.ts +0 -37
  293. package/shared/theme-presets.ts +0 -3
  294. package/shared/types/app-config.ts +0 -172
  295. package/shared/types/nuxt-config.ts +0 -14
  296. package/tags.ts +0 -192
@@ -1,20 +0,0 @@
1
- import { defineOgImage } from "#imports";
2
- import { useGinkoDocsConfig } from "./useGinkoDocsConfig";
3
-
4
- export interface GinkoOgImageProps {
5
- title?: string;
6
- description?: string;
7
- locale?: string;
8
- [key: string]: unknown;
9
- }
10
-
11
- /**
12
- * Declares the page's social image using the configured OgImage template.
13
- * No-op when the consumer sets `ginkoDocs.ogImage.enabled: false`.
14
- */
15
- export function useGinkoOgImage(props?: GinkoOgImageProps) {
16
- const config = useGinkoDocsConfig();
17
- if (config.ogImage?.enabled === false) return;
18
- const component = config.ogImage?.component ?? "GinkoDocs";
19
- defineOgImage(component as never, props as never);
20
- }
@@ -1,12 +0,0 @@
1
- import { useI18n } from "#imports";
2
- import { isLocaleCode, localizedPath } from "../../i18n/locales";
3
- import type { LocalizedRouteKey } from "../../i18n/routes";
4
-
5
- export function useLocalizedPath() {
6
- const { locale, t } = useI18n();
7
-
8
- return (key: LocalizedRouteKey) => {
9
- const path = t(`routes.${key}`);
10
- return isLocaleCode(locale.value) ? localizedPath(locale.value, path) : path;
11
- };
12
- }
@@ -1,31 +0,0 @@
1
- import { useRoute, useSwitchLocalePath } from "#imports";
2
- import type { RouteLocationRaw } from "vue-router";
3
- import { useContentRouteAlternates } from "./useContentRouteAlternates";
4
- import { isLocaleCode } from "../../i18n/locales";
5
-
6
- export function useLocalizedRouteSwitch() {
7
- const route = useRoute();
8
- const switchLocalePath = useSwitchLocalePath();
9
- const { current: alternates } = useContentRouteAlternates();
10
-
11
- function switchPathname(targetLocale: string) {
12
- if (!isLocaleCode(targetLocale)) {
13
- return route.path;
14
- }
15
-
16
- const configuredLocale = targetLocale as Parameters<typeof switchLocalePath>[0];
17
- return (
18
- alternates.value.find((alternate) => alternate.locale === targetLocale)?.path ||
19
- switchLocalePath(configuredLocale)
20
- );
21
- }
22
-
23
- function switchPath(targetLocale: string): RouteLocationRaw {
24
- return { path: switchPathname(targetLocale), query: route.query, hash: route.hash };
25
- }
26
-
27
- return {
28
- switchPath,
29
- switchPathname,
30
- };
31
- }
@@ -1,18 +0,0 @@
1
- import { onMounted, ref, type Ref } from "vue";
2
-
3
- /**
4
- * Platform-aware modifier key label. Defaults to "Ctrl" during SSR and
5
- * upgrades to "⌘" on Apple platforms after mount (onMounted is client-only,
6
- * so hydration stays consistent).
7
- */
8
- export function useMetaKey(): Ref<string> {
9
- const metaSymbol = ref("Ctrl");
10
-
11
- onMounted(() => {
12
- if (typeof navigator !== "undefined" && navigator.userAgent.includes("Macintosh")) {
13
- metaSymbol.value = "⌘";
14
- }
15
- });
16
-
17
- return metaSymbol;
18
- }
@@ -1,79 +0,0 @@
1
- import { agentRawPathForRoute } from "@lupinum/ginko-content/agent-paths";
2
- import { useClipboard } from "@vueuse/core";
3
- import { computed, onBeforeUnmount, ref } from "vue";
4
- import { useRoute } from "#imports";
5
- import { useGinkoDocsConfig } from "./useGinkoDocsConfig";
6
-
7
- export type PageMarkdownAction = "markdown" | "link" | "mcp";
8
- export type PageMarkdownActionResult = "success" | "error";
9
-
10
- export function usePageMarkdownActions() {
11
- const route = useRoute();
12
- const config = useGinkoDocsConfig();
13
- const { copy } = useClipboard({ legacy: true });
14
- const result = ref<{ action: PageMarkdownAction; status: PageMarkdownActionResult } | null>(null);
15
- let resetTimer: ReturnType<typeof setTimeout> | undefined;
16
-
17
- const rawPath = computed(() => agentRawPathForRoute(route.path));
18
- const rawUrl = computed(() => new URL(rawPath.value, config.site.url).toString());
19
- const mcpUrl = computed(() => new URL("/mcp", config.site.url).toString());
20
- const chatGptUrl = computed(
21
- () =>
22
- `https://chatgpt.com/?hints=search&q=${encodeURIComponent(`Read ${rawUrl.value} so I can ask questions about it.`)}`,
23
- );
24
- const claudeUrl = computed(
25
- () =>
26
- `https://claude.ai/new?q=${encodeURIComponent(`Read ${rawUrl.value} so I can ask questions about it.`)}`,
27
- );
28
- const actions = computed(() => ({
29
- chatGpt: config.markdownActions?.chatGpt !== false,
30
- claude: config.markdownActions?.claude !== false,
31
- mcp: config.markdownActions?.mcp !== false,
32
- }));
33
-
34
- function setResult(action: PageMarkdownAction, status: PageMarkdownActionResult) {
35
- if (resetTimer) clearTimeout(resetTimer);
36
- result.value = { action, status };
37
- resetTimer = setTimeout(
38
- () => {
39
- result.value = null;
40
- },
41
- status === "success" ? 1800 : 4000,
42
- );
43
- }
44
-
45
- async function run(action: PageMarkdownAction, operation: () => Promise<void>) {
46
- try {
47
- await operation();
48
- setResult(action, "success");
49
- } catch {
50
- setResult(action, "error");
51
- }
52
- }
53
-
54
- const copyValue = (value: string, action: Exclude<PageMarkdownAction, "markdown">) =>
55
- run(action, () => copy(value));
56
-
57
- const copyMarkdown = () =>
58
- run("markdown", async () => {
59
- const response = await fetch(rawPath.value);
60
- if (!response.ok) throw new Error(`Markdown request failed with ${response.status}`);
61
- await copy(await response.text());
62
- });
63
-
64
- onBeforeUnmount(() => {
65
- if (resetTimer) clearTimeout(resetTimer);
66
- });
67
-
68
- return {
69
- actions,
70
- chatGptUrl,
71
- claudeUrl,
72
- copyMarkdown,
73
- copyValue,
74
- mcpUrl,
75
- rawPath,
76
- rawUrl,
77
- result,
78
- };
79
- }
@@ -1,24 +0,0 @@
1
- import { computed, type MaybeRefOrGetter, toValue } from "vue";
2
- import type { GinkoDocsProseAppearance, GinkoDocsProseFamily } from "../../shared/types/app-config";
3
- import { useGinkoDocsConfig } from "./useGinkoDocsConfig";
4
-
5
- const DEFAULT_APPEARANCE: GinkoDocsProseAppearance = "quiet";
6
-
7
- function normalizeAppearance(value: unknown): GinkoDocsProseAppearance | undefined {
8
- return value === "quiet" || value === "tint" ? value : undefined;
9
- }
10
-
11
- export function useProseAppearance(
12
- family: GinkoDocsProseFamily,
13
- appearance?: MaybeRefOrGetter<string | undefined>,
14
- ) {
15
- const config = useGinkoDocsConfig();
16
-
17
- return computed<GinkoDocsProseAppearance>(
18
- () =>
19
- normalizeAppearance(toValue(appearance)) ??
20
- normalizeAppearance(config.prose?.components?.[family]) ??
21
- normalizeAppearance(config.prose?.appearance) ??
22
- DEFAULT_APPEARANCE,
23
- );
24
- }
@@ -1,25 +0,0 @@
1
- import { toValue, type MaybeRefOrGetter } from "vue";
2
- import { useHead } from "#imports";
3
-
4
- export type SchemaJsonNode = Record<string, unknown>;
5
-
6
- export function useSchemaJsonLd(schemas: MaybeRefOrGetter<SchemaJsonNode[]>) {
7
- useHead(() => {
8
- const graph = toValue(schemas).filter(Boolean);
9
-
10
- return {
11
- script: graph.length
12
- ? [
13
- {
14
- type: "application/ld+json",
15
- "data-schema-org": "true",
16
- innerHTML: JSON.stringify({
17
- "@context": "https://schema.org",
18
- "@graph": graph,
19
- }),
20
- },
21
- ]
22
- : [],
23
- };
24
- });
25
- }
@@ -1,64 +0,0 @@
1
- import { getLocalizedSiteText } from "#ginko-docs/config/site.utils";
2
- import { useI18n, useRouter } from "#imports";
3
- import { useLocalizedPath } from "#ginko-docs/composables/useLocalizedPath";
4
- import { computed } from "vue";
5
- import { useGinkoDocsConfig } from "./useGinkoDocsConfig";
6
- import {
7
- resolveBanner,
8
- resolveMainNav,
9
- resolveSocialLinks,
10
- type NavItem,
11
- } from "./site-navigation.utils";
12
-
13
- export const useSiteNavigation = () => {
14
- const config = useGinkoDocsConfig();
15
- const { locale, t } = useI18n();
16
- const router = useRouter();
17
- const path = useLocalizedPath();
18
-
19
- const site = computed(() => ({
20
- name: getLocalizedSiteText(config.site.name, locale.value),
21
- description: getLocalizedSiteText(config.site.description, locale.value),
22
- logo: config.site.logo,
23
- url: config.site.url,
24
- lupinumAttribution: config.site.lupinumAttribution,
25
- legalLinks: config.site.legalLinks.map((link) => {
26
- const href = getLocalizedSiteText(link.to, locale.value);
27
- return {
28
- label: getLocalizedSiteText(link.label, locale.value),
29
- href,
30
- external: /^https?:\/\//.test(href),
31
- };
32
- }),
33
- }));
34
-
35
- const blogPath = computed(() => path("blog"));
36
- const blogExists = computed(() =>
37
- router.getRoutes().some((route) => route.path === blogPath.value),
38
- );
39
-
40
- const banner = computed(() =>
41
- resolveBanner(config.banner, {
42
- locale: locale.value,
43
- defaultText: t("banner.text"),
44
- defaultLinkLabel: t("banner.linkLabel"),
45
- }),
46
- );
47
-
48
- const socialLinks = computed<NavItem[]>(() => resolveSocialLinks(config.social));
49
-
50
- const mainNav = computed<NavItem[]>(() =>
51
- resolveMainNav(config.nav.links, {
52
- locale: locale.value,
53
- docsPath: path("docs"),
54
- blogPath: blogPath.value,
55
- blogExists: blogExists.value,
56
- docsLabel: t("nav.documentation"),
57
- blogLabel: t("nav.blog"),
58
- docsDescription: t("nav.docsDescription"),
59
- blogDescription: t("nav.blogDescription"),
60
- }),
61
- );
62
-
63
- return { site, banner, mainNav, socialLinks };
64
- };
@@ -1,36 +0,0 @@
1
- import type { GinkoDocsLocalizedText } from "../../shared/types/app-config";
2
- import { defaultLocale, type LocaleCode } from "../../i18n/locales";
3
-
4
- export function getLocalizedSiteText(
5
- value: GinkoDocsLocalizedText,
6
- locale: string,
7
- fallbackLocale: LocaleCode = defaultLocale,
8
- ): string {
9
- if (typeof value === "string") return value;
10
- return value[locale as LocaleCode] ?? value[fallbackLocale] ?? Object.values(value)[0] ?? "";
11
- }
12
-
13
- function isLocalSiteUrl(value: string) {
14
- try {
15
- const host = new URL(value).hostname;
16
- return host === "localhost" || host === "127.0.0.1" || host === "::1";
17
- } catch {
18
- return false;
19
- }
20
- }
21
-
22
- export function resolveSiteUrl(
23
- canonicalUrl: string,
24
- options: {
25
- envUrl?: string;
26
- mode?: string;
27
- } = {},
28
- ) {
29
- const { envUrl, mode } = options;
30
-
31
- if (!envUrl) return canonicalUrl;
32
- if (isLocalSiteUrl(envUrl) && mode !== "development" && mode !== "test") {
33
- return canonicalUrl;
34
- }
35
- return envUrl;
36
- }
@@ -1,37 +0,0 @@
1
- <script setup lang="ts">
2
- import type { HTMLAttributes } from "vue";
3
- import { cn } from "#ginko-docs/utils";
4
- import { useI18n } from "#imports";
5
-
6
- const props = defineProps<{
7
- items: { title: string; path?: string }[];
8
- class?: HTMLAttributes["class"];
9
- }>();
10
-
11
- const { t } = useI18n();
12
- </script>
13
-
14
- <template>
15
- <nav
16
- v-if="items.length"
17
- :class="cn('flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground', props.class)"
18
- :aria-label="t('docs.breadcrumbs')"
19
- >
20
- <template v-for="(item, index) in items" :key="item.path ?? item.title">
21
- <Icon
22
- v-if="index > 0"
23
- name="lucide:chevron-right"
24
- class="size-3.5 text-border"
25
- aria-hidden="true"
26
- />
27
- <NuxtLink
28
- v-if="item.path"
29
- :to="item.path"
30
- class="rounded-sm transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
31
- >
32
- {{ item.title }}
33
- </NuxtLink>
34
- <span v-else>{{ item.title }}</span>
35
- </template>
36
- </nav>
37
- </template>
@@ -1,75 +0,0 @@
1
- <script setup lang="ts">
2
- import type { GinkoDocsAppConfig } from "../../../../shared/types/app-config";
3
- import { computed } from "vue";
4
- import { useAppConfig, useI18n, useRoute } from "#imports";
5
- import { buildRepoEditUrl, buildRepoIssueUrl } from "#ginko-docs/utils/repository";
6
-
7
- const props = withDefaults(
8
- defineProps<{
9
- stem?: string;
10
- extension?: string;
11
- title: string;
12
- variant?: "article" | "rail";
13
- }>(),
14
- {
15
- variant: "article",
16
- },
17
- );
18
-
19
- const route = useRoute();
20
- const { t } = useI18n();
21
- const repository = (useAppConfig().ginkoDocs as GinkoDocsAppConfig).repository;
22
-
23
- const sourcePath = computed(() => {
24
- if (!repository || !props.stem) return null;
25
- const directory = repository.contentDirectory?.replace(/^\/+|\/+$/g, "") ?? "content";
26
- const extension = props.extension?.replace(/^\./, "") || "md";
27
- return `${directory}/${props.stem}.${extension}`;
28
- });
29
-
30
- const editUrl = computed(() =>
31
- repository && sourcePath.value ? buildRepoEditUrl(repository, sourcePath.value) : null,
32
- );
33
-
34
- const issueUrl = computed(() =>
35
- repository
36
- ? buildRepoIssueUrl(repository, {
37
- title: t("docs.issueTitle", { title: props.title }),
38
- body: t("docs.issueBody", { path: route.path }),
39
- })
40
- : null,
41
- );
42
- </script>
43
-
44
- <template>
45
- <div
46
- v-if="repository"
47
- :class="
48
- variant === 'rail'
49
- ? 'flex flex-col gap-2.5 text-sm'
50
- : 'flex flex-wrap items-center gap-x-4 gap-y-2 text-sm'
51
- "
52
- :aria-label="t('docs.contribute')"
53
- >
54
- <a
55
- v-if="editUrl"
56
- :href="editUrl"
57
- target="_blank"
58
- rel="noopener noreferrer"
59
- class="inline-flex min-h-9 items-center gap-1.5 font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
60
- >
61
- <Icon name="lucide:pen-line" class="size-4" aria-hidden="true" />
62
- {{ t("docs.editPage") }}
63
- </a>
64
- <a
65
- v-if="issueUrl"
66
- :href="issueUrl"
67
- target="_blank"
68
- rel="noopener noreferrer"
69
- class="inline-flex min-h-9 items-center gap-1.5 font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
70
- >
71
- <Icon name="lucide:circle-alert" class="size-4" aria-hidden="true" />
72
- {{ t("docs.reportIssue") }}
73
- </a>
74
- </div>
75
- </template>
@@ -1,108 +0,0 @@
1
- <script setup lang="ts">
2
- import type { HTMLAttributes } from "vue";
3
- import { ref, watch } from "vue";
4
- import {
5
- Sheet,
6
- SheetContent,
7
- SheetDescription,
8
- SheetTitle,
9
- SheetTrigger,
10
- } from "#ginko-docs/components/ui/sheet";
11
- import { cn } from "#ginko-docs/utils";
12
- import type { FlatTocItem } from "#ginko-docs/utils/content";
13
- import DocsToc from "./DocsToc.vue";
14
- import { useI18n, useRoute } from "#imports";
15
-
16
- const props = defineProps<{
17
- items: FlatTocItem[];
18
- activeIds?: string[];
19
- pageTitle?: string;
20
- class?: HTMLAttributes["class"];
21
- }>();
22
-
23
- const sidebarOpen = ref(false);
24
- const tocOpen = ref(false);
25
- const route = useRoute();
26
- const { t } = useI18n();
27
-
28
- watch(
29
- () => route.hash,
30
- () => {
31
- tocOpen.value = false;
32
- },
33
- );
34
- watch(
35
- () => route.path,
36
- () => {
37
- sidebarOpen.value = false;
38
- tocOpen.value = false;
39
- },
40
- );
41
- </script>
42
-
43
- <template>
44
- <div
45
- :class="
46
- cn(
47
- 'sticky top-[var(--site-header-height)] z-30 flex h-11 shrink-0 items-center justify-between border-b border-border bg-background/90 px-4 backdrop-blur-md md:px-6 xl:hidden',
48
- props.class,
49
- )
50
- "
51
- >
52
- <Sheet v-model:open="sidebarOpen">
53
- <SheetTrigger as-child>
54
- <button
55
- type="button"
56
- class="-ml-1 flex h-8 min-w-0 items-center gap-2 rounded-lg px-2 text-sm font-medium text-foreground transition-colors hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
57
- :aria-label="t('docs.pageNavigation')"
58
- >
59
- <Icon
60
- name="lucide:panel-left-open"
61
- class="size-4 shrink-0 text-muted-foreground"
62
- aria-hidden="true"
63
- />
64
- <span class="truncate">{{ pageTitle ?? t("docs.fallbackTitle") }}</span>
65
- </button>
66
- </SheetTrigger>
67
-
68
- <SheetContent
69
- side="left"
70
- class="flex w-[var(--docs-sidebar-width)] max-w-[85vw] flex-col gap-0 p-0"
71
- >
72
- <div class="border-b border-border px-4 py-3">
73
- <SheetTitle class="text-sm font-semibold">{{ t("docs.label") }}</SheetTitle>
74
- <SheetDescription class="sr-only">{{ t("docs.pageNavigation") }}</SheetDescription>
75
- </div>
76
- <div class="min-h-0 flex-1">
77
- <DocsSidebar variant="drawer" />
78
- </div>
79
- </SheetContent>
80
- </Sheet>
81
-
82
- <Sheet v-if="items.length" v-model:open="tocOpen">
83
- <SheetTrigger as-child>
84
- <button
85
- type="button"
86
- class="-mr-1 flex h-7 shrink-0 items-center gap-1.5 rounded-md px-2.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
87
- >
88
- <Icon name="lucide:list" class="size-3.5" aria-hidden="true" />
89
- <span>{{ t("docs.toc") }}</span>
90
- </button>
91
- </SheetTrigger>
92
-
93
- <SheetContent side="bottom" class="flex max-h-[85dvh] flex-col gap-0 rounded-t-2xl p-0">
94
- <div class="flex shrink-0 flex-col items-center border-b border-border px-6 pt-3 pb-4">
95
- <div class="mb-4 h-1 w-10 rounded-full bg-border" />
96
- <SheetTitle class="self-start text-sm font-semibold">{{ t("docs.toc") }}</SheetTitle>
97
- <SheetDescription class="sr-only">{{
98
- pageTitle ?? t("docs.fallbackTitle")
99
- }}</SheetDescription>
100
- </div>
101
-
102
- <div class="flex-1 overflow-y-auto px-6 py-5" @click="tocOpen = false">
103
- <DocsToc :items="items" :active-ids="activeIds" :show-title="false" />
104
- </div>
105
- </SheetContent>
106
- </Sheet>
107
- </div>
108
- </template>