@uxfront/layer-docs 0.1.1 → 0.2.1
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 +114 -6
- package/app/components/app/AppHeaderAttribution.vue +10 -1
- package/app/components/content/FrameworkSwitcher.vue +1 -0
- package/app/components/content/GradientPageHero.vue +35 -0
- package/app/components/docs/DocsAsideLeftTop.vue +24 -0
- package/app/components/docs/DocsFrameworkSelect.vue +18 -0
- package/app/composables/useFramework.ts +20 -29
- package/app/layouts/default.vue +1 -0
- package/app/plugins/posthog.client.ts +24 -5
- package/i18n/locales/ar.json +24 -0
- package/i18n/locales/be.json +24 -0
- package/i18n/locales/bn.json +24 -0
- package/i18n/locales/ca.json +24 -0
- package/i18n/locales/ckb.json +24 -0
- package/i18n/locales/cs.json +24 -0
- package/i18n/locales/da.json +24 -0
- package/i18n/locales/de.json +24 -0
- package/i18n/locales/el.json +24 -0
- package/i18n/locales/en.json +1 -0
- package/i18n/locales/et.json +24 -0
- package/i18n/locales/fr.json +24 -0
- package/i18n/locales/he.json +24 -0
- package/i18n/locales/hi.json +24 -0
- package/i18n/locales/hy.json +24 -0
- package/i18n/locales/it.json +24 -0
- package/i18n/locales/ja.json +24 -0
- package/i18n/locales/kk.json +24 -0
- package/i18n/locales/km.json +24 -0
- package/i18n/locales/ko.json +24 -0
- package/i18n/locales/ky.json +24 -0
- package/i18n/locales/lb.json +24 -0
- package/i18n/locales/ms.json +24 -0
- package/i18n/locales/nb.json +24 -0
- package/i18n/locales/pl.json +24 -0
- package/i18n/locales/ru.json +24 -0
- package/i18n/locales/sl.json +24 -0
- package/i18n/locales/sv.json +24 -0
- package/i18n/locales/uk.json +24 -0
- package/i18n/locales/ur.json +24 -0
- package/i18n/locales/vi.json +24 -0
- package/modules/optimizeDeps.ts +45 -0
- package/nuxt.config.ts +1 -0
- package/nuxt.schema.ts +359 -0
- package/package.json +2 -1
- package/utils/content.ts +85 -10
package/nuxt.schema.ts
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import { field, group } from "@nuxt/content/preview";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Nuxt Content Studio preview schema for this layer's `app.config.ts` surface.
|
|
5
|
+
*
|
|
6
|
+
* Every field below describes a key the layer itself declares and reads, so the
|
|
7
|
+
* schema is owned here rather than restated in each consumer. Nuxt merges
|
|
8
|
+
* schemas across layers, so a consumer declares only the keys it adds on top.
|
|
9
|
+
*
|
|
10
|
+
* This file is load-bearing beyond Studio: once a schema exists, Nuxt derives
|
|
11
|
+
* the generated `AppConfig` type from it, and any key the layer reads but the
|
|
12
|
+
* schema omits collapses to `{}` and fails typecheck at the read site. Adding a
|
|
13
|
+
* key to `app.config.ts` or reading a new one from a component means adding it
|
|
14
|
+
* here in the same change.
|
|
15
|
+
*
|
|
16
|
+
* Brand-free by construction: the defaults are Nuxt UI palette tokens and
|
|
17
|
+
* generic placeholder strings, never a product's values.
|
|
18
|
+
*/
|
|
19
|
+
export default defineNuxtSchema({
|
|
20
|
+
appConfig: {
|
|
21
|
+
ui: group({
|
|
22
|
+
title: "UI",
|
|
23
|
+
description: "UI Customization.",
|
|
24
|
+
icon: "i-lucide-palette",
|
|
25
|
+
fields: {
|
|
26
|
+
colors: group({
|
|
27
|
+
title: "Colors",
|
|
28
|
+
description: "Manage main colors of your application",
|
|
29
|
+
icon: "i-lucide-palette",
|
|
30
|
+
fields: {
|
|
31
|
+
primary: field({
|
|
32
|
+
type: "string",
|
|
33
|
+
title: "Primary",
|
|
34
|
+
description: "Primary color of your UI.",
|
|
35
|
+
icon: "i-lucide-palette",
|
|
36
|
+
default: "green",
|
|
37
|
+
required: [
|
|
38
|
+
"red",
|
|
39
|
+
"orange",
|
|
40
|
+
"amber",
|
|
41
|
+
"yellow",
|
|
42
|
+
"lime",
|
|
43
|
+
"green",
|
|
44
|
+
"emerald",
|
|
45
|
+
"teal",
|
|
46
|
+
"cyan",
|
|
47
|
+
"sky",
|
|
48
|
+
"blue",
|
|
49
|
+
"indigo",
|
|
50
|
+
"violet",
|
|
51
|
+
"purple",
|
|
52
|
+
"fuchsia",
|
|
53
|
+
"pink",
|
|
54
|
+
"rose",
|
|
55
|
+
],
|
|
56
|
+
}),
|
|
57
|
+
neutral: field({
|
|
58
|
+
type: "string",
|
|
59
|
+
title: "Neutral",
|
|
60
|
+
description: "Neutral color of your UI.",
|
|
61
|
+
icon: "i-lucide-palette",
|
|
62
|
+
default: "slate",
|
|
63
|
+
required: ["slate", "gray", "zinc", "neutral", "stone"],
|
|
64
|
+
}),
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
67
|
+
icons: group({
|
|
68
|
+
title: "Icons",
|
|
69
|
+
description: "Manage icons used in the application.",
|
|
70
|
+
icon: "i-lucide-settings",
|
|
71
|
+
fields: {
|
|
72
|
+
search: field({
|
|
73
|
+
type: "icon",
|
|
74
|
+
title: "Search Bar",
|
|
75
|
+
description: "Icon to display in the search bar.",
|
|
76
|
+
icon: "i-lucide-search",
|
|
77
|
+
default: "i-lucide-search",
|
|
78
|
+
}),
|
|
79
|
+
dark: field({
|
|
80
|
+
type: "icon",
|
|
81
|
+
title: "Dark mode",
|
|
82
|
+
description: "Icon of color mode button for dark mode.",
|
|
83
|
+
icon: "i-lucide-moon",
|
|
84
|
+
default: "i-lucide-moon",
|
|
85
|
+
}),
|
|
86
|
+
light: field({
|
|
87
|
+
type: "icon",
|
|
88
|
+
title: "Light mode",
|
|
89
|
+
description: "Icon of color mode button for light mode.",
|
|
90
|
+
icon: "i-lucide-sun",
|
|
91
|
+
default: "i-lucide-sun",
|
|
92
|
+
}),
|
|
93
|
+
external: field({
|
|
94
|
+
type: "icon",
|
|
95
|
+
title: "External Link",
|
|
96
|
+
description: "Icon for external link.",
|
|
97
|
+
icon: "i-lucide-external-link",
|
|
98
|
+
default: "i-lucide-external-link",
|
|
99
|
+
}),
|
|
100
|
+
chevron: field({
|
|
101
|
+
type: "icon",
|
|
102
|
+
title: "Chevron",
|
|
103
|
+
description: "Icon for chevron.",
|
|
104
|
+
icon: "i-lucide-chevron-down",
|
|
105
|
+
default: "i-lucide-chevron-down",
|
|
106
|
+
}),
|
|
107
|
+
hash: field({
|
|
108
|
+
type: "icon",
|
|
109
|
+
title: "Hash",
|
|
110
|
+
description: "Icon for hash anchors.",
|
|
111
|
+
icon: "i-lucide-hash",
|
|
112
|
+
default: "i-lucide-hash",
|
|
113
|
+
}),
|
|
114
|
+
},
|
|
115
|
+
}),
|
|
116
|
+
},
|
|
117
|
+
}),
|
|
118
|
+
seo: group({
|
|
119
|
+
title: "SEO",
|
|
120
|
+
description: "SEO configuration.",
|
|
121
|
+
icon: "i-lucide-search",
|
|
122
|
+
fields: {
|
|
123
|
+
title: field({
|
|
124
|
+
type: "string",
|
|
125
|
+
title: "Title",
|
|
126
|
+
description: "Title to display in the header.",
|
|
127
|
+
icon: "i-lucide-type",
|
|
128
|
+
default: "",
|
|
129
|
+
}),
|
|
130
|
+
description: field({
|
|
131
|
+
type: "string",
|
|
132
|
+
title: "Description",
|
|
133
|
+
description: "Description to display in the header.",
|
|
134
|
+
icon: "i-lucide-type",
|
|
135
|
+
default: "",
|
|
136
|
+
}),
|
|
137
|
+
},
|
|
138
|
+
}),
|
|
139
|
+
header: group({
|
|
140
|
+
title: "Header",
|
|
141
|
+
description: "Header configuration.",
|
|
142
|
+
icon: "i-lucide-layout",
|
|
143
|
+
fields: {
|
|
144
|
+
title: field({
|
|
145
|
+
type: "string",
|
|
146
|
+
title: "Title",
|
|
147
|
+
description: "Title to display in the header.",
|
|
148
|
+
icon: "i-lucide-type",
|
|
149
|
+
default: "",
|
|
150
|
+
}),
|
|
151
|
+
logo: group({
|
|
152
|
+
title: "Logo",
|
|
153
|
+
description: "Header logo configuration.",
|
|
154
|
+
icon: "i-lucide-image",
|
|
155
|
+
fields: {
|
|
156
|
+
light: field({
|
|
157
|
+
type: "media",
|
|
158
|
+
title: "Light Mode Logo",
|
|
159
|
+
description: "Pick an image from your gallery.",
|
|
160
|
+
icon: "i-lucide-sun",
|
|
161
|
+
default: "",
|
|
162
|
+
}),
|
|
163
|
+
dark: field({
|
|
164
|
+
type: "media",
|
|
165
|
+
title: "Dark Mode Logo",
|
|
166
|
+
description: "Pick an image from your gallery.",
|
|
167
|
+
icon: "i-lucide-moon",
|
|
168
|
+
default: "",
|
|
169
|
+
}),
|
|
170
|
+
alt: field({
|
|
171
|
+
type: "string",
|
|
172
|
+
title: "Alt",
|
|
173
|
+
description: "Alt to display for accessibility.",
|
|
174
|
+
icon: "i-lucide-text",
|
|
175
|
+
default: "",
|
|
176
|
+
}),
|
|
177
|
+
},
|
|
178
|
+
}),
|
|
179
|
+
links: field({
|
|
180
|
+
type: "array",
|
|
181
|
+
title: "Links",
|
|
182
|
+
description: "Navigation links to display in the header.",
|
|
183
|
+
icon: "i-lucide-link",
|
|
184
|
+
default: [],
|
|
185
|
+
}),
|
|
186
|
+
attribution: group({
|
|
187
|
+
title: "Attribution",
|
|
188
|
+
description: "Brand attribution rendered beside the header wordmark.",
|
|
189
|
+
icon: "i-lucide-badge",
|
|
190
|
+
fields: {
|
|
191
|
+
prefix: field({
|
|
192
|
+
type: "string",
|
|
193
|
+
title: "Prefix",
|
|
194
|
+
description: 'Unlinked word before the label, e.g. "by".',
|
|
195
|
+
icon: "i-lucide-text",
|
|
196
|
+
default: "",
|
|
197
|
+
}),
|
|
198
|
+
label: field({
|
|
199
|
+
type: "string",
|
|
200
|
+
title: "Label",
|
|
201
|
+
description: "Linked attribution text. Empty renders nothing.",
|
|
202
|
+
icon: "i-lucide-type",
|
|
203
|
+
default: "",
|
|
204
|
+
}),
|
|
205
|
+
to: field({
|
|
206
|
+
type: "string",
|
|
207
|
+
title: "URL",
|
|
208
|
+
description: "Destination the label links to.",
|
|
209
|
+
icon: "i-lucide-link",
|
|
210
|
+
default: "",
|
|
211
|
+
}),
|
|
212
|
+
},
|
|
213
|
+
}),
|
|
214
|
+
},
|
|
215
|
+
}),
|
|
216
|
+
footer: group({
|
|
217
|
+
title: "Footer",
|
|
218
|
+
description: "Footer configuration.",
|
|
219
|
+
icon: "i-lucide-panel-bottom",
|
|
220
|
+
fields: {
|
|
221
|
+
credits: field({
|
|
222
|
+
type: "string",
|
|
223
|
+
title: "Credits",
|
|
224
|
+
description: "Copyright line. Falls back to the header title.",
|
|
225
|
+
icon: "i-lucide-copyright",
|
|
226
|
+
default: "",
|
|
227
|
+
}),
|
|
228
|
+
links: field({
|
|
229
|
+
type: "array",
|
|
230
|
+
title: "Links",
|
|
231
|
+
description: "Navigation links to display in the footer.",
|
|
232
|
+
icon: "i-lucide-link",
|
|
233
|
+
default: [],
|
|
234
|
+
}),
|
|
235
|
+
},
|
|
236
|
+
}),
|
|
237
|
+
socials: field({
|
|
238
|
+
type: "object",
|
|
239
|
+
title: "Social Networks",
|
|
240
|
+
description: "Social links configuration.",
|
|
241
|
+
icon: "i-lucide-network",
|
|
242
|
+
default: {},
|
|
243
|
+
}),
|
|
244
|
+
toc: group({
|
|
245
|
+
title: "Table of contents",
|
|
246
|
+
description: "TOC configuration.",
|
|
247
|
+
icon: "i-lucide-list",
|
|
248
|
+
fields: {
|
|
249
|
+
title: field({
|
|
250
|
+
type: "string",
|
|
251
|
+
title: "Title",
|
|
252
|
+
description: "Title of the table of contents.",
|
|
253
|
+
icon: "i-lucide-heading",
|
|
254
|
+
default: "On this page",
|
|
255
|
+
}),
|
|
256
|
+
bottom: group({
|
|
257
|
+
title: "Bottom",
|
|
258
|
+
description: "Bottom section of the table of contents.",
|
|
259
|
+
icon: "i-lucide-list",
|
|
260
|
+
fields: {
|
|
261
|
+
title: field({
|
|
262
|
+
type: "string",
|
|
263
|
+
title: "Title",
|
|
264
|
+
description: "Title of the bottom section.",
|
|
265
|
+
icon: "i-lucide-heading",
|
|
266
|
+
default: "Community",
|
|
267
|
+
}),
|
|
268
|
+
links: field({
|
|
269
|
+
type: "array",
|
|
270
|
+
title: "Links",
|
|
271
|
+
description: "Links to display in the bottom section.",
|
|
272
|
+
icon: "i-lucide-link",
|
|
273
|
+
default: [],
|
|
274
|
+
}),
|
|
275
|
+
},
|
|
276
|
+
}),
|
|
277
|
+
},
|
|
278
|
+
}),
|
|
279
|
+
analytics: group({
|
|
280
|
+
title: "Analytics",
|
|
281
|
+
description: "PostHog analytics plugin (production only, requires a runtime key).",
|
|
282
|
+
icon: "i-lucide-chart-line",
|
|
283
|
+
fields: {
|
|
284
|
+
enabled: field({
|
|
285
|
+
type: "boolean",
|
|
286
|
+
title: "Enabled",
|
|
287
|
+
description: "Set to false to opt out of the analytics plugin.",
|
|
288
|
+
icon: "i-lucide-toggle-right",
|
|
289
|
+
default: true,
|
|
290
|
+
}),
|
|
291
|
+
},
|
|
292
|
+
}),
|
|
293
|
+
i18nRedirect: group({
|
|
294
|
+
title: "Locale redirect",
|
|
295
|
+
description: "Redirect `/` to `/{locale}` (only fires when i18n is configured).",
|
|
296
|
+
icon: "i-lucide-languages",
|
|
297
|
+
fields: {
|
|
298
|
+
enabled: field({
|
|
299
|
+
type: "boolean",
|
|
300
|
+
title: "Enabled",
|
|
301
|
+
description: "Set to false to opt out of the locale redirect.",
|
|
302
|
+
icon: "i-lucide-toggle-right",
|
|
303
|
+
default: true,
|
|
304
|
+
}),
|
|
305
|
+
},
|
|
306
|
+
}),
|
|
307
|
+
nonRouteCategories: field({
|
|
308
|
+
type: "object",
|
|
309
|
+
title: "Non-route categories",
|
|
310
|
+
description:
|
|
311
|
+
"Navigation folders that group pages without owning a route, keyed by directory name.",
|
|
312
|
+
icon: "i-lucide-folder-tree",
|
|
313
|
+
default: {},
|
|
314
|
+
}),
|
|
315
|
+
docsTheme: group({
|
|
316
|
+
title: "Docs theme",
|
|
317
|
+
description: "Documentation-specific theme options.",
|
|
318
|
+
icon: "i-lucide-book-open",
|
|
319
|
+
fields: {
|
|
320
|
+
frameworks: field({
|
|
321
|
+
type: "array",
|
|
322
|
+
title: "Frameworks",
|
|
323
|
+
description:
|
|
324
|
+
"Frameworks offered by the sidebar select and in-content switcher, in display order. Empty by default — `defu` concatenates arrays across layers, so a non-empty default here could only be appended to, never overridden.",
|
|
325
|
+
icon: "i-lucide-layers",
|
|
326
|
+
default: [],
|
|
327
|
+
}),
|
|
328
|
+
},
|
|
329
|
+
}),
|
|
330
|
+
github: group({
|
|
331
|
+
title: "GitHub",
|
|
332
|
+
description: "GitHub configuration.",
|
|
333
|
+
icon: "i-simple-icons-github",
|
|
334
|
+
fields: {
|
|
335
|
+
url: field({
|
|
336
|
+
type: "string",
|
|
337
|
+
title: "URL",
|
|
338
|
+
description: "GitHub URL.",
|
|
339
|
+
icon: "i-simple-icons-github",
|
|
340
|
+
default: "",
|
|
341
|
+
}),
|
|
342
|
+
branch: field({
|
|
343
|
+
type: "string",
|
|
344
|
+
title: "Branch",
|
|
345
|
+
description: "GitHub branch.",
|
|
346
|
+
icon: "i-lucide-git-branch",
|
|
347
|
+
default: "main",
|
|
348
|
+
}),
|
|
349
|
+
rootDir: field({
|
|
350
|
+
type: "string",
|
|
351
|
+
title: "Root Directory",
|
|
352
|
+
description: "Root directory of the GitHub repository.",
|
|
353
|
+
icon: "i-lucide-folder",
|
|
354
|
+
default: "",
|
|
355
|
+
}),
|
|
356
|
+
},
|
|
357
|
+
}),
|
|
358
|
+
},
|
|
359
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uxfront/layer-docs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Neutral, brandable Nuxt-layer documentation theme. Consumers extend it and supply their own branding, content and section topology.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"server",
|
|
26
26
|
"utils",
|
|
27
27
|
"nuxt.config.ts",
|
|
28
|
+
"nuxt.schema.ts",
|
|
28
29
|
"tsconfig.json",
|
|
29
30
|
"README.md",
|
|
30
31
|
"CHANGELOG.md",
|
package/utils/content.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { DefinedCollection } from "@nuxt/content";
|
|
2
2
|
import { defineContentConfig, defineCollection, z } from "@nuxt/content";
|
|
3
3
|
import { useNuxt } from "@nuxt/kit";
|
|
4
|
+
import { defineSitemapSchema } from "@nuxtjs/sitemap/content";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Minimal structural shape of a documentation section descriptor. The consuming
|
|
@@ -15,8 +16,11 @@ export interface DocsSectionDescriptor {
|
|
|
15
16
|
slug: string;
|
|
16
17
|
/** Human label, used as a fallback nav title. */
|
|
17
18
|
label: string;
|
|
18
|
-
/**
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Source folder(s) under `content/docs/`. String or list. Accepts a readonly
|
|
21
|
+
* list so a consumer can declare its topology with `as const`.
|
|
22
|
+
*/
|
|
23
|
+
folder: string | readonly string[];
|
|
20
24
|
/**
|
|
21
25
|
* When `folder` is a list, the index whose pages mount at the section root
|
|
22
26
|
* (`/docs/<slug>`) instead of `/docs/<slug>/<folder>`. Defaults to none.
|
|
@@ -24,8 +28,40 @@ export interface DocsSectionDescriptor {
|
|
|
24
28
|
rootFolder?: number;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Opt-in extras layered on top of the base collection set. Both default to
|
|
33
|
+
* `false`, so an existing `defineDocsCollections(sections)` call is unchanged.
|
|
34
|
+
*/
|
|
35
|
+
export interface DefineDocsCollectionsOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Fold `@nuxtjs/sitemap`'s frontmatter schema into every page collection so
|
|
38
|
+
* authors can set per-page sitemap fields (priority, changefreq, lastmod).
|
|
39
|
+
* Requires the consumer to register `@nuxtjs/sitemap`.
|
|
40
|
+
*/
|
|
41
|
+
sitemap?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Emit a locale-independent `changelog` collection sourced from
|
|
44
|
+
* `content/changelog/*.md`. One entry per released version, with `version`,
|
|
45
|
+
* `date`, and an optional `releaseUrl` override for entries that predate the
|
|
46
|
+
* repository's current release-tag convention.
|
|
47
|
+
*/
|
|
48
|
+
changelog?: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// `@nuxtjs/sitemap` and `@nuxt/content` can resolve different zod majors in a
|
|
52
|
+
// consumer's tree (v4 and v3 respectively), and the two `ZodType` shapes are
|
|
53
|
+
// structurally incompatible even though the runtime value is fine. Cast at the
|
|
54
|
+
// single seam rather than pinning a consumer's zod.
|
|
55
|
+
const sitemapSchema = () =>
|
|
28
56
|
z.object({
|
|
57
|
+
sitemap: defineSitemapSchema() as unknown as ReturnType<typeof z.any>,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const createLandingSchema = (options: DefineDocsCollectionsOptions) =>
|
|
61
|
+
options.sitemap ? sitemapSchema() : undefined;
|
|
62
|
+
|
|
63
|
+
const createDocsSchema = (options: DefineDocsCollectionsOptions) => {
|
|
64
|
+
const schema = z.object({
|
|
29
65
|
links: z
|
|
30
66
|
.array(
|
|
31
67
|
z.object({
|
|
@@ -38,8 +74,18 @@ const createDocsSchema = () =>
|
|
|
38
74
|
.optional(),
|
|
39
75
|
});
|
|
40
76
|
|
|
77
|
+
return options.sitemap ? schema.extend(sitemapSchema().shape) : schema;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const createChangelogSchema = () =>
|
|
81
|
+
z.object({
|
|
82
|
+
version: z.string(),
|
|
83
|
+
date: z.string(),
|
|
84
|
+
releaseUrl: z.string().url().optional(),
|
|
85
|
+
});
|
|
86
|
+
|
|
41
87
|
const buildDocsSource = (section: DocsSectionDescriptor, pathPrefix = "", urlPrefix = "") => {
|
|
42
|
-
const folders =
|
|
88
|
+
const folders = typeof section.folder === "string" ? [section.folder] : section.folder;
|
|
43
89
|
const baseUrl = `${urlPrefix}/docs/${section.slug}`;
|
|
44
90
|
|
|
45
91
|
if (folders.length === 1) {
|
|
@@ -64,7 +110,7 @@ const buildDocsSource = (section: DocsSectionDescriptor, pathPrefix = "", urlPre
|
|
|
64
110
|
* ```ts
|
|
65
111
|
* import { defineDocsCollections } from "@uxfront/layer-docs/content";
|
|
66
112
|
* import { DOCS_SECTIONS } from "./app/constants/sections";
|
|
67
|
-
* export default defineDocsCollections(DOCS_SECTIONS);
|
|
113
|
+
* export default defineDocsCollections([...DOCS_SECTIONS]);
|
|
68
114
|
* ```
|
|
69
115
|
*
|
|
70
116
|
* Produces one `landing` collection (root markdown) plus one `docs_<key>`
|
|
@@ -72,10 +118,26 @@ const buildDocsSource = (section: DocsSectionDescriptor, pathPrefix = "", urlPre
|
|
|
72
118
|
* collections are generated per-locale (`landing_<code>`, `docs_<key>_<code>`)
|
|
73
119
|
* and sourced from a matching `content/<code>/` subtree; otherwise a single flat
|
|
74
120
|
* set is produced. The section topology and content stay in the consuming app.
|
|
121
|
+
*
|
|
122
|
+
* Two opt-in extras are available — sitemap frontmatter on every page, and a
|
|
123
|
+
* `changelog` collection:
|
|
124
|
+
*
|
|
125
|
+
* ```ts
|
|
126
|
+
* export default defineDocsCollections([...DOCS_SECTIONS], {
|
|
127
|
+
* sitemap: true,
|
|
128
|
+
* changelog: true,
|
|
129
|
+
* });
|
|
130
|
+
* ```
|
|
75
131
|
*/
|
|
76
|
-
export function defineDocsCollections(
|
|
77
|
-
|
|
78
|
-
|
|
132
|
+
export function defineDocsCollections(
|
|
133
|
+
sections: readonly DocsSectionDescriptor[],
|
|
134
|
+
options: DefineDocsCollectionsOptions = {},
|
|
135
|
+
) {
|
|
136
|
+
const { options: nuxtOptions } = useNuxt();
|
|
137
|
+
const locales = nuxtOptions.i18n?.locales;
|
|
138
|
+
|
|
139
|
+
const landingSchema = createLandingSchema(options);
|
|
140
|
+
const docsSchema = createDocsSchema(options);
|
|
79
141
|
|
|
80
142
|
let collections: Record<string, DefinedCollection>;
|
|
81
143
|
|
|
@@ -87,13 +149,14 @@ export function defineDocsCollections(sections: DocsSectionDescriptor[]) {
|
|
|
87
149
|
collections[`landing_${code}`] = defineCollection({
|
|
88
150
|
type: "page",
|
|
89
151
|
source: [{ include: `${code}/*.md` }],
|
|
152
|
+
...(landingSchema ? { schema: landingSchema } : {}),
|
|
90
153
|
});
|
|
91
154
|
|
|
92
155
|
for (const section of sections) {
|
|
93
156
|
collections[`docs_${section.key}_${code}`] = defineCollection({
|
|
94
157
|
type: "page",
|
|
95
158
|
source: buildDocsSource(section, `${code}/`, `/${code}`),
|
|
96
|
-
schema:
|
|
159
|
+
schema: docsSchema,
|
|
97
160
|
});
|
|
98
161
|
}
|
|
99
162
|
}
|
|
@@ -102,6 +165,7 @@ export function defineDocsCollections(sections: DocsSectionDescriptor[]) {
|
|
|
102
165
|
landing: defineCollection({
|
|
103
166
|
type: "page",
|
|
104
167
|
source: [{ include: "*.md" }],
|
|
168
|
+
...(landingSchema ? { schema: landingSchema } : {}),
|
|
105
169
|
}),
|
|
106
170
|
};
|
|
107
171
|
|
|
@@ -109,10 +173,21 @@ export function defineDocsCollections(sections: DocsSectionDescriptor[]) {
|
|
|
109
173
|
collections[`docs_${section.key}`] = defineCollection({
|
|
110
174
|
type: "page",
|
|
111
175
|
source: buildDocsSource(section),
|
|
112
|
-
schema:
|
|
176
|
+
schema: docsSchema,
|
|
113
177
|
});
|
|
114
178
|
}
|
|
115
179
|
}
|
|
116
180
|
|
|
181
|
+
if (options.changelog) {
|
|
182
|
+
// Locale-independent on purpose: a release history is the same document in
|
|
183
|
+
// every language. The index route renders every body inline; each entry also
|
|
184
|
+
// has a deep-linkable detail route reading from this same collection.
|
|
185
|
+
collections.changelog = defineCollection({
|
|
186
|
+
type: "page",
|
|
187
|
+
source: { include: "changelog/*.md" },
|
|
188
|
+
schema: createChangelogSchema(),
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
117
192
|
return defineContentConfig({ collections });
|
|
118
193
|
}
|