@lupinum/ginko-docs 0.4.0-rc.3 → 0.4.0-rc.5
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/README.md +1 -1
- package/app/app.config.ts +1 -0
- package/app/assets/css/tailwind.css +7 -0
- package/app/assets/css/theme-presets.css +141 -0
- package/app/components/site/SiteBanner.vue +2 -2
- package/app/pages/index.vue +2 -2
- package/app/plugins/ginko-docs-theme.ts +1 -0
- package/package.json +2 -1
- package/server/routes/.well-known/ai-catalog.json.get.ts +3 -6
- package/server/routes/mcp/server-card.get.ts +3 -6
- package/shared/theme-presets.ts +3 -0
- package/shared/types/app-config.ts +4 -0
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ Use this package when a Nuxt application needs documentation routes, navigation,
|
|
|
29
29
|
## Installation
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
pnpm add -D @lupinum/ginko-docs@0.4.0-rc.
|
|
32
|
+
pnpm add -D @lupinum/ginko-docs@0.4.0-rc.5 @lupinum/ginko-content@1.0.0-beta.5
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
```ts
|
package/app/app.config.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
2
|
@import "tw-animate-css";
|
|
3
3
|
@import "./theme-palettes.css";
|
|
4
|
+
@import "./theme-presets.css";
|
|
4
5
|
@source "../../**/*.{vue,ts}";
|
|
5
6
|
|
|
6
7
|
@custom-variant dark (&:is(.dark *));
|
|
@@ -29,6 +30,8 @@
|
|
|
29
30
|
--color-popover-foreground: var(--popover-foreground);
|
|
30
31
|
--color-primary: var(--primary);
|
|
31
32
|
--color-primary-foreground: var(--primary-foreground);
|
|
33
|
+
--color-brand: var(--brand);
|
|
34
|
+
--color-brand-foreground: var(--brand-foreground);
|
|
32
35
|
--color-secondary: var(--secondary);
|
|
33
36
|
--color-secondary-foreground: var(--secondary-foreground);
|
|
34
37
|
--color-muted: var(--muted);
|
|
@@ -147,6 +150,8 @@
|
|
|
147
150
|
--popover-foreground: var(--theme-neutral-950);
|
|
148
151
|
--primary: var(--theme-primary-light);
|
|
149
152
|
--primary-foreground: var(--theme-primary-light-foreground);
|
|
153
|
+
--brand: var(--primary);
|
|
154
|
+
--brand-foreground: var(--primary-foreground);
|
|
150
155
|
--secondary: var(--theme-neutral-100);
|
|
151
156
|
--secondary-foreground: var(--theme-neutral-900);
|
|
152
157
|
--muted: var(--theme-neutral-100);
|
|
@@ -223,6 +228,8 @@
|
|
|
223
228
|
--popover-foreground: var(--theme-neutral-50);
|
|
224
229
|
--primary: var(--theme-primary-dark);
|
|
225
230
|
--primary-foreground: var(--theme-primary-dark-foreground);
|
|
231
|
+
--brand: var(--primary);
|
|
232
|
+
--brand-foreground: var(--primary-foreground);
|
|
226
233
|
--secondary: var(--theme-neutral-800);
|
|
227
234
|
--secondary-foreground: var(--theme-neutral-50);
|
|
228
235
|
--muted: var(--theme-neutral-800);
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/* Complete visual systems. Presets intentionally override palette selection;
|
|
2
|
+
use the default preset when neutral and primary must be configured alone. */
|
|
3
|
+
|
|
4
|
+
html[data-theme-preset="nuxt"] {
|
|
5
|
+
/* Official Nuxt green scale. */
|
|
6
|
+
--nuxt-green-50: #effdf5;
|
|
7
|
+
--nuxt-green-100: #d9fbe8;
|
|
8
|
+
--nuxt-green-200: #b3f5d1;
|
|
9
|
+
--nuxt-green-300: #75edae;
|
|
10
|
+
--nuxt-green-400: #00dc82;
|
|
11
|
+
--nuxt-green-500: #00c16a;
|
|
12
|
+
--nuxt-green-600: #00a155;
|
|
13
|
+
--nuxt-green-700: #007f45;
|
|
14
|
+
--nuxt-green-800: #016538;
|
|
15
|
+
--nuxt-green-900: #0a5331;
|
|
16
|
+
--nuxt-green-950: #052e16;
|
|
17
|
+
|
|
18
|
+
/* Nuxt uses Slate for neutral surfaces. */
|
|
19
|
+
--theme-neutral-50: var(--color-slate-50);
|
|
20
|
+
--theme-neutral-100: var(--color-slate-100);
|
|
21
|
+
--theme-neutral-200: var(--color-slate-200);
|
|
22
|
+
--theme-neutral-300: var(--color-slate-300);
|
|
23
|
+
--theme-neutral-400: var(--color-slate-400);
|
|
24
|
+
--theme-neutral-500: var(--color-slate-500);
|
|
25
|
+
--theme-neutral-600: var(--color-slate-600);
|
|
26
|
+
--theme-neutral-700: var(--color-slate-700);
|
|
27
|
+
--theme-neutral-800: var(--color-slate-800);
|
|
28
|
+
--theme-neutral-900: var(--color-slate-900);
|
|
29
|
+
--theme-neutral-950: var(--color-slate-950);
|
|
30
|
+
|
|
31
|
+
/* Normal-size text needs the darker green in light mode. */
|
|
32
|
+
--theme-primary-light: var(--nuxt-green-700);
|
|
33
|
+
--theme-primary-light-foreground: #ffffff;
|
|
34
|
+
--theme-primary-light-ring: var(--nuxt-green-600);
|
|
35
|
+
--theme-primary-dark: var(--nuxt-green-400);
|
|
36
|
+
--theme-primary-dark-foreground: var(--nuxt-green-950);
|
|
37
|
+
--theme-primary-dark-ring: var(--nuxt-green-400);
|
|
38
|
+
|
|
39
|
+
/* Brand surfaces can use Nuxt green with its high-contrast navy foreground. */
|
|
40
|
+
--brand: var(--nuxt-green-400);
|
|
41
|
+
--brand-foreground: #020420;
|
|
42
|
+
|
|
43
|
+
--background: #ffffff;
|
|
44
|
+
--foreground: var(--color-slate-900);
|
|
45
|
+
--card: #ffffff;
|
|
46
|
+
--card-foreground: var(--color-slate-900);
|
|
47
|
+
--popover: #ffffff;
|
|
48
|
+
--popover-foreground: var(--color-slate-900);
|
|
49
|
+
--primary: var(--theme-primary-light);
|
|
50
|
+
--primary-foreground: var(--theme-primary-light-foreground);
|
|
51
|
+
--secondary: var(--color-slate-50);
|
|
52
|
+
--secondary-foreground: var(--color-slate-900);
|
|
53
|
+
--muted: var(--color-slate-50);
|
|
54
|
+
--muted-foreground: var(--color-slate-500);
|
|
55
|
+
--accent: var(--color-slate-100);
|
|
56
|
+
--accent-foreground: var(--color-slate-900);
|
|
57
|
+
--border: var(--color-slate-200);
|
|
58
|
+
--input: var(--color-slate-200);
|
|
59
|
+
--ring: var(--nuxt-green-600);
|
|
60
|
+
--code: var(--color-slate-50);
|
|
61
|
+
--code-foreground: var(--color-slate-900);
|
|
62
|
+
--code-border: var(--color-slate-200);
|
|
63
|
+
|
|
64
|
+
--hero-bg: #ffffff;
|
|
65
|
+
--hero-bg-muted: var(--color-slate-50);
|
|
66
|
+
--hero-blue: var(--nuxt-green-400);
|
|
67
|
+
--hero-blue-light: var(--nuxt-green-300);
|
|
68
|
+
--hero-blue-dark: var(--nuxt-green-700);
|
|
69
|
+
--hero-blue-muted: var(--nuxt-green-50);
|
|
70
|
+
--hero-mint: var(--nuxt-green-400);
|
|
71
|
+
--hero-mint-dark: var(--nuxt-green-700);
|
|
72
|
+
--hero-mint-muted: var(--nuxt-green-50);
|
|
73
|
+
--hero-mint-text: var(--nuxt-green-700);
|
|
74
|
+
--hero-yellow: var(--nuxt-green-400);
|
|
75
|
+
--hero-yellow-hover: var(--nuxt-green-500);
|
|
76
|
+
--hero-yellow-dark: var(--nuxt-green-700);
|
|
77
|
+
--hero-yellow-muted: var(--nuxt-green-50);
|
|
78
|
+
--hero-coral: var(--nuxt-green-400);
|
|
79
|
+
--hero-coral-light: var(--nuxt-green-300);
|
|
80
|
+
--hero-coral-dark: var(--nuxt-green-700);
|
|
81
|
+
--hero-coral-muted: var(--nuxt-green-50);
|
|
82
|
+
--hero-coral-text: var(--nuxt-green-700);
|
|
83
|
+
--hero-check: var(--nuxt-green-400);
|
|
84
|
+
--hero-white: #ffffff;
|
|
85
|
+
|
|
86
|
+
--agent-background: var(--color-slate-950);
|
|
87
|
+
--agent-foreground: var(--color-slate-100);
|
|
88
|
+
--agent-muted: var(--color-slate-400);
|
|
89
|
+
|
|
90
|
+
/* Nuxt UI-compatible aliases for consumer-owned examples. */
|
|
91
|
+
--ui-bg: var(--background);
|
|
92
|
+
--ui-bg-muted: var(--muted);
|
|
93
|
+
--ui-bg-elevated: var(--card);
|
|
94
|
+
--ui-bg-accented: var(--accent);
|
|
95
|
+
--ui-border: var(--border);
|
|
96
|
+
--ui-border-muted: var(--border);
|
|
97
|
+
--ui-border-accented: var(--border);
|
|
98
|
+
--ui-text: var(--foreground);
|
|
99
|
+
--ui-text-default: var(--foreground);
|
|
100
|
+
--ui-text-highlighted: var(--foreground);
|
|
101
|
+
--ui-text-muted: var(--muted-foreground);
|
|
102
|
+
--ui-text-dimmed: var(--muted-foreground);
|
|
103
|
+
--ui-text-toned: var(--muted-foreground);
|
|
104
|
+
--ui-primary: var(--primary);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
html.dark[data-theme-preset="nuxt"] {
|
|
108
|
+
--background: var(--color-slate-950);
|
|
109
|
+
--foreground: var(--color-slate-50);
|
|
110
|
+
--card: var(--color-slate-900);
|
|
111
|
+
--card-foreground: var(--color-slate-50);
|
|
112
|
+
--popover: var(--color-slate-900);
|
|
113
|
+
--popover-foreground: var(--color-slate-50);
|
|
114
|
+
--primary: var(--nuxt-green-400);
|
|
115
|
+
--primary-foreground: var(--nuxt-green-950);
|
|
116
|
+
--secondary: var(--color-slate-900);
|
|
117
|
+
--secondary-foreground: var(--color-slate-50);
|
|
118
|
+
--muted: var(--color-slate-900);
|
|
119
|
+
--muted-foreground: var(--color-slate-400);
|
|
120
|
+
--accent: var(--color-slate-800);
|
|
121
|
+
--accent-foreground: var(--color-slate-50);
|
|
122
|
+
--border: var(--color-slate-800);
|
|
123
|
+
--input: var(--color-slate-700);
|
|
124
|
+
--ring: var(--nuxt-green-400);
|
|
125
|
+
--code: var(--color-slate-900);
|
|
126
|
+
--code-foreground: var(--color-slate-50);
|
|
127
|
+
--code-border: var(--color-slate-800);
|
|
128
|
+
|
|
129
|
+
--hero-bg: var(--color-slate-950);
|
|
130
|
+
--hero-bg-muted: var(--color-slate-900);
|
|
131
|
+
--hero-blue-dark: var(--nuxt-green-400);
|
|
132
|
+
--hero-mint-dark: var(--nuxt-green-400);
|
|
133
|
+
--hero-yellow-dark: var(--nuxt-green-400);
|
|
134
|
+
--hero-coral-dark: var(--nuxt-green-400);
|
|
135
|
+
--hero-blue-muted: color-mix(in oklab, var(--nuxt-green-400) 12%, var(--color-slate-900));
|
|
136
|
+
--hero-mint-muted: var(--hero-blue-muted);
|
|
137
|
+
--hero-yellow-muted: var(--hero-blue-muted);
|
|
138
|
+
--hero-coral-muted: var(--hero-blue-muted);
|
|
139
|
+
--hero-mint-text: var(--nuxt-green-300);
|
|
140
|
+
--hero-coral-text: var(--nuxt-green-300);
|
|
141
|
+
}
|
|
@@ -73,7 +73,7 @@ onBeforeUnmount(() => {
|
|
|
73
73
|
ref="bannerElement"
|
|
74
74
|
role="region"
|
|
75
75
|
:aria-label="banner.text"
|
|
76
|
-
class="relative z-30 bg-
|
|
76
|
+
class="relative z-30 bg-brand px-10 py-2.5 text-center text-sm leading-5 font-medium text-brand-foreground"
|
|
77
77
|
>
|
|
78
78
|
<span class="mx-auto block max-w-[min(100%,52rem)]">
|
|
79
79
|
{{ banner.text }}
|
|
@@ -87,7 +87,7 @@ onBeforeUnmount(() => {
|
|
|
87
87
|
</span>
|
|
88
88
|
<button
|
|
89
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-
|
|
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
91
|
:aria-label="t('banner.dismiss')"
|
|
92
92
|
@click="dismissed = true"
|
|
93
93
|
>
|
package/app/pages/index.vue
CHANGED
|
@@ -127,7 +127,7 @@ useSeoMeta({
|
|
|
127
127
|
<div class="mt-10 flex flex-wrap items-center gap-3">
|
|
128
128
|
<NuxtLink
|
|
129
129
|
:to="landing.primary.to"
|
|
130
|
-
class="inline-flex h-11 items-center gap-2 rounded-md bg-
|
|
130
|
+
class="inline-flex h-11 items-center gap-2 rounded-md bg-brand px-5 text-sm font-semibold text-brand-foreground transition-transform hover:-translate-y-0.5"
|
|
131
131
|
>
|
|
132
132
|
{{ landing.primary.label }}
|
|
133
133
|
<Icon name="lucide:arrow-right" class="size-4" aria-hidden="true" />
|
|
@@ -240,7 +240,7 @@ useSeoMeta({
|
|
|
240
240
|
<div class="mt-9 flex flex-wrap items-center justify-center gap-3">
|
|
241
241
|
<NuxtLink
|
|
242
242
|
:to="landing.cta.primary.to"
|
|
243
|
-
class="inline-flex h-11 items-center gap-2 rounded-md bg-
|
|
243
|
+
class="inline-flex h-11 items-center gap-2 rounded-md bg-brand px-5 text-sm font-semibold text-brand-foreground transition-transform hover:-translate-y-0.5"
|
|
244
244
|
>
|
|
245
245
|
{{ landing.cta.primary.label }}
|
|
246
246
|
<Icon name="lucide:arrow-right" class="size-4" aria-hidden="true" />
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lupinum/ginko-docs",
|
|
3
|
-
"version": "0.4.0-rc.
|
|
3
|
+
"version": "0.4.0-rc.5",
|
|
4
4
|
"description": "A Nuxt documentation layer powered by Ginko Content.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"content",
|
|
@@ -74,6 +74,7 @@
|
|
|
74
74
|
"@vueuse/core": "^14.4.0",
|
|
75
75
|
"class-variance-authority": "^0.7.1",
|
|
76
76
|
"clsx": "^2.1.1",
|
|
77
|
+
"h3": "1.15.11",
|
|
77
78
|
"motion-v": "^2.3.0",
|
|
78
79
|
"nitropack": "^2.13.4",
|
|
79
80
|
"nuxt-og-image": "^6.7.8",
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import { setResponseHeaders } from "h3";
|
|
2
1
|
import { useAppConfig } from "#imports";
|
|
3
2
|
import { createGinkoDocsAiCatalog } from "../../utils/mcp-server-card";
|
|
4
3
|
|
|
5
4
|
export default defineEventHandler((event) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"content-type": "application/ai-catalog+json; charset=utf-8",
|
|
10
|
-
});
|
|
5
|
+
event.node.res.setHeader("access-control-allow-origin", "*");
|
|
6
|
+
event.node.res.setHeader("cache-control", "public, max-age=3600");
|
|
7
|
+
event.node.res.setHeader("content-type", "application/ai-catalog+json; charset=utf-8");
|
|
11
8
|
|
|
12
9
|
return createGinkoDocsAiCatalog(useAppConfig().ginkoDocs.site.url);
|
|
13
10
|
});
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import { setResponseHeaders } from "h3";
|
|
2
1
|
import { useAppConfig } from "#imports";
|
|
3
2
|
import packageMetadata from "../../../package.json" with { type: "json" };
|
|
4
3
|
import { createGinkoDocsServerCard } from "../../utils/mcp-server-card";
|
|
5
4
|
|
|
6
5
|
export default defineEventHandler((event) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"content-type": "application/mcp-server-card+json; charset=utf-8",
|
|
11
|
-
});
|
|
6
|
+
event.node.res.setHeader("access-control-allow-origin", "*");
|
|
7
|
+
event.node.res.setHeader("cache-control", "public, max-age=3600");
|
|
8
|
+
event.node.res.setHeader("content-type", "application/mcp-server-card+json; charset=utf-8");
|
|
12
9
|
|
|
13
10
|
return createGinkoDocsServerCard({
|
|
14
11
|
origin: useAppConfig().ginkoDocs.site.url,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export type { GinkoDocsNeutralPalette, GinkoDocsPrimaryPalette } from "../theme-palettes";
|
|
2
|
+
export type { GinkoDocsThemePreset } from "../theme-presets";
|
|
2
3
|
import type { GinkoDocsNeutralPalette, GinkoDocsPrimaryPalette } from "../theme-palettes";
|
|
4
|
+
import type { GinkoDocsThemePreset } from "../theme-presets";
|
|
3
5
|
|
|
4
6
|
export type GinkoDocsLocalizedText = string | { en: string; de?: string };
|
|
5
7
|
|
|
@@ -61,6 +63,8 @@ export type GinkoDocsHeroMedia =
|
|
|
61
63
|
|
|
62
64
|
export interface GinkoDocsAppConfig {
|
|
63
65
|
theme: {
|
|
66
|
+
/** Coordinated visual system. A non-default preset owns palette and surface tokens. */
|
|
67
|
+
preset?: GinkoDocsThemePreset;
|
|
64
68
|
neutral: GinkoDocsNeutralPalette;
|
|
65
69
|
primary: GinkoDocsPrimaryPalette;
|
|
66
70
|
codeBlocks: GinkoDocsCodeBlockTheme;
|