@lupinum/ginko-content 0.1.2 → 0.1.3
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 +18 -4
- package/compatibility.json +1 -1
- package/dist/cli.mjs +317 -294
- package/dist/cms-import/index.js +5 -1
- package/dist/config.d.mts +1 -1
- package/dist/config.mjs +1 -1
- package/dist/core/cache-hints.d.ts +9 -1
- package/dist/core/content/collection.js +1 -1
- package/dist/core/content/path.js +1 -1
- package/dist/core/errors.js +5 -1
- package/dist/core/provider-errors +1 -0
- package/dist/core/provider-errors.d.ts +10 -0
- package/dist/core/provider-errors.js +27 -0
- package/dist/core/query/execute.js +12 -3
- package/dist/core/query/filter.js +2 -2
- package/dist/core/query/lower.js +5 -4
- package/dist/features/navigation/build.js +14 -6
- package/dist/features/navigation/canonical.js +1 -1
- package/dist/features/sitemap/query.js +2 -2
- package/dist/integrations/nitro/ingest.d.ts +3 -3
- package/dist/integrations/nitro/ingest.js +3 -3
- package/dist/integrations/nitro/storage.js +3 -1
- package/dist/module.d.mts +151 -526
- package/dist/module.json +1 -1
- package/dist/module.mjs +1091 -722
- package/dist/parsers/csv.js +4 -3
- package/dist/parsers/index.d.ts +2 -5
- package/dist/parsers/index.js +2 -2
- package/dist/parsers/markdown-plugins.d.ts +1 -0
- package/dist/parsers/markdown-plugins.js +83 -1
- package/dist/parsers/markdown.js +1 -1
- package/dist/public/client.d.ts +3 -2
- package/dist/public/client.js +2 -2
- package/dist/public/provider-errors.d.ts +2 -1
- package/dist/public/provider-errors.js +1 -18
- package/dist/public/provider.d.ts +3 -10
- package/dist/public/server.d.ts +6 -1
- package/dist/public/server.js +33 -0
- package/dist/runtime/agent-paths +1 -0
- package/dist/runtime/agent-paths.d.ts +6 -0
- package/dist/runtime/agent-paths.js +41 -0
- package/dist/runtime/app/components/internal/MarkdownRenderer.d.ts +1 -1
- package/dist/runtime/app/composables/head.d.ts +3 -0
- package/dist/runtime/app/composables/head.js +2 -1
- package/dist/runtime/app/composables/hot-reload +1 -0
- package/dist/runtime/app/composables/hot-reload.d.ts +5 -0
- package/dist/runtime/app/composables/hot-reload.js +15 -0
- package/dist/runtime/app/composables/locale-context.d.ts +1 -1
- package/dist/runtime/app/composables/locale-context.js +2 -1
- package/dist/runtime/app/composables/locale.js +2 -2
- package/dist/runtime/app/composables/search.js +10 -6
- package/dist/runtime/app/composables/use-content-document +1 -0
- package/dist/runtime/app/composables/use-content-document.d.ts +29 -0
- package/dist/runtime/app/composables/use-content-document.js +44 -0
- package/dist/runtime/app/composables/use-content-list +1 -0
- package/dist/runtime/app/composables/use-content-list.d.ts +43 -0
- package/dist/runtime/app/composables/use-content-list.js +98 -0
- package/dist/runtime/app/composables/use-content-navigation +1 -0
- package/dist/runtime/app/composables/use-content-navigation.d.ts +40 -0
- package/dist/runtime/app/composables/use-content-navigation.js +102 -0
- package/dist/runtime/app/composables/use-content-page +1 -0
- package/dist/runtime/app/composables/use-content-page.d.ts +47 -0
- package/dist/runtime/app/composables/use-content-page.js +142 -0
- package/dist/runtime/app/composables/use-content-shared +1 -0
- package/dist/runtime/app/composables/use-content-shared.d.ts +13 -0
- package/dist/runtime/app/composables/use-content-shared.js +29 -0
- package/dist/runtime/app/composables/use-content.d.ts +11 -206
- package/dist/runtime/app/composables/use-content.js +4 -377
- package/dist/runtime/app/plugins/hot-reload +1 -0
- package/dist/runtime/app/plugins/hot-reload.js +6 -0
- package/dist/runtime/query/backlinks +1 -0
- package/dist/runtime/query/backlinks.d.ts +8 -0
- package/dist/runtime/query/backlinks.js +90 -0
- package/dist/runtime/query/context +1 -0
- package/dist/runtime/query/context.d.ts +20 -0
- package/dist/runtime/query/context.js +0 -0
- package/dist/runtime/query/documents +1 -0
- package/dist/runtime/query/documents.d.ts +6 -0
- package/dist/runtime/query/documents.js +98 -0
- package/dist/runtime/query/errors +1 -0
- package/dist/runtime/query/errors.d.ts +1 -0
- package/dist/runtime/query/errors.js +4 -0
- package/dist/runtime/query/handles +1 -0
- package/dist/runtime/query/handles.d.ts +2 -0
- package/dist/runtime/query/handles.js +7 -0
- package/dist/runtime/query/locale-options +1 -0
- package/dist/runtime/query/locale-options.d.ts +5 -0
- package/dist/runtime/query/locale-options.js +14 -0
- package/dist/runtime/query/localized-docs +1 -0
- package/dist/runtime/query/localized-docs.d.ts +17 -0
- package/dist/runtime/query/localized-docs.js +44 -0
- package/dist/runtime/query/navigation +1 -0
- package/dist/runtime/query/navigation.d.ts +22 -0
- package/dist/runtime/query/navigation.js +73 -0
- package/dist/runtime/query/pagination +1 -0
- package/dist/runtime/query/pagination.d.ts +7 -0
- package/dist/runtime/query/pagination.js +78 -0
- package/dist/runtime/query/populate +1 -0
- package/dist/runtime/query/populate.d.ts +9 -0
- package/dist/runtime/query/populate.js +106 -0
- package/dist/runtime/query/responses +1 -0
- package/dist/runtime/query/responses.d.ts +10 -0
- package/dist/runtime/query/responses.js +47 -0
- package/dist/runtime/query/unified.d.ts +4 -20
- package/dist/runtime/query/unified.js +14 -544
- package/dist/runtime/query/variants +1 -0
- package/dist/runtime/query/variants.d.ts +11 -0
- package/dist/runtime/query/variants.js +36 -0
- package/dist/runtime/server/agent-http +1 -0
- package/dist/runtime/server/agent-http.d.ts +7 -0
- package/dist/runtime/server/agent-http.js +36 -0
- package/dist/runtime/server/agent-markdown +1 -0
- package/dist/runtime/server/agent-markdown.d.ts +83 -0
- package/dist/runtime/server/agent-markdown.js +449 -0
- package/dist/runtime/server/agent-site +1 -0
- package/dist/runtime/server/agent-site.d.ts +38 -0
- package/dist/runtime/server/agent-site.js +273 -0
- package/dist/runtime/server/api/agent-llms +1 -0
- package/dist/runtime/server/api/agent-llms-full +1 -0
- package/dist/runtime/server/api/agent-llms-full.d.ts +2 -0
- package/dist/runtime/server/api/agent-llms-full.js +13 -0
- package/dist/runtime/server/api/agent-llms.d.ts +2 -0
- package/dist/runtime/server/api/agent-llms.js +14 -0
- package/dist/runtime/server/api/agent-raw +1 -0
- package/dist/runtime/server/api/agent-raw.d.ts +2 -0
- package/dist/runtime/server/api/agent-raw.js +17 -0
- package/dist/runtime/server/api/locales.d.ts +2 -2
- package/dist/runtime/server/api/locales.js +4 -2
- package/dist/runtime/server/api/navigation.d.ts +1 -1
- package/dist/runtime/server/api/query.d.ts +1 -1
- package/dist/runtime/server/api/query.js +4 -1
- package/dist/runtime/server/api/revalidate.js +2 -2
- package/dist/runtime/server/api/site-data.d.ts +1 -1
- package/dist/runtime/server/collection-helpers.js +2 -1
- package/dist/runtime/server/middleware/agent-link-headers +1 -0
- package/dist/runtime/server/middleware/agent-link-headers.d.ts +2 -0
- package/dist/runtime/server/middleware/agent-link-headers.js +42 -0
- package/dist/runtime/server/middleware/agent-markdown +1 -0
- package/dist/runtime/server/middleware/agent-markdown.d.ts +2 -0
- package/dist/runtime/server/middleware/agent-markdown.js +43 -0
- package/dist/runtime/server/plugins/sitemap.js +1 -0
- package/dist/runtime/server/provider-query.d.ts +8 -5
- package/dist/runtime/server/provider-query.js +50 -8
- package/dist/runtime/server/provider-result.d.ts +19 -2
- package/dist/runtime/server/providers/filesystem.js +4 -1
- package/dist/runtime/server/providers/index.d.ts +3 -1
- package/dist/runtime/server/providers/index.js +2 -2
- package/dist/runtime/server/query-api.js +2 -1
- package/dist/runtime/server/query-executor.d.ts +3 -2
- package/dist/runtime/server/query-executor.js +13 -5
- package/dist/runtime/server/search.js +1 -1
- package/dist/runtime/server/sitemap-provider.js +40 -1
- package/dist/runtime/server/sitemap.js +3 -2
- package/dist/runtime/transformers/component-resolver.js +2 -1
- package/dist/runtime/utils/content-components.d.ts +0 -5
- package/dist/storage/content.d.ts +2 -9
- package/dist/storage/references.d.ts +1 -8
- package/dist/storage/references.js +9 -4
- package/dist/testing/provider-contract.js +3 -4
- package/dist/testing/provider-fixture.d.ts +3 -1
- package/dist/testing/provider-fixture.js +27 -14
- package/dist/types/config.d.ts +77 -0
- package/dist/types/config.js +23 -0
- package/dist/types/module.d.ts +15 -5
- package/dist/types/query-parts/collections +1 -0
- package/dist/types/query-parts/collections.d.ts +15 -0
- package/dist/types/query-parts/collections.js +0 -0
- package/dist/types/query-parts/public +1 -0
- package/dist/types/query-parts/public.d.ts +202 -0
- package/dist/types/query-parts/public.js +0 -0
- package/dist/types/query-parts/results +1 -0
- package/dist/types/query-parts/results.d.ts +95 -0
- package/dist/types/query-parts/results.js +0 -0
- package/dist/types/query-parts/transport +1 -0
- package/dist/types/query-parts/transport.d.ts +103 -0
- package/dist/types/query-parts/transport.js +0 -0
- package/dist/types/query.d.ts +4 -870
- package/dist/types/query.js +4 -0
- package/dist/types/runtime.d.ts +2 -2
- package/dist/types/virtual.d.ts +54 -0
- package/dist/types.d.mts +2 -2
- package/dist/web-types.json +1 -1
- package/package.json +5 -5
- package/dist/runtime/app/composables/web-socket +0 -1
- package/dist/runtime/app/composables/web-socket.d.ts +0 -3
- package/dist/runtime/app/composables/web-socket.js +0 -65
- package/dist/runtime/app/plugins/ws +0 -1
- package/dist/runtime/app/plugins/ws.js +0 -7
- /package/dist/runtime/app/plugins/{ws.d.ts → hot-reload.d.ts} +0 -0
package/dist/module.mjs
CHANGED
|
@@ -1,103 +1,37 @@
|
|
|
1
|
-
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { join as join$1, basename, resolve as resolve$1, relative as relative$1, dirname } from 'node:path';
|
|
3
|
-
import { pathToFileURL } from 'node:url';
|
|
4
1
|
import { addTypeTemplate, addImports, addServerImports, addComponentsDir, addPlugin, addServerHandler, defineNuxtModule, createResolver, useLogger, addTemplate } from '@nuxt/kit';
|
|
5
2
|
import { defu } from 'defu';
|
|
3
|
+
import fs, { existsSync } from 'fs';
|
|
4
|
+
import { join, relative, resolve, isAbsolute } from 'pathe';
|
|
5
|
+
import jiti from 'jiti';
|
|
6
|
+
import { createRequire } from 'node:module';
|
|
7
|
+
import { pathToFileURL } from 'node:url';
|
|
8
|
+
import { genSafeVariableName, genImport } from 'knitwork';
|
|
6
9
|
import { hash } from 'ohash';
|
|
7
|
-
import { resolve, join, relative, isAbsolute } from 'pathe';
|
|
8
|
-
import { withTrailingSlash } from 'ufo';
|
|
9
|
-
import { normalizeContentConfigCollectionNames } from '../dist/types/config';
|
|
10
|
-
export { defineCollection, defineContentConfig, reference } from '../dist/types/config';
|
|
11
10
|
import 'unstorage/drivers/fs';
|
|
12
11
|
import 'unstorage/drivers/http';
|
|
13
12
|
import 'unstorage/drivers/github';
|
|
14
|
-
import { WebSocketServer } from 'ws';
|
|
15
13
|
import { consola } from 'consola';
|
|
16
|
-
import fs, { existsSync } from 'fs';
|
|
17
|
-
import jiti from 'jiti';
|
|
18
|
-
import { createRequire } from 'node:module';
|
|
19
|
-
import { genSafeVariableName, genImport } from 'knitwork';
|
|
20
|
-
import { listen } from 'listhen';
|
|
21
14
|
import { makeIgnored } from '../dist/core/content/ignore';
|
|
22
|
-
import { readFile, readdir } from 'node:fs/promises';
|
|
23
|
-
import { resolveContentSitemapSource, GINKO_SITEMAP_SOURCE_NAME } from '../dist/runtime/utils/sitemap-source';
|
|
24
15
|
import { resolveCollectionI18nConfig } from '../dist/features/localization/config';
|
|
16
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
17
|
+
import { join as join$1, basename, resolve as resolve$1, relative as relative$1, dirname } from 'node:path';
|
|
25
18
|
import { globby } from 'globby';
|
|
26
|
-
import { transformContent } from '../dist/parsers/index';
|
|
27
|
-
import { expandDataLocaleVariants } from '../dist/core/content/locale';
|
|
28
19
|
import { buildContentGraph } from '../dist/core/content/graph';
|
|
20
|
+
import { expandDataLocaleVariants } from '../dist/core/content/locale';
|
|
29
21
|
import { normalizeCollectionSources, normalizeCollectionExcludes } from '../dist/core/content/sources';
|
|
30
|
-
import { resolveCollectionI18n, prefixPathWithLocale } from '../dist/features/localization/path';
|
|
31
22
|
import { resolveCollection } from '../dist/core/content/collection';
|
|
23
|
+
import { transformContent } from '../dist/parsers/index';
|
|
24
|
+
import { resolveCollectionI18n, prefixPathWithLocale } from '../dist/features/localization/path';
|
|
25
|
+
import { resolveContentSitemapSource, GINKO_SITEMAP_SOURCE_NAME } from '../dist/runtime/utils/sitemap-source';
|
|
32
26
|
import { normalizeRouteMounts, normalizeContentPath } from '../dist/core/content/path';
|
|
27
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
28
|
+
import { withTrailingSlash } from 'ufo';
|
|
29
|
+
import { normalizeContentConfigCollectionNames } from '../dist/types/config';
|
|
30
|
+
export { agentMetadataFields, defineAgentAppPage, defineAgentMarkdownPolicy, defineAgentMetadataFields, defineAgentSection, defineCollection, defineContentConfig, reference } from '../dist/types/config';
|
|
33
31
|
import { collectTopLevelReferenceFieldsByTarget } from '../dist/core/references/schema';
|
|
34
32
|
|
|
35
33
|
const name = "@lupinum/ginko-content";
|
|
36
|
-
const version = "0.1.
|
|
37
|
-
|
|
38
|
-
const logger = consola.withTag("@lupinum/ginko-content");
|
|
39
|
-
const CACHE_VERSION = 3;
|
|
40
|
-
const MOUNT_PREFIX = "content:source:";
|
|
41
|
-
function useContentMounts(nuxt, storages) {
|
|
42
|
-
const key = (path, prefix = "") => `${MOUNT_PREFIX}${path.replace(/[/:]/g, "_")}${prefix.replace(/\//g, ":")}`;
|
|
43
|
-
const baseDir = nuxt.options.future?.compatibilityVersion === 4 ? nuxt.options.rootDir : nuxt.options.srcDir;
|
|
44
|
-
storages = Object.entries(storages).reduce((mounts, [name, storage]) => {
|
|
45
|
-
mounts[key(storage.name || name, storage.prefix)] = storage;
|
|
46
|
-
return mounts;
|
|
47
|
-
}, {});
|
|
48
|
-
const defaultStorage = key("content");
|
|
49
|
-
if (!storages[defaultStorage]) {
|
|
50
|
-
storages[defaultStorage] = {
|
|
51
|
-
name: defaultStorage,
|
|
52
|
-
driver: "fs",
|
|
53
|
-
base: resolve(baseDir, "content")
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
return storages;
|
|
57
|
-
}
|
|
58
|
-
function createWebSocket() {
|
|
59
|
-
const wss = new WebSocketServer({ noServer: true });
|
|
60
|
-
const serve = (req, socket = req.socket, head = "") => wss.handleUpgrade(req, socket, head, (client) => wss.emit("connection", client, req));
|
|
61
|
-
const broadcast = (data) => {
|
|
62
|
-
data = JSON.stringify(data);
|
|
63
|
-
for (const client of wss.clients) {
|
|
64
|
-
try {
|
|
65
|
-
client.send(data);
|
|
66
|
-
} catch {
|
|
67
|
-
logger.debug("Skipping websocket client that is not ready to receive content refresh events.");
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
return {
|
|
72
|
-
serve,
|
|
73
|
-
broadcast,
|
|
74
|
-
close: () => {
|
|
75
|
-
wss.clients.forEach((client) => client.close());
|
|
76
|
-
return new Promise((resolve2) => wss.close(resolve2));
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
function processMarkdownOptions(options) {
|
|
81
|
-
const anchorLinks = typeof options.anchorLinks === "boolean" ? { depth: options.anchorLinks ? 6 : 0, exclude: [] } : { depth: 4, exclude: [1], ...options.anchorLinks };
|
|
82
|
-
const plugins = options.plugins?.length ? options.plugins : [
|
|
83
|
-
["toc", { depth: 2, searchDepth: 2 }],
|
|
84
|
-
"summary"
|
|
85
|
-
];
|
|
86
|
-
return {
|
|
87
|
-
...options,
|
|
88
|
-
anchorLinks,
|
|
89
|
-
plugins: resolveMarkdownPlugins(plugins)
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
function resolveMarkdownPlugins(plugins) {
|
|
93
|
-
return (plugins || []).map((plugin) => {
|
|
94
|
-
const [name, options] = Array.isArray(plugin) ? plugin : [plugin, {}];
|
|
95
|
-
return {
|
|
96
|
-
name,
|
|
97
|
-
options
|
|
98
|
-
};
|
|
99
|
-
});
|
|
100
|
-
}
|
|
34
|
+
const version = "0.1.3";
|
|
101
35
|
|
|
102
36
|
const CONFIG_FILES = [
|
|
103
37
|
"content.config.ts",
|
|
@@ -175,7 +109,7 @@ const createVirtualContentTemplates = (contentContext, nuxt, contentConfigPath,
|
|
|
175
109
|
write: true,
|
|
176
110
|
getContents: () => {
|
|
177
111
|
const cache = contentContext.cache;
|
|
178
|
-
if (!cache
|
|
112
|
+
if (!cache) {
|
|
179
113
|
return [
|
|
180
114
|
"export const loadContentCacheAdapter = () => undefined",
|
|
181
115
|
"export default {}"
|
|
@@ -211,14 +145,66 @@ const registerVirtualContentAliases = (nuxt, transformersTemplate, virtualConfig
|
|
|
211
145
|
});
|
|
212
146
|
};
|
|
213
147
|
|
|
148
|
+
consola.withTag("@lupinum/ginko-content");
|
|
149
|
+
const CACHE_VERSION = 3;
|
|
150
|
+
const MOUNT_PREFIX = "content:source:";
|
|
151
|
+
function useContentMounts(nuxt, storages) {
|
|
152
|
+
const key = (path, prefix = "") => `${MOUNT_PREFIX}${path.replace(/[/:]/g, "_")}${prefix.replace(/\//g, ":")}`;
|
|
153
|
+
const baseDir = nuxt.options.future?.compatibilityVersion === 4 ? nuxt.options.rootDir : nuxt.options.srcDir;
|
|
154
|
+
storages = Object.entries(storages).reduce((mounts, [name, storage]) => {
|
|
155
|
+
mounts[key(storage.name || name, storage.prefix)] = storage;
|
|
156
|
+
return mounts;
|
|
157
|
+
}, {});
|
|
158
|
+
const defaultStorage = key("content");
|
|
159
|
+
if (!storages[defaultStorage]) {
|
|
160
|
+
storages[defaultStorage] = {
|
|
161
|
+
name: defaultStorage,
|
|
162
|
+
driver: "fs",
|
|
163
|
+
base: resolve(baseDir, "content")
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
return storages;
|
|
167
|
+
}
|
|
168
|
+
function processMarkdownOptions(options) {
|
|
169
|
+
const anchorLinks = typeof options.anchorLinks === "boolean" ? { depth: options.anchorLinks ? 6 : 0, exclude: [] } : { depth: 4, exclude: [1], ...options.anchorLinks };
|
|
170
|
+
const plugins = options.plugins?.length ? options.plugins : [
|
|
171
|
+
["toc", { depth: 2, searchDepth: 2 }],
|
|
172
|
+
"summary"
|
|
173
|
+
];
|
|
174
|
+
return {
|
|
175
|
+
anchorLinks,
|
|
176
|
+
tags: options.tags || {},
|
|
177
|
+
image: options.image,
|
|
178
|
+
plugins: resolveMarkdownPlugins(plugins)
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function resolveMarkdownPlugins(plugins) {
|
|
182
|
+
return (plugins || []).map((plugin) => {
|
|
183
|
+
const [name, options] = Array.isArray(plugin) ? plugin : [plugin, {}];
|
|
184
|
+
return {
|
|
185
|
+
name,
|
|
186
|
+
options
|
|
187
|
+
};
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
214
191
|
const registerContentDevRuntime = (nuxt, options, contentContext) => {
|
|
215
192
|
const isIgnored = makeIgnored(contentContext.ignores);
|
|
193
|
+
let viteServer;
|
|
194
|
+
if (options.watch !== false) {
|
|
195
|
+
nuxt.options.vite ||= {};
|
|
196
|
+
nuxt.options.vite.plugins ||= [];
|
|
197
|
+
nuxt.options.vite.plugins.push({
|
|
198
|
+
name: "ginko-content-hmr",
|
|
199
|
+
configureServer(server) {
|
|
200
|
+
viteServer = server;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
216
204
|
nuxt.hook("nitro:init", async (nitro) => {
|
|
217
|
-
if (
|
|
205
|
+
if (options.watch === false) {
|
|
218
206
|
return;
|
|
219
207
|
}
|
|
220
|
-
const ws = createWebSocket();
|
|
221
|
-
const { server, url } = await listen(() => "Ginko", options.watch.ws);
|
|
222
208
|
const unwatch = await nitro.storage.watch(async (event, key) => {
|
|
223
209
|
if (!key.startsWith(MOUNT_PREFIX) || isIgnored(key)) {
|
|
224
210
|
return;
|
|
@@ -227,56 +213,85 @@ const registerContentDevRuntime = (nuxt, options, contentContext) => {
|
|
|
227
213
|
await nitro.storage.removeItem("cache:content:_manifest.json");
|
|
228
214
|
await nitro.storage.removeItem("cache:content:_nav.json");
|
|
229
215
|
await nitro.storage.removeItem("cache:content:_meta.json");
|
|
230
|
-
|
|
216
|
+
await nitro.storage.removeItem(`cache:content:parsed:${key}`);
|
|
217
|
+
const payload = { event, key };
|
|
218
|
+
viteServer?.ws.send({
|
|
219
|
+
type: "custom",
|
|
220
|
+
event: "ginko-content:update",
|
|
221
|
+
data: payload
|
|
222
|
+
});
|
|
231
223
|
});
|
|
232
224
|
nitro.hooks.hook("close", async () => {
|
|
233
225
|
await unwatch();
|
|
234
|
-
await ws.close();
|
|
235
|
-
await server.close();
|
|
236
226
|
});
|
|
237
|
-
server.on("upgrade", ws.serve);
|
|
238
|
-
nitro.options.runtimeConfig.public.content.wsUrl = url.replace("http", "ws");
|
|
239
227
|
await nitro.storage.removeItem("cache:content:_manifest.json");
|
|
240
228
|
await nitro.storage.removeItem("cache:content:_nav.json");
|
|
241
229
|
await nitro.storage.removeItem("cache:content:_meta.json");
|
|
242
230
|
});
|
|
243
231
|
};
|
|
244
232
|
|
|
233
|
+
const runtimeAppImportSpecs = [
|
|
234
|
+
{ name: "getCollectionPath", as: "getCollectionPath", from: "./query/routes.js" },
|
|
235
|
+
{ name: "useContentHead", as: "useContentHead", from: "./app/composables/head.js" },
|
|
236
|
+
{ name: "useContentPage", as: "useContentPage", from: "./app/composables/use-content.js" },
|
|
237
|
+
{ name: "useContentOne", as: "useContentOne", from: "./app/composables/use-content.js" },
|
|
238
|
+
{ name: "useContentMany", as: "useContentMany", from: "./app/composables/use-content.js" },
|
|
239
|
+
{ name: "useContentPagination", as: "useContentPagination", from: "./app/composables/use-content.js" },
|
|
240
|
+
{ name: "useContentBacklinks", as: "useContentBacklinks", from: "./app/composables/use-content.js" },
|
|
241
|
+
{ name: "useContentResolveOne", as: "useContentResolveOne", from: "./app/composables/use-content.js" },
|
|
242
|
+
{ name: "useContentVariants", as: "useContentVariants", from: "./app/composables/use-content.js" },
|
|
243
|
+
{ name: "useContentTree", as: "useContentTree", from: "./app/composables/use-content.js" },
|
|
244
|
+
{ name: "useContentNavigation", as: "useContentNavigation", from: "./app/composables/use-content.js" },
|
|
245
|
+
{ name: "useContentNeighbors", as: "useContentNeighbors", from: "./app/composables/use-content.js" },
|
|
246
|
+
{ name: "useContentSwitchLocalePath", as: "useContentSwitchLocalePath", from: "./app/composables/route.js" },
|
|
247
|
+
{ name: "useContentSearchData", as: "useContentSearchData", from: "./app/composables/search.js" },
|
|
248
|
+
{ name: "useContentSearchResults", as: "useContentSearchResults", from: "./app/composables/search.js" },
|
|
249
|
+
{ name: "querySiteData", as: "querySiteData", from: "./app/composables/site-data.js" }
|
|
250
|
+
];
|
|
251
|
+
const runtimeServerImportSpecs = [
|
|
252
|
+
{ name: "one", as: "one" },
|
|
253
|
+
{ name: "many", as: "many" },
|
|
254
|
+
{ name: "paginate", as: "paginate" },
|
|
255
|
+
{ name: "backlinks", as: "backlinks" },
|
|
256
|
+
{ name: "resolveOne", as: "resolveOne" },
|
|
257
|
+
{ name: "variants", as: "variants" },
|
|
258
|
+
{ name: "tree", as: "tree" },
|
|
259
|
+
{ name: "neighbors", as: "neighbors" },
|
|
260
|
+
{ name: "getCollectionPath", as: "getCollectionPath" },
|
|
261
|
+
{ name: "queryCollectionsSitemapEntries", as: "queryCollectionsSitemapEntries" }
|
|
262
|
+
];
|
|
263
|
+
const generatedContentServerValueNames = [
|
|
264
|
+
...runtimeServerImportSpecs.map((spec) => spec.name),
|
|
265
|
+
"contentCacheHeaders",
|
|
266
|
+
"noopContentCache",
|
|
267
|
+
"vercelContentCache",
|
|
268
|
+
"clearContentCacheHint",
|
|
269
|
+
"collectContentCacheHint",
|
|
270
|
+
"getContentCacheHint",
|
|
271
|
+
"withContentCache",
|
|
272
|
+
"createContentProviderError"
|
|
273
|
+
];
|
|
274
|
+
const generatedContentServerTypeSpecs = [
|
|
275
|
+
{ local: "ContentCacheAdapter", exported: "ContentCacheAdapter" },
|
|
276
|
+
{ local: "ContentCacheHint", exported: "ContentCacheHint" },
|
|
277
|
+
{ local: "ContentCacheHintInput", exported: "ContentCacheHintInput" },
|
|
278
|
+
{ local: "ContentCacheInvalidateInput", exported: "ContentCacheInvalidateInput" },
|
|
279
|
+
{ local: "ContentProvider", exported: "ContentProvider" },
|
|
280
|
+
{ local: "ContentProviderCapabilities", exported: "ContentProviderCapabilities" },
|
|
281
|
+
{ local: "ContentProviderResult<T>", exported: "ContentProviderResult<T>" },
|
|
282
|
+
{ local: "MaybeContentProviderResult<T>", exported: "MaybeContentProviderResult<T>" },
|
|
283
|
+
{ local: "ContentProviderErrorCode", exported: "ContentProviderErrorCode" },
|
|
284
|
+
{ local: "VercelContentCacheOptions", exported: "VercelContentCacheOptions" }
|
|
285
|
+
];
|
|
245
286
|
const registerRuntimeImports = (resolveRuntimeModule) => {
|
|
246
|
-
addImports(
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
{ name: "useContentBacklinks", as: "useContentBacklinks", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
255
|
-
{ name: "useContentResolveOne", as: "useContentResolveOne", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
256
|
-
{ name: "useContentVariants", as: "useContentVariants", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
257
|
-
{ name: "useContentTree", as: "useContentTree", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
258
|
-
{ name: "useContentNavigation", as: "useContentNavigation", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
259
|
-
{ name: "useContentNeighbors", as: "useContentNeighbors", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
260
|
-
{ name: "useContentLocaleSwitch", as: "useContentLocaleSwitch", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
261
|
-
{ name: "useContentSwitchLocalePath", as: "useContentSwitchLocalePath", from: resolveRuntimeModule("./app/composables/route.js") },
|
|
262
|
-
// Search & site data — keep the headless useContentSearch export explicit
|
|
263
|
-
// because Nuxt UI owns the same auto-import name.
|
|
264
|
-
{ name: "useContentSearchData", as: "useContentSearchData", from: resolveRuntimeModule("./app/composables/search.js") },
|
|
265
|
-
{ name: "useContentSearchResults", as: "useContentSearchResults", from: resolveRuntimeModule("./app/composables/search.js") },
|
|
266
|
-
{ name: "querySiteData", as: "querySiteData", from: resolveRuntimeModule("./app/composables/site-data.js") }
|
|
267
|
-
]);
|
|
268
|
-
addServerImports([
|
|
269
|
-
{ name: "one", as: "one", from: resolveRuntimeModule("./server/index.js") },
|
|
270
|
-
{ name: "many", as: "many", from: resolveRuntimeModule("./server/index.js") },
|
|
271
|
-
{ name: "paginate", as: "paginate", from: resolveRuntimeModule("./server/index.js") },
|
|
272
|
-
{ name: "backlinks", as: "backlinks", from: resolveRuntimeModule("./server/index.js") },
|
|
273
|
-
{ name: "resolveOne", as: "resolveOne", from: resolveRuntimeModule("./server/index.js") },
|
|
274
|
-
{ name: "variants", as: "variants", from: resolveRuntimeModule("./server/index.js") },
|
|
275
|
-
{ name: "tree", as: "tree", from: resolveRuntimeModule("./server/index.js") },
|
|
276
|
-
{ name: "neighbors", as: "neighbors", from: resolveRuntimeModule("./server/index.js") },
|
|
277
|
-
{ name: "getCollectionPath", as: "getCollectionPath", from: resolveRuntimeModule("./server/index.js") },
|
|
278
|
-
{ name: "queryCollectionsSitemapEntries", as: "queryCollectionsSitemapEntries", from: resolveRuntimeModule("./server/index.js") }
|
|
279
|
-
]);
|
|
287
|
+
addImports(runtimeAppImportSpecs.map((spec) => ({
|
|
288
|
+
...spec,
|
|
289
|
+
from: resolveRuntimeModule(spec.from)
|
|
290
|
+
})));
|
|
291
|
+
addServerImports(runtimeServerImportSpecs.map((spec) => ({
|
|
292
|
+
...spec,
|
|
293
|
+
from: resolveRuntimeModule("./server/index.js")
|
|
294
|
+
})));
|
|
280
295
|
};
|
|
281
296
|
const registerRuntimeComponents = (resolve) => {
|
|
282
297
|
addComponentsDir({
|
|
@@ -332,11 +347,11 @@ const registerContentI18nTemplate = (addTemplateImpl, hasNuxtI18nModule) => {
|
|
|
332
347
|
].join("\n")
|
|
333
348
|
});
|
|
334
349
|
};
|
|
335
|
-
const registerUserContentComponents = async (nuxt,
|
|
350
|
+
const registerUserContentComponents = async (nuxt, _resolve) => {
|
|
336
351
|
const layers = [...nuxt.options._layers];
|
|
337
352
|
for (const layer of layers) {
|
|
338
353
|
const srcDir = layer.config.srcDir;
|
|
339
|
-
const globalComponents =
|
|
354
|
+
const globalComponents = join(srcDir, "components/content");
|
|
340
355
|
const dirStat = await fs.promises.stat(globalComponents).catch((error) => {
|
|
341
356
|
if (error.code === "ENOENT") {
|
|
342
357
|
return null;
|
|
@@ -362,6 +377,12 @@ const registerGeneratedTypes = (contentConfigPath, resolveRuntimeModuleRoot, col
|
|
|
362
377
|
const key = JSON.stringify(name);
|
|
363
378
|
return ` ${key}: StrictParsedContent & __GeneratedCollectionSchema<__ContentCollectionExport<${key}>>`;
|
|
364
379
|
});
|
|
380
|
+
const contentServerValueDeclarations = generatedContentServerValueNames.map(
|
|
381
|
+
(name) => ` const ${name}: typeof import('${resolveRuntimeModuleRoot("./server")}').${name}`
|
|
382
|
+
);
|
|
383
|
+
const contentServerTypeDeclarations = generatedContentServerTypeSpecs.map(
|
|
384
|
+
(spec) => ` type ${spec.local} = import('${resolveRuntimeModuleRoot("./server")}').${spec.exported}`
|
|
385
|
+
);
|
|
365
386
|
return addTypeTemplate({
|
|
366
387
|
filename: "types/content.d.ts",
|
|
367
388
|
getContents: () => [
|
|
@@ -418,42 +439,36 @@ const registerGeneratedTypes = (contentConfigPath, resolveRuntimeModuleRoot, col
|
|
|
418
439
|
" interface ContentCollectionI18nMap extends Pick<__GeneratedContentCollectionMap, __GeneratedI18nCollectionNames> {}",
|
|
419
440
|
"}",
|
|
420
441
|
"declare module '#content/server' {",
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
` const paginate: typeof import('${resolveRuntimeModuleRoot("./server")}').paginate`,
|
|
424
|
-
` const backlinks: typeof import('${resolveRuntimeModuleRoot("./server")}').backlinks`,
|
|
425
|
-
` const resolveOne: typeof import('${resolveRuntimeModuleRoot("./server")}').resolveOne`,
|
|
426
|
-
` const variants: typeof import('${resolveRuntimeModuleRoot("./server")}').variants`,
|
|
427
|
-
` const tree: typeof import('${resolveRuntimeModuleRoot("./server")}').tree`,
|
|
428
|
-
` const neighbors: typeof import('${resolveRuntimeModuleRoot("./server")}').neighbors`,
|
|
429
|
-
` const queryCollectionsSitemapEntries: typeof import('${resolveRuntimeModuleRoot("./server")}').queryCollectionsSitemapEntries`,
|
|
430
|
-
` const contentCacheHeaders: typeof import('${resolveRuntimeModuleRoot("./server")}').contentCacheHeaders`,
|
|
431
|
-
` const noopContentCache: typeof import('${resolveRuntimeModuleRoot("./server")}').noopContentCache`,
|
|
432
|
-
` const vercelContentCache: typeof import('${resolveRuntimeModuleRoot("./server")}').vercelContentCache`,
|
|
433
|
-
` const clearContentCacheHint: typeof import('${resolveRuntimeModuleRoot("./server")}').clearContentCacheHint`,
|
|
434
|
-
` const collectContentCacheHint: typeof import('${resolveRuntimeModuleRoot("./server")}').collectContentCacheHint`,
|
|
435
|
-
` const getContentCacheHint: typeof import('${resolveRuntimeModuleRoot("./server")}').getContentCacheHint`,
|
|
436
|
-
` const withContentCache: typeof import('${resolveRuntimeModuleRoot("./server")}').withContentCache`,
|
|
437
|
-
` const createContentProviderError: typeof import('${resolveRuntimeModuleRoot("./server")}').createContentProviderError`,
|
|
438
|
-
` type ContentCacheAdapter = import('${resolveRuntimeModuleRoot("./server")}').ContentCacheAdapter`,
|
|
439
|
-
` type ContentCacheHint = import('${resolveRuntimeModuleRoot("./server")}').ContentCacheHint`,
|
|
440
|
-
` type ContentCacheHintInput = import('${resolveRuntimeModuleRoot("./server")}').ContentCacheHintInput`,
|
|
441
|
-
` type ContentCacheInvalidateInput = import('${resolveRuntimeModuleRoot("./server")}').ContentCacheInvalidateInput`,
|
|
442
|
-
` type ContentProvider = import('${resolveRuntimeModuleRoot("./server")}').ContentProvider`,
|
|
443
|
-
` type ContentProviderCapabilities = import('${resolveRuntimeModuleRoot("./server")}').ContentProviderCapabilities`,
|
|
444
|
-
` type ContentProviderResult<T> = import('${resolveRuntimeModuleRoot("./server")}').ContentProviderResult<T>`,
|
|
445
|
-
` type MaybeContentProviderResult<T> = import('${resolveRuntimeModuleRoot("./server")}').MaybeContentProviderResult<T>`,
|
|
446
|
-
` type ContentProviderErrorCode = import('${resolveRuntimeModuleRoot("./server")}').ContentProviderErrorCode`,
|
|
447
|
-
` type VercelContentCacheOptions = import('${resolveRuntimeModuleRoot("./server")}').VercelContentCacheOptions`,
|
|
442
|
+
...contentServerValueDeclarations,
|
|
443
|
+
...contentServerTypeDeclarations,
|
|
448
444
|
"}"
|
|
449
445
|
].filter(Boolean).join("\n")
|
|
450
446
|
});
|
|
451
447
|
};
|
|
452
448
|
const registerDevRuntimePlugin = (resolveRuntimeModule) => {
|
|
453
|
-
addPlugin(resolveRuntimeModule("./app/plugins/
|
|
449
|
+
addPlugin(resolveRuntimeModule("./app/plugins/hot-reload.js"));
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
const normalizeAgentRouteOptions = (options) => {
|
|
453
|
+
if (options.agent === false) {
|
|
454
|
+
return {
|
|
455
|
+
routes: false,
|
|
456
|
+
linkHeaders: false,
|
|
457
|
+
markdownNegotiation: false,
|
|
458
|
+
prerender: false
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
routes: options.agent?.routes !== false,
|
|
463
|
+
linkHeaders: options.agent?.linkHeaders !== false,
|
|
464
|
+
markdownNegotiation: options.agent?.markdownNegotiation !== false,
|
|
465
|
+
prerender: options.agent?.prerender !== false
|
|
466
|
+
};
|
|
454
467
|
};
|
|
455
468
|
|
|
456
469
|
const registerContentServerHandlers = (nuxt, options, resolveRuntimeModule, buildIntegrity) => {
|
|
470
|
+
const revalidate = options.revalidate === false ? void 0 : options.revalidate;
|
|
471
|
+
const sitemap = options.sitemap === false ? false : options.sitemap === true ? { path: "/sitemap" } : options.sitemap;
|
|
457
472
|
addServerHandler({
|
|
458
473
|
method: "get",
|
|
459
474
|
route: `${options.api.baseURL}/query/**:params`,
|
|
@@ -474,7 +489,7 @@ const registerContentServerHandlers = (nuxt, options, resolveRuntimeModule, buil
|
|
|
474
489
|
route: `${options.api.baseURL}/site-data`,
|
|
475
490
|
handler: resolveRuntimeModule("./server/api/site-data.js")
|
|
476
491
|
});
|
|
477
|
-
if (
|
|
492
|
+
if (revalidate?.token) {
|
|
478
493
|
addServerHandler({
|
|
479
494
|
method: "post",
|
|
480
495
|
route: `${options.api.baseURL}/revalidate`,
|
|
@@ -486,10 +501,10 @@ const registerContentServerHandlers = (nuxt, options, resolveRuntimeModule, buil
|
|
|
486
501
|
route: nuxt.options.dev ? `${options.api.baseURL}/cache.json` : `${options.api.baseURL}/cache.${buildIntegrity}.json`,
|
|
487
502
|
handler: resolveRuntimeModule("./server/api/cache.js")
|
|
488
503
|
});
|
|
489
|
-
if (
|
|
504
|
+
if (sitemap !== false) {
|
|
490
505
|
addServerHandler({
|
|
491
506
|
method: "get",
|
|
492
|
-
route: `${options.api.baseURL}${
|
|
507
|
+
route: `${options.api.baseURL}${sitemap.path || "/sitemap"}`,
|
|
493
508
|
handler: resolveRuntimeModule("./server/api/sitemap.js")
|
|
494
509
|
});
|
|
495
510
|
}
|
|
@@ -505,6 +520,46 @@ const registerContentServerHandlers = (nuxt, options, resolveRuntimeModule, buil
|
|
|
505
520
|
handler: resolveRuntimeModule("./server/api/navigation.js")
|
|
506
521
|
});
|
|
507
522
|
}
|
|
523
|
+
const agent = normalizeAgentRouteOptions(options);
|
|
524
|
+
if (agent.routes) {
|
|
525
|
+
addServerHandler({
|
|
526
|
+
method: "get",
|
|
527
|
+
route: "/llms.txt",
|
|
528
|
+
handler: resolveRuntimeModule("./server/api/agent-llms.js")
|
|
529
|
+
});
|
|
530
|
+
addServerHandler({
|
|
531
|
+
method: "get",
|
|
532
|
+
route: "/llms-full.txt",
|
|
533
|
+
handler: resolveRuntimeModule("./server/api/agent-llms-full.js")
|
|
534
|
+
});
|
|
535
|
+
addServerHandler({
|
|
536
|
+
method: "get",
|
|
537
|
+
route: "/:locale/llms.txt",
|
|
538
|
+
handler: resolveRuntimeModule("./server/api/agent-llms.js")
|
|
539
|
+
});
|
|
540
|
+
addServerHandler({
|
|
541
|
+
method: "get",
|
|
542
|
+
route: "/:locale/llms-full.txt",
|
|
543
|
+
handler: resolveRuntimeModule("./server/api/agent-llms-full.js")
|
|
544
|
+
});
|
|
545
|
+
addServerHandler({
|
|
546
|
+
method: "get",
|
|
547
|
+
route: "/raw/**:slug",
|
|
548
|
+
handler: resolveRuntimeModule("./server/api/agent-raw.js")
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
if (agent.markdownNegotiation) {
|
|
552
|
+
addServerHandler({
|
|
553
|
+
middleware: true,
|
|
554
|
+
handler: resolveRuntimeModule("./server/middleware/agent-markdown.js")
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
if (agent.linkHeaders) {
|
|
558
|
+
addServerHandler({
|
|
559
|
+
middleware: true,
|
|
560
|
+
handler: resolveRuntimeModule("./server/middleware/agent-link-headers.js")
|
|
561
|
+
});
|
|
562
|
+
}
|
|
508
563
|
};
|
|
509
564
|
const registerContentSearchServerHandlers = (apiBaseURL, search, resolveRuntimeModule) => {
|
|
510
565
|
const searchBaseURL = search.apiBaseURL || `${apiBaseURL.replace(/\/$/, "")}/search`;
|
|
@@ -523,12 +578,58 @@ const registerContentSearchServerHandlers = (apiBaseURL, search, resolveRuntimeM
|
|
|
523
578
|
}
|
|
524
579
|
};
|
|
525
580
|
|
|
526
|
-
const
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
581
|
+
const registerContentComponentsTemplate = (addTemplateImpl) => {
|
|
582
|
+
addTemplateImpl({
|
|
583
|
+
filename: "content-components.mjs",
|
|
584
|
+
getContents({ app, nuxt }) {
|
|
585
|
+
const componentsMap = app.components.filter((component) => {
|
|
586
|
+
if (component.island) {
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
if (component.filePath.endsWith(".css")) {
|
|
590
|
+
return false;
|
|
591
|
+
}
|
|
592
|
+
if (component.pascalName === "ClientOnly" || component.filePath.includes("nuxt/dist/") || component.filePath.includes("NuxtWelcome")) {
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
return true;
|
|
596
|
+
}).reduce((map, component) => {
|
|
597
|
+
const importPath = isAbsolute(component.filePath) ? "./" + relative(nuxt.options.buildDir, component.filePath).replace(/\b\.(?!vue)\w+$/g, "") : component.filePath.replace(/\b\.(?!vue)\w+$/g, "");
|
|
598
|
+
map[component.pascalName] = map[component.pascalName] || [
|
|
599
|
+
component.pascalName,
|
|
600
|
+
importPath,
|
|
601
|
+
component.global,
|
|
602
|
+
component.export || "default"
|
|
603
|
+
];
|
|
604
|
+
return map;
|
|
605
|
+
}, {});
|
|
606
|
+
const componentsList = Object.values(componentsMap);
|
|
607
|
+
const globalComponents = componentsList.filter((component) => component[2]).map((component) => component[0]);
|
|
608
|
+
const localComponents = componentsList.filter((component) => !component[2]);
|
|
609
|
+
return [
|
|
610
|
+
"const pickExport = (mod, exportName, componentName, path) => {",
|
|
611
|
+
" const resolved = exportName === 'default' ? mod?.default || mod : mod?.[exportName]",
|
|
612
|
+
" if (!resolved) {",
|
|
613
|
+
' throw new Error(`[nuxt-content] Missing export "${exportName}" for component "${componentName}" in "${path}".`)',
|
|
614
|
+
" }",
|
|
615
|
+
" return resolved",
|
|
616
|
+
"}",
|
|
617
|
+
"export const localComponentLoaders = {",
|
|
618
|
+
...localComponents.map(([pascalName, path, , exp]) => {
|
|
619
|
+
const pathLiteral = JSON.stringify(path);
|
|
620
|
+
const exportLiteral = JSON.stringify(exp);
|
|
621
|
+
const nameLiteral = JSON.stringify(pascalName);
|
|
622
|
+
return ` ${pascalName}: () => import(${pathLiteral}).then(mod => pickExport(mod, ${exportLiteral}, ${nameLiteral}, ${pathLiteral})),`;
|
|
623
|
+
}),
|
|
624
|
+
"}",
|
|
625
|
+
`export const globalComponents = ${JSON.stringify(globalComponents)}`,
|
|
626
|
+
`export const localComponents = ${JSON.stringify(localComponents.map((component) => component[0]))}`
|
|
627
|
+
].join("\n");
|
|
628
|
+
}
|
|
629
|
+
});
|
|
531
630
|
};
|
|
631
|
+
|
|
632
|
+
const SITEMAP_INDEX = "sitemap_index.xml";
|
|
532
633
|
const countTag = (xml, tag) => (xml.match(new RegExp(`<${tag}>`, "g")) || []).length;
|
|
533
634
|
const extractLocValues = (xml) => {
|
|
534
635
|
return Array.from(xml.matchAll(/<loc>([^<]+)<\/loc>/g), (match) => match[1]);
|
|
@@ -595,10 +696,9 @@ const discoverSitemapsFromDisk = async (outputPublicDir) => {
|
|
|
595
696
|
}
|
|
596
697
|
const rootSitemapPath = join$1(outputPublicDir, "sitemap.xml");
|
|
597
698
|
const rootSitemapXml = await readFile(rootSitemapPath, "utf8");
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
);
|
|
699
|
+
if (!(countTag(rootSitemapXml, "url") > 0 || rootSitemapXml.includes("<urlset"))) {
|
|
700
|
+
throw new Error(`Content sitemap assertion failed: no child sitemap files were discovered in ${indexPath} or ${sitemapDir}, and ${rootSitemapPath} is not a urlset sitemap.`);
|
|
701
|
+
}
|
|
602
702
|
return [{
|
|
603
703
|
name: "sitemap",
|
|
604
704
|
path: rootSitemapPath,
|
|
@@ -633,7 +733,9 @@ async function assertGeneratedSitemaps({
|
|
|
633
733
|
logger
|
|
634
734
|
}) {
|
|
635
735
|
const discoveredSitemaps = targets || (outputPublicDir ? await discoverSitemapsFromDisk(outputPublicDir) : []);
|
|
636
|
-
|
|
736
|
+
if (discoveredSitemaps.length === 0) {
|
|
737
|
+
throw new Error("Content sitemap assertion failed: no sitemap targets were available for validation.");
|
|
738
|
+
}
|
|
637
739
|
const targetMap = new Map(discoveredSitemaps.map((target) => [target.name, target]));
|
|
638
740
|
const failures = [];
|
|
639
741
|
for (const sitemapName of Object.keys(options.sitemaps)) {
|
|
@@ -675,7 +777,7 @@ async function assertGeneratedSitemaps({
|
|
|
675
777
|
failures.push([
|
|
676
778
|
`- Placeholder sitemap URLs found: ${placeholderSiteUrls.join(", ")}`,
|
|
677
779
|
"Expected production URLs in generated sitemap loc values.",
|
|
678
|
-
"Set site.url or runtimeConfig.public.siteUrl to the deployed origin for production release checks."
|
|
780
|
+
"Set site.url or runtimeConfig.public.content.siteUrl to the deployed origin for production release checks."
|
|
679
781
|
].join(" "));
|
|
680
782
|
}
|
|
681
783
|
}
|
|
@@ -707,283 +809,14 @@ const createSitemapAssertionTargetsFromPrerenderedSitemaps = (sitemaps) => {
|
|
|
707
809
|
}
|
|
708
810
|
return true;
|
|
709
811
|
});
|
|
710
|
-
|
|
812
|
+
if (targets.length === 0) {
|
|
813
|
+
throw new Error("Content sitemap assertion failed: no sitemap urlsets were available from sitemap:prerender:done.");
|
|
814
|
+
}
|
|
711
815
|
return targets;
|
|
712
816
|
};
|
|
713
817
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
if (typeof entry === "string") {
|
|
717
|
-
return entry === name;
|
|
718
|
-
}
|
|
719
|
-
if (Array.isArray(entry) && typeof entry[0] === "string") {
|
|
720
|
-
return entry[0] === name;
|
|
721
|
-
}
|
|
722
|
-
return false;
|
|
723
|
-
});
|
|
724
|
-
}
|
|
725
|
-
function hasNuxtI18nModule(modules = []) {
|
|
726
|
-
return hasNuxtModule(modules, "@nuxtjs/i18n");
|
|
727
|
-
}
|
|
728
|
-
function hasNuxtSitemapModule(modules = []) {
|
|
729
|
-
return hasNuxtModule(modules, "@nuxtjs/sitemap");
|
|
730
|
-
}
|
|
731
|
-
function configureNuxtSitemapSource(nuxt, apiBaseURL, sitemapPath = "/sitemap") {
|
|
732
|
-
if (!hasNuxtSitemapModule(nuxt.options.modules)) {
|
|
733
|
-
return;
|
|
734
|
-
}
|
|
735
|
-
const source = {
|
|
736
|
-
context: {
|
|
737
|
-
name: GINKO_SITEMAP_SOURCE_NAME
|
|
738
|
-
},
|
|
739
|
-
fetch: resolveContentSitemapSource(apiBaseURL, sitemapPath)
|
|
740
|
-
};
|
|
741
|
-
const sitemap = nuxt.options.sitemap ??= {};
|
|
742
|
-
const sources = Array.isArray(sitemap.sources) ? sitemap.sources : [];
|
|
743
|
-
sitemap.sources = [
|
|
744
|
-
...sources.filter((item) => {
|
|
745
|
-
if (typeof item === "string") return item !== source.fetch;
|
|
746
|
-
return item?.fetch !== source.fetch && item?.context?.name !== GINKO_SITEMAP_SOURCE_NAME;
|
|
747
|
-
}),
|
|
748
|
-
source
|
|
749
|
-
];
|
|
750
|
-
}
|
|
751
|
-
function resolveNuxtSitemapPrerenderRoutes(nuxt) {
|
|
752
|
-
if (!hasNuxtSitemapModule(nuxt.options.modules)) {
|
|
753
|
-
return [];
|
|
754
|
-
}
|
|
755
|
-
const nuxtSitemap = nuxt.options.sitemap;
|
|
756
|
-
if (nuxtSitemap?.sitemaps === false) {
|
|
757
|
-
return ["/sitemap.xml"];
|
|
758
|
-
}
|
|
759
|
-
const nuxtI18n = nuxt.options.i18n || {};
|
|
760
|
-
if (!hasNuxtI18nModule(nuxt.options.modules) || !Array.isArray(nuxtI18n.locales) || nuxtI18n.locales.length === 0) {
|
|
761
|
-
return ["/sitemap.xml"];
|
|
762
|
-
}
|
|
763
|
-
const childRoutes = nuxtI18n.locales.map((locale) => typeof locale === "string" ? locale : locale.language || locale.code).filter(Boolean).map((locale) => `/__sitemap__/${locale}.xml`);
|
|
764
|
-
return Array.from(/* @__PURE__ */ new Set(["/sitemap.xml", "/sitemap_index.xml", ...childRoutes]));
|
|
765
|
-
}
|
|
766
|
-
function resolveModuleI18nOptions(options, nuxt) {
|
|
767
|
-
if (options.i18n === false) {
|
|
768
|
-
return {
|
|
769
|
-
locales: [],
|
|
770
|
-
defaultLocale: void 0,
|
|
771
|
-
fallback: {},
|
|
772
|
-
translatedSlugs: false,
|
|
773
|
-
strictTranslatedSlugs: false
|
|
774
|
-
};
|
|
775
|
-
}
|
|
776
|
-
const moduleI18n = options.i18n === true ? {} : options.i18n || {};
|
|
777
|
-
const nuxtI18n = nuxt.options.i18n || {};
|
|
778
|
-
const nuxtLocales = Array.isArray(nuxtI18n.locales) ? nuxtI18n.locales.map((locale) => typeof locale === "string" ? locale : locale.code).filter(Boolean) : [];
|
|
779
|
-
const locales = Array.from(new Set([
|
|
780
|
-
moduleI18n.defaultLocale,
|
|
781
|
-
nuxtI18n.defaultLocale,
|
|
782
|
-
...moduleI18n.locales || [],
|
|
783
|
-
...nuxtLocales
|
|
784
|
-
].filter(Boolean)));
|
|
785
|
-
const defaultLocale = moduleI18n.defaultLocale || nuxtI18n.defaultLocale || locales[0];
|
|
786
|
-
return {
|
|
787
|
-
locales,
|
|
788
|
-
defaultLocale,
|
|
789
|
-
fallback: defu({}, moduleI18n.fallback),
|
|
790
|
-
translatedSlugs: moduleI18n.translatedSlugs ?? false,
|
|
791
|
-
strictTranslatedSlugs: moduleI18n.strictTranslatedSlugs ?? false
|
|
792
|
-
};
|
|
793
|
-
}
|
|
794
|
-
function normalizeSitemapOptions(options) {
|
|
795
|
-
if (options.sitemap === false) {
|
|
796
|
-
return false;
|
|
797
|
-
}
|
|
798
|
-
const sitemap = options.sitemap === true ? {} : options.sitemap;
|
|
799
|
-
return {
|
|
800
|
-
path: sitemap.path || "/sitemap",
|
|
801
|
-
include: sitemap.include,
|
|
802
|
-
exclude: sitemap.exclude || [],
|
|
803
|
-
includeDrafts: sitemap.includeDrafts,
|
|
804
|
-
assert: normalizeContentSitemapAssertOptions(sitemap.assert)
|
|
805
|
-
};
|
|
806
|
-
}
|
|
807
|
-
function normalizeSearchOptions(options) {
|
|
808
|
-
if (options.search === false) {
|
|
809
|
-
return false;
|
|
810
|
-
}
|
|
811
|
-
return {
|
|
812
|
-
engine: options.search?.engine || "minisearch",
|
|
813
|
-
ignoredTags: options.search?.ignoredTags || ["script", "style", "pre"],
|
|
814
|
-
filterQuery: options.search?.filterQuery || { _draft: false, _partial: false },
|
|
815
|
-
collections: options.search?.collections,
|
|
816
|
-
extraFields: options.search?.extraFields || [],
|
|
817
|
-
apiBaseURL: options.search?.apiBaseURL,
|
|
818
|
-
minisearch: normalizeMiniSearchOptions(options.search?.minisearch)
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
const defaultMiniSearchOptions = {
|
|
822
|
-
fields: ["title", "content", "headings"],
|
|
823
|
-
storeFields: ["path", "title", "excerpt", "anchor", "locale", "collection"],
|
|
824
|
-
boost: {
|
|
825
|
-
title: 4,
|
|
826
|
-
headings: 2,
|
|
827
|
-
content: 1
|
|
828
|
-
},
|
|
829
|
-
fuzzy: 0.2,
|
|
830
|
-
prefix: true
|
|
831
|
-
};
|
|
832
|
-
const requiredMiniSearchStoreFields = ["path", "title", "excerpt"];
|
|
833
|
-
function normalizeMiniSearchOptions(options = {}) {
|
|
834
|
-
const fields = options?.fields?.filter((field) => typeof field === "string" && field.length > 0);
|
|
835
|
-
const storeFields = options?.storeFields?.filter((field) => typeof field === "string" && field.length > 0);
|
|
836
|
-
const boost = Object.fromEntries(
|
|
837
|
-
Object.entries(options?.boost || {}).filter((entry) => typeof entry[0] === "string" && entry[0].length > 0 && typeof entry[1] === "number" && Number.isFinite(entry[1]))
|
|
838
|
-
);
|
|
839
|
-
const resolvedFields = fields?.length ? fields : [...defaultMiniSearchOptions.fields];
|
|
840
|
-
const resolvedStoreFields = storeFields?.length ? storeFields : defaultMiniSearchOptions.storeFields;
|
|
841
|
-
return {
|
|
842
|
-
fields: resolvedFields,
|
|
843
|
-
storeFields: Array.from(/* @__PURE__ */ new Set([...requiredMiniSearchStoreFields, ...resolvedStoreFields])),
|
|
844
|
-
boost: Object.keys(boost).length ? boost : { ...defaultMiniSearchOptions.boost },
|
|
845
|
-
fuzzy: typeof options?.fuzzy === "boolean" || typeof options?.fuzzy === "number" ? options.fuzzy : defaultMiniSearchOptions.fuzzy,
|
|
846
|
-
prefix: typeof options?.prefix === "boolean" ? options.prefix : defaultMiniSearchOptions.prefix
|
|
847
|
-
};
|
|
848
|
-
}
|
|
849
|
-
function createSearchRuntimeConfig(search, apiBaseURL) {
|
|
850
|
-
const resolvedApiBaseURL = search.apiBaseURL || `${apiBaseURL.replace(/\/$/, "")}/search`;
|
|
851
|
-
return {
|
|
852
|
-
apiBaseURL: resolvedApiBaseURL,
|
|
853
|
-
indexURL: `${resolvedApiBaseURL.replace(/\/$/, "")}/index.json`,
|
|
854
|
-
engine: search.engine || "minisearch",
|
|
855
|
-
minisearch: normalizeMiniSearchOptions(search.minisearch)
|
|
856
|
-
};
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
const resolveNuxtSiteUrl = (nuxt) => {
|
|
860
|
-
const publicRuntime = nuxt.options.runtimeConfig.public;
|
|
861
|
-
const configuredSiteUrl = publicRuntime.siteUrl;
|
|
862
|
-
if (typeof configuredSiteUrl === "string" && configuredSiteUrl.length > 0) {
|
|
863
|
-
return configuredSiteUrl;
|
|
864
|
-
}
|
|
865
|
-
const nuxtSite = nuxt.options.site;
|
|
866
|
-
return typeof nuxtSite?.url === "string" && nuxtSite.url.length > 0 ? nuxtSite.url : void 0;
|
|
867
|
-
};
|
|
868
|
-
const applyContentRuntimeConfig = (nuxt, options, contentContext, runtimeCollections, buildIntegrity, cacheIntegrity) => {
|
|
869
|
-
const searchRuntime = contentContext.search === false ? false : {
|
|
870
|
-
apiBaseURL: contentContext.search.apiBaseURL || `${options.api.baseURL.replace(/\/$/, "")}/search`,
|
|
871
|
-
indexURL: `${(contentContext.search.apiBaseURL || `${options.api.baseURL.replace(/\/$/, "")}/search`).replace(/\/$/, "")}/index.json`,
|
|
872
|
-
engine: contentContext.search.engine || "minisearch",
|
|
873
|
-
minisearch: normalizeMiniSearchOptions(contentContext.search.minisearch)
|
|
874
|
-
};
|
|
875
|
-
const contentRuntime = defu(nuxt.options.runtimeConfig.public.content, {
|
|
876
|
-
locales: contentContext.locales,
|
|
877
|
-
provider: contentContext.provider || "filesystem",
|
|
878
|
-
providers: contentContext.providers || {},
|
|
879
|
-
defaultLocale: contentContext.defaultLocale || void 0,
|
|
880
|
-
localeFallback: contentContext.localeFallback || {},
|
|
881
|
-
translatedSlugs: contentContext.translatedSlugs ?? false,
|
|
882
|
-
strictTranslatedSlugs: contentContext.strictTranslatedSlugs ?? false,
|
|
883
|
-
collections: runtimeCollections,
|
|
884
|
-
integrity: buildIntegrity,
|
|
885
|
-
experimental: {
|
|
886
|
-
stripQueryParameters: options.experimental.stripQueryParameters
|
|
887
|
-
},
|
|
888
|
-
respectPathCase: options.respectPathCase ?? false,
|
|
889
|
-
api: {
|
|
890
|
-
baseURL: options.api.baseURL
|
|
891
|
-
},
|
|
892
|
-
markdown: {
|
|
893
|
-
plugins: contentContext.markdown.plugins,
|
|
894
|
-
tags: contentContext.markdown.tags,
|
|
895
|
-
anchorLinks: contentContext.markdown.anchorLinks,
|
|
896
|
-
image: contentContext.markdown.image || "auto"
|
|
897
|
-
},
|
|
898
|
-
sitemap: contentContext.sitemap ? {
|
|
899
|
-
path: contentContext.sitemap.path || "/sitemap",
|
|
900
|
-
...contentContext.sitemap.include?.length ? { include: contentContext.sitemap.include } : {},
|
|
901
|
-
...contentContext.sitemap.exclude?.length ? { exclude: contentContext.sitemap.exclude } : {},
|
|
902
|
-
...typeof contentContext.sitemap.includeDrafts === "boolean" ? { includeDrafts: contentContext.sitemap.includeDrafts } : {}
|
|
903
|
-
} : false,
|
|
904
|
-
search: searchRuntime,
|
|
905
|
-
navigation: contentContext.navigation,
|
|
906
|
-
wsUrl: "",
|
|
907
|
-
contentHead: options.contentHead ?? true
|
|
908
|
-
});
|
|
909
|
-
const siteUrl = resolveNuxtSiteUrl(nuxt);
|
|
910
|
-
if (siteUrl) {
|
|
911
|
-
nuxt.options.runtimeConfig.public.siteUrl = siteUrl;
|
|
912
|
-
}
|
|
913
|
-
nuxt.options.runtimeConfig.public.content = contentRuntime;
|
|
914
|
-
nuxt.options.runtimeConfig.content = defu(nuxt.options.runtimeConfig.content, {
|
|
915
|
-
cacheVersion: CACHE_VERSION,
|
|
916
|
-
cacheIntegrity,
|
|
917
|
-
revalidate: options.revalidate && options.revalidate !== false && options.revalidate.token ? {
|
|
918
|
-
token: options.revalidate.token,
|
|
919
|
-
allowUnsigned: options.revalidate.allowUnsigned === true
|
|
920
|
-
} : false,
|
|
921
|
-
...contentContext,
|
|
922
|
-
collections: runtimeCollections
|
|
923
|
-
});
|
|
924
|
-
};
|
|
925
|
-
|
|
926
|
-
const registerContentComponentsTemplate = (addTemplateImpl) => {
|
|
927
|
-
addTemplateImpl({
|
|
928
|
-
filename: "content-components.mjs",
|
|
929
|
-
getContents({ app, nuxt }) {
|
|
930
|
-
const componentsMap = app.components.filter((component) => {
|
|
931
|
-
if (component.island) {
|
|
932
|
-
return false;
|
|
933
|
-
}
|
|
934
|
-
if (component.filePath.endsWith(".css")) {
|
|
935
|
-
return false;
|
|
936
|
-
}
|
|
937
|
-
if (component.pascalName === "ClientOnly" || component.filePath.includes("nuxt/dist/") || component.filePath.includes("NuxtWelcome")) {
|
|
938
|
-
return false;
|
|
939
|
-
}
|
|
940
|
-
return true;
|
|
941
|
-
}).reduce((map, component) => {
|
|
942
|
-
const importPath = isAbsolute(component.filePath) ? "./" + relative(nuxt.options.buildDir, component.filePath).replace(/\b\.(?!vue)\w+$/g, "") : component.filePath.replace(/\b\.(?!vue)\w+$/g, "");
|
|
943
|
-
map[component.pascalName] = map[component.pascalName] || [
|
|
944
|
-
component.pascalName,
|
|
945
|
-
importPath,
|
|
946
|
-
component.global,
|
|
947
|
-
component.export || "default"
|
|
948
|
-
];
|
|
949
|
-
return map;
|
|
950
|
-
}, {});
|
|
951
|
-
const componentsList = Object.values(componentsMap);
|
|
952
|
-
const globalComponents = componentsList.filter((component) => component[2]).map((component) => component[0]);
|
|
953
|
-
const localComponents = componentsList.filter((component) => !component[2]);
|
|
954
|
-
return [
|
|
955
|
-
"const pickExport = (mod, exportName, componentName, path) => {",
|
|
956
|
-
" const resolved = exportName === 'default' ? mod?.default || mod : mod?.[exportName]",
|
|
957
|
-
" if (!resolved) {",
|
|
958
|
-
' throw new Error(`[nuxt-content] Missing export "${exportName}" for component "${componentName}" in "${path}".`)',
|
|
959
|
-
" }",
|
|
960
|
-
" return resolved",
|
|
961
|
-
"}",
|
|
962
|
-
"export const localComponentLoaders = {",
|
|
963
|
-
...localComponents.map(([pascalName, path, , exp]) => {
|
|
964
|
-
const pathLiteral = JSON.stringify(path);
|
|
965
|
-
const exportLiteral = JSON.stringify(exp);
|
|
966
|
-
const nameLiteral = JSON.stringify(pascalName);
|
|
967
|
-
return ` ${pascalName}: () => import(${pathLiteral}).then(mod => pickExport(mod, ${exportLiteral}, ${nameLiteral}, ${pathLiteral})),`;
|
|
968
|
-
}),
|
|
969
|
-
"}",
|
|
970
|
-
`export const globalComponents = ${JSON.stringify(globalComponents)}`,
|
|
971
|
-
`export const localComponents = ${JSON.stringify(localComponents.map((component) => component[0]))}`
|
|
972
|
-
].join("\n");
|
|
973
|
-
}
|
|
974
|
-
});
|
|
975
|
-
};
|
|
976
|
-
|
|
977
|
-
const appendHook = (hooks, name, handler) => {
|
|
978
|
-
const existing = hooks[name];
|
|
979
|
-
if (!existing) {
|
|
980
|
-
hooks[name] = handler;
|
|
981
|
-
return;
|
|
982
|
-
}
|
|
983
|
-
hooks[name] = Array.isArray(existing) ? [...existing, handler] : [existing, handler];
|
|
984
|
-
};
|
|
985
|
-
const resolveSitemapCollections = (collections, sitemap) => {
|
|
986
|
-
if (!sitemap || sitemap === false) {
|
|
818
|
+
const resolveSitemapCollections = (collections, sitemap) => {
|
|
819
|
+
if (!sitemap) {
|
|
987
820
|
return [];
|
|
988
821
|
}
|
|
989
822
|
const include = sitemap.include?.length ? sitemap.include : Object.keys(collections);
|
|
@@ -997,7 +830,7 @@ const toTranslatedSlugSourcePattern = (source) => {
|
|
|
997
830
|
return match ? `${match[1]}.*${match[2] || ""}` : segment;
|
|
998
831
|
}).join("/");
|
|
999
832
|
};
|
|
1000
|
-
const
|
|
833
|
+
const parseDerivedCollectionFiles = async (rootDir, collections, collectionNames, contentContext) => {
|
|
1001
834
|
const contentDir = resolve$1(rootDir, "content");
|
|
1002
835
|
const patterns = Array.from(new Set(
|
|
1003
836
|
collectionNames.flatMap((name) => {
|
|
@@ -1028,7 +861,7 @@ const parseCollectionFiles = async (rootDir, collections, collectionNames, conte
|
|
|
1028
861
|
for (const id of ids) {
|
|
1029
862
|
const file = resolve$1(contentDir, id);
|
|
1030
863
|
const content = await readFile(file, "utf8");
|
|
1031
|
-
const normalizedId = `content:${relative$1(contentDir, file).
|
|
864
|
+
const normalizedId = `content:${relative$1(contentDir, file).replace(/\\/g, "/")}`;
|
|
1032
865
|
const parsed = await transformContent(normalizedId, content, {
|
|
1033
866
|
markdown: contentContext.markdown,
|
|
1034
867
|
yaml: contentContext.yaml,
|
|
@@ -1042,29 +875,36 @@ const parseCollectionFiles = async (rootDir, collections, collectionNames, conte
|
|
|
1042
875
|
collectionResolver: (filePath) => resolveCollection(filePath, collections, contentContext.locales || [])
|
|
1043
876
|
}
|
|
1044
877
|
});
|
|
1045
|
-
const collection = parsed._collection ? collections[parsed._collection] : void 0;
|
|
1046
|
-
documents.push(...expandDataLocaleVariants(parsed, collection?.i18n));
|
|
878
|
+
const collection = typeof parsed._collection === "string" ? collections[parsed._collection] : void 0;
|
|
879
|
+
documents.push(...expandDataLocaleVariants(parsed, collection?.i18n === true ? void 0 : collection?.i18n));
|
|
1047
880
|
}
|
|
1048
881
|
return documents;
|
|
1049
882
|
};
|
|
1050
|
-
const
|
|
883
|
+
const collectDerivedDocuments = async (rootDir, contentContext) => {
|
|
1051
884
|
const collections = contentContext.collections || {};
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
const includeCollections = resolveSitemapCollections(collections, contentContext.sitemap);
|
|
1056
|
-
if (!includeCollections.length) {
|
|
1057
|
-
return [];
|
|
885
|
+
const includedCollections = resolveSitemapCollections(collections, contentContext.sitemap);
|
|
886
|
+
if (!includedCollections.length) {
|
|
887
|
+
return { collections, includedCollections, graph: buildContentGraph([], { locales: contentContext.locales, defaultLocale: contentContext.defaultLocale }) };
|
|
1058
888
|
}
|
|
1059
|
-
const documents = await
|
|
889
|
+
const documents = await parseDerivedCollectionFiles(rootDir, collections, includedCollections, contentContext);
|
|
1060
890
|
const graph = buildContentGraph(documents, {
|
|
1061
891
|
locales: contentContext.locales,
|
|
1062
892
|
defaultLocale: contentContext.defaultLocale
|
|
1063
893
|
});
|
|
894
|
+
return { collections, includedCollections, graph };
|
|
895
|
+
};
|
|
896
|
+
const collectDerivedPrerenderRoutes = async (rootDir, contentContext) => {
|
|
897
|
+
if (!contentContext.sitemap) {
|
|
898
|
+
return [];
|
|
899
|
+
}
|
|
900
|
+
const { includedCollections, graph } = await collectDerivedDocuments(rootDir, contentContext);
|
|
901
|
+
if (!includedCollections.length) {
|
|
902
|
+
return [];
|
|
903
|
+
}
|
|
1064
904
|
const routes = /* @__PURE__ */ new Set();
|
|
1065
|
-
for (const collection of
|
|
905
|
+
for (const collection of includedCollections) {
|
|
1066
906
|
const { defaultLocale } = resolveCollectionI18n(collection, contentContext);
|
|
1067
|
-
const includeDrafts =
|
|
907
|
+
const includeDrafts = Boolean(contentContext.sitemap.includeDrafts);
|
|
1068
908
|
const seenCanonicalKeys = /* @__PURE__ */ new Set();
|
|
1069
909
|
for (const contentId of graph.byCollection[collection] || []) {
|
|
1070
910
|
const document = graph.byId[contentId];
|
|
@@ -1091,18 +931,12 @@ const collectPrerenderRoutes = async (rootDir, contentContext) => {
|
|
|
1091
931
|
return Array.from(routes).sort();
|
|
1092
932
|
};
|
|
1093
933
|
const collectSitemapCollectionRouteCounts = async (rootDir, contentContext) => {
|
|
1094
|
-
const
|
|
1095
|
-
const includedCollections = resolveSitemapCollections(collections, contentContext.sitemap);
|
|
934
|
+
const { includedCollections, graph } = await collectDerivedDocuments(rootDir, contentContext);
|
|
1096
935
|
if (!includedCollections.length) {
|
|
1097
936
|
return {};
|
|
1098
937
|
}
|
|
1099
|
-
const documents = await parseCollectionFiles(rootDir, collections, includedCollections, contentContext);
|
|
1100
|
-
const graph = buildContentGraph(documents, {
|
|
1101
|
-
locales: contentContext.locales,
|
|
1102
|
-
defaultLocale: contentContext.defaultLocale
|
|
1103
|
-
});
|
|
1104
938
|
const counts = Object.fromEntries(includedCollections.map((collection) => [collection, 0]));
|
|
1105
|
-
const includeDrafts = contentContext.sitemap
|
|
939
|
+
const includeDrafts = contentContext.sitemap ? Boolean(contentContext.sitemap.includeDrafts) : false;
|
|
1106
940
|
for (const collection of includedCollections) {
|
|
1107
941
|
const seenCanonicalKeys = /* @__PURE__ */ new Set();
|
|
1108
942
|
for (const contentId of graph.byCollection[collection] || []) {
|
|
@@ -1126,12 +960,32 @@ const collectSitemapCollectionRouteCounts = async (rootDir, contentContext) => {
|
|
|
1126
960
|
}
|
|
1127
961
|
return counts;
|
|
1128
962
|
};
|
|
963
|
+
|
|
964
|
+
const appendHook = (hooks, name, handler) => {
|
|
965
|
+
const existing = hooks[name];
|
|
966
|
+
if (!existing) {
|
|
967
|
+
hooks[name] = handler;
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
hooks[name] = Array.isArray(existing) ? [...existing, handler] : [existing, handler];
|
|
971
|
+
};
|
|
1129
972
|
const registerContentNitroIntegrationHooks = (nitroConfig, options, contentContext) => {
|
|
1130
|
-
const
|
|
973
|
+
const getHookContentContext = () => {
|
|
974
|
+
if (!options.resolveContentContext) {
|
|
975
|
+
return contentContext;
|
|
976
|
+
}
|
|
977
|
+
try {
|
|
978
|
+
return options.resolveContentContext();
|
|
979
|
+
} catch {
|
|
980
|
+
return contentContext;
|
|
981
|
+
}
|
|
982
|
+
};
|
|
1131
983
|
nitroConfig.hooks ||= {};
|
|
1132
|
-
if (contentContext.sitemap
|
|
984
|
+
if (contentContext.sitemap && contentContext.sitemap.assert?.enabled) {
|
|
1133
985
|
appendHook(nitroConfig.hooks, "compiled", async (nitro) => {
|
|
1134
|
-
const
|
|
986
|
+
const hookContentContext = getHookContentContext();
|
|
987
|
+
const hookUsesFilesystemProvider = !hookContentContext.provider || hookContentContext.provider === "filesystem";
|
|
988
|
+
const assertOptions = hookContentContext.sitemap ? hookContentContext.sitemap.assert : void 0;
|
|
1135
989
|
if (!assertOptions || !shouldRunSitemapAssertionOnCompiled(assertOptions, nitro)) {
|
|
1136
990
|
return;
|
|
1137
991
|
}
|
|
@@ -1139,11 +993,11 @@ const registerContentNitroIntegrationHooks = (nitroConfig, options, contentConte
|
|
|
1139
993
|
await assertGeneratedSitemaps({
|
|
1140
994
|
outputPublicDir: nitro.options.output.publicDir,
|
|
1141
995
|
options: assertOptions,
|
|
1142
|
-
collectionRouteCounts:
|
|
996
|
+
collectionRouteCounts: hookUsesFilesystemProvider ? await collectSitemapCollectionRouteCounts(options.rootDir, hookContentContext) : {},
|
|
1143
997
|
logger: nitro.logger
|
|
1144
998
|
});
|
|
1145
999
|
} catch (error) {
|
|
1146
|
-
if (error
|
|
1000
|
+
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
1147
1001
|
return;
|
|
1148
1002
|
}
|
|
1149
1003
|
throw error;
|
|
@@ -1151,8 +1005,10 @@ const registerContentNitroIntegrationHooks = (nitroConfig, options, contentConte
|
|
|
1151
1005
|
});
|
|
1152
1006
|
}
|
|
1153
1007
|
appendHook(nitroConfig.hooks, "prerender:routes", async (routes) => {
|
|
1154
|
-
|
|
1155
|
-
|
|
1008
|
+
const hookContentContext = getHookContentContext();
|
|
1009
|
+
const hookUsesFilesystemProvider = !hookContentContext.provider || hookContentContext.provider === "filesystem";
|
|
1010
|
+
if (hookUsesFilesystemProvider) {
|
|
1011
|
+
for (const route of await collectDerivedPrerenderRoutes(options.rootDir, hookContentContext)) {
|
|
1156
1012
|
routes.add(route);
|
|
1157
1013
|
}
|
|
1158
1014
|
}
|
|
@@ -1163,10 +1019,155 @@ const registerContentNitroIntegrationHooks = (nitroConfig, options, contentConte
|
|
|
1163
1019
|
});
|
|
1164
1020
|
};
|
|
1165
1021
|
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1022
|
+
function hasNuxtModule(modules = [], name) {
|
|
1023
|
+
return modules.some((entry) => {
|
|
1024
|
+
if (typeof entry === "string") {
|
|
1025
|
+
return entry === name;
|
|
1026
|
+
}
|
|
1027
|
+
if (Array.isArray(entry) && typeof entry[0] === "string") {
|
|
1028
|
+
return entry[0] === name;
|
|
1029
|
+
}
|
|
1030
|
+
return false;
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
function hasNuxtI18nModule(modules = []) {
|
|
1034
|
+
return hasNuxtModule(modules, "@nuxtjs/i18n");
|
|
1035
|
+
}
|
|
1036
|
+
function hasNuxtSitemapModule(modules = []) {
|
|
1037
|
+
return hasNuxtModule(modules, "@nuxtjs/sitemap");
|
|
1038
|
+
}
|
|
1039
|
+
function configureNuxtSitemapSource(nuxt, apiBaseURL, sitemapPath = "/sitemap") {
|
|
1040
|
+
if (!hasNuxtSitemapModule(nuxt.options.modules)) {
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
const source = {
|
|
1044
|
+
context: {
|
|
1045
|
+
name: GINKO_SITEMAP_SOURCE_NAME
|
|
1046
|
+
},
|
|
1047
|
+
fetch: resolveContentSitemapSource(apiBaseURL, sitemapPath)
|
|
1048
|
+
};
|
|
1049
|
+
const sitemap = nuxt.options.sitemap ??= {};
|
|
1050
|
+
const sources = Array.isArray(sitemap.sources) ? sitemap.sources : [];
|
|
1051
|
+
sitemap.sources = [
|
|
1052
|
+
...sources.filter((item) => {
|
|
1053
|
+
if (typeof item === "string") return item !== source.fetch;
|
|
1054
|
+
return item?.fetch !== source.fetch && item?.context?.name !== GINKO_SITEMAP_SOURCE_NAME;
|
|
1055
|
+
}),
|
|
1056
|
+
source
|
|
1057
|
+
];
|
|
1058
|
+
}
|
|
1059
|
+
function resolveNuxtSitemapPrerenderRoutes(nuxt) {
|
|
1060
|
+
if (!hasNuxtSitemapModule(nuxt.options.modules)) {
|
|
1061
|
+
return [];
|
|
1062
|
+
}
|
|
1063
|
+
const nuxtSitemap = nuxt.options.sitemap;
|
|
1064
|
+
if (nuxtSitemap?.sitemaps === false) {
|
|
1065
|
+
return ["/sitemap.xml"];
|
|
1066
|
+
}
|
|
1067
|
+
const nuxtI18n = nuxt.options.i18n || {};
|
|
1068
|
+
if (!hasNuxtI18nModule(nuxt.options.modules) || !Array.isArray(nuxtI18n.locales) || nuxtI18n.locales.length === 0) {
|
|
1069
|
+
return ["/sitemap.xml"];
|
|
1070
|
+
}
|
|
1071
|
+
const childRoutes = nuxtI18n.locales.map((locale) => typeof locale === "string" ? locale : locale.language || locale.code).filter(Boolean).map((locale) => `/__sitemap__/${locale}.xml`);
|
|
1072
|
+
return Array.from(/* @__PURE__ */ new Set(["/sitemap.xml", "/sitemap_index.xml", ...childRoutes]));
|
|
1073
|
+
}
|
|
1074
|
+
function resolveModuleI18nOptions(options, nuxt) {
|
|
1075
|
+
if (options.i18n === false) {
|
|
1076
|
+
return {
|
|
1077
|
+
locales: [],
|
|
1078
|
+
defaultLocale: void 0,
|
|
1079
|
+
fallback: {},
|
|
1080
|
+
translatedSlugs: false,
|
|
1081
|
+
strictTranslatedSlugs: false
|
|
1082
|
+
};
|
|
1083
|
+
}
|
|
1084
|
+
const moduleI18n = options.i18n === true ? {} : options.i18n || {};
|
|
1085
|
+
const nuxtI18n = nuxt.options.i18n || {};
|
|
1086
|
+
const nuxtLocales = Array.isArray(nuxtI18n.locales) ? nuxtI18n.locales.map((locale) => typeof locale === "string" ? locale : locale.code).filter(Boolean) : [];
|
|
1087
|
+
const locales = Array.from(new Set([
|
|
1088
|
+
moduleI18n.defaultLocale,
|
|
1089
|
+
nuxtI18n.defaultLocale,
|
|
1090
|
+
...moduleI18n.locales || [],
|
|
1091
|
+
...nuxtLocales
|
|
1092
|
+
].filter(Boolean)));
|
|
1093
|
+
const defaultLocale = moduleI18n.defaultLocale || nuxtI18n.defaultLocale || locales[0];
|
|
1094
|
+
return {
|
|
1095
|
+
locales,
|
|
1096
|
+
defaultLocale,
|
|
1097
|
+
fallback: defu({}, moduleI18n.fallback),
|
|
1098
|
+
translatedSlugs: moduleI18n.translatedSlugs ?? false,
|
|
1099
|
+
strictTranslatedSlugs: moduleI18n.strictTranslatedSlugs ?? false
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
function normalizeSitemapOptions(options) {
|
|
1103
|
+
if (options.sitemap === false) {
|
|
1104
|
+
return false;
|
|
1105
|
+
}
|
|
1106
|
+
const sitemap = options.sitemap === true ? {} : options.sitemap;
|
|
1107
|
+
return {
|
|
1108
|
+
path: sitemap.path || "/sitemap",
|
|
1109
|
+
include: sitemap.include,
|
|
1110
|
+
exclude: sitemap.exclude || [],
|
|
1111
|
+
includeDrafts: sitemap.includeDrafts,
|
|
1112
|
+
assert: normalizeContentSitemapAssertOptions(sitemap.assert)
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
function normalizeSearchOptions(options) {
|
|
1116
|
+
if (options.search === false) {
|
|
1117
|
+
return false;
|
|
1118
|
+
}
|
|
1119
|
+
return {
|
|
1120
|
+
engine: options.search?.engine || "minisearch",
|
|
1121
|
+
ignoredTags: options.search?.ignoredTags || ["script", "style", "pre"],
|
|
1122
|
+
filterQuery: options.search?.filterQuery || { _draft: false, _partial: false },
|
|
1123
|
+
collections: options.search?.collections,
|
|
1124
|
+
extraFields: options.search?.extraFields || [],
|
|
1125
|
+
apiBaseURL: options.search?.apiBaseURL,
|
|
1126
|
+
minisearch: normalizeMiniSearchOptions(options.search?.minisearch)
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1129
|
+
const defaultMiniSearchOptions = {
|
|
1130
|
+
fields: ["title", "content", "headings"],
|
|
1131
|
+
storeFields: ["path", "title", "excerpt", "anchor", "locale", "collection"],
|
|
1132
|
+
boost: {
|
|
1133
|
+
title: 4,
|
|
1134
|
+
headings: 2,
|
|
1135
|
+
content: 1
|
|
1136
|
+
},
|
|
1137
|
+
fuzzy: 0.2,
|
|
1138
|
+
prefix: true
|
|
1139
|
+
};
|
|
1140
|
+
const requiredMiniSearchStoreFields = ["path", "title", "excerpt"];
|
|
1141
|
+
function normalizeMiniSearchOptions(options = {}) {
|
|
1142
|
+
const fields = options?.fields?.filter((field) => typeof field === "string" && field.length > 0);
|
|
1143
|
+
const storeFields = options?.storeFields?.filter((field) => typeof field === "string" && field.length > 0);
|
|
1144
|
+
const boost = Object.fromEntries(
|
|
1145
|
+
Object.entries(options?.boost || {}).filter((entry) => typeof entry[0] === "string" && entry[0].length > 0 && typeof entry[1] === "number" && Number.isFinite(entry[1]))
|
|
1146
|
+
);
|
|
1147
|
+
const resolvedFields = fields?.length ? fields : [...defaultMiniSearchOptions.fields];
|
|
1148
|
+
const resolvedStoreFields = storeFields?.length ? storeFields : defaultMiniSearchOptions.storeFields;
|
|
1149
|
+
return {
|
|
1150
|
+
fields: resolvedFields,
|
|
1151
|
+
storeFields: Array.from(/* @__PURE__ */ new Set([...requiredMiniSearchStoreFields, ...resolvedStoreFields])),
|
|
1152
|
+
boost: Object.keys(boost).length ? boost : { ...defaultMiniSearchOptions.boost },
|
|
1153
|
+
fuzzy: typeof options?.fuzzy === "boolean" || typeof options?.fuzzy === "number" ? options.fuzzy : defaultMiniSearchOptions.fuzzy,
|
|
1154
|
+
prefix: typeof options?.prefix === "boolean" ? options.prefix : defaultMiniSearchOptions.prefix
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
function createSearchRuntimeConfig(search, apiBaseURL) {
|
|
1158
|
+
const resolvedApiBaseURL = search.apiBaseURL || `${apiBaseURL.replace(/\/$/, "")}/search`;
|
|
1159
|
+
return {
|
|
1160
|
+
apiBaseURL: resolvedApiBaseURL,
|
|
1161
|
+
indexURL: `${resolvedApiBaseURL.replace(/\/$/, "")}/index.json`,
|
|
1162
|
+
engine: search.engine || "minisearch",
|
|
1163
|
+
minisearch: normalizeMiniSearchOptions(search.minisearch)
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
const getContentPageMeta = (page) => {
|
|
1168
|
+
const content = page.meta?.content;
|
|
1169
|
+
return content && typeof content === "object" ? content : void 0;
|
|
1170
|
+
};
|
|
1170
1171
|
const isRouteConfig = (value) => typeof value === "string" || value !== null && typeof value === "object" && Object.values(value).every((entry) => typeof entry === "string");
|
|
1171
1172
|
const describePage = (page) => page.file || page.path || "<unknown page>";
|
|
1172
1173
|
const expectedLocalesFor = (collection, locales, defaultLocale) => {
|
|
@@ -1218,6 +1219,568 @@ function validatePage(page, contentMeta, collections, options) {
|
|
|
1218
1219
|
}
|
|
1219
1220
|
}
|
|
1220
1221
|
|
|
1222
|
+
const hasAgentSurface = (config) => Boolean(
|
|
1223
|
+
config.agent || Object.values(config.collections || {}).some((collection) => Boolean(collection.agent?.markdown))
|
|
1224
|
+
);
|
|
1225
|
+
const agentSectionIds = (sections) => new Set((sections || []).map((section) => section.id).filter(Boolean));
|
|
1226
|
+
const validateAgentConfig = (config, options, context) => {
|
|
1227
|
+
if (!hasAgentSurface(config)) return;
|
|
1228
|
+
const agentRoutes = normalizeAgentRouteOptions(options);
|
|
1229
|
+
if (!context.dev && agentRoutes.routes && agentRoutes.prerender && !config.agent?.site?.url) {
|
|
1230
|
+
throw new Error(
|
|
1231
|
+
"@lupinum/ginko-content agent prerender requires agent.site.url for non-dev builds. Set agent.site.url in content.config.ts or disable content.agent.prerender."
|
|
1232
|
+
);
|
|
1233
|
+
}
|
|
1234
|
+
const sections = agentSectionIds(config.agent?.sections);
|
|
1235
|
+
const seenSections = /* @__PURE__ */ new Set();
|
|
1236
|
+
for (const section of config.agent?.sections || []) {
|
|
1237
|
+
if (!section.id) {
|
|
1238
|
+
throw new Error("@lupinum/ginko-content agent section ids must be non-empty strings.");
|
|
1239
|
+
}
|
|
1240
|
+
if (seenSections.has(section.id)) {
|
|
1241
|
+
throw new Error(`Duplicate Ginko agent section id "${section.id}". Agent section ids must be unique.`);
|
|
1242
|
+
}
|
|
1243
|
+
seenSections.add(section.id);
|
|
1244
|
+
}
|
|
1245
|
+
const assertSection = (id, owner) => {
|
|
1246
|
+
if (!id || id === "content") return;
|
|
1247
|
+
if (!sections.has(id)) {
|
|
1248
|
+
throw new Error(
|
|
1249
|
+
`${owner} references unknown Ginko agent section "${id}". Declare it in agent.sections or use the default "content" section.`
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
};
|
|
1253
|
+
for (const [name, collection] of Object.entries(config.collections || {})) {
|
|
1254
|
+
if (collection.agent?.markdown || collection.agent?.section) {
|
|
1255
|
+
assertSection(collection.agent.section, `Collection "${name}"`);
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
for (const page of config.agent?.pages || []) {
|
|
1259
|
+
assertSection(page.section, `Agent app page "${page.id}"`);
|
|
1260
|
+
}
|
|
1261
|
+
};
|
|
1262
|
+
|
|
1263
|
+
const normalizeStaticRoutePath = (path) => {
|
|
1264
|
+
if (!path || path === "/") return "/";
|
|
1265
|
+
return `/${path.replace(/\/+/g, "/").replace(/^\/+|\/+$/g, "")}`;
|
|
1266
|
+
};
|
|
1267
|
+
const collectRawMarkdownLinksFromLlms = (markdown, siteUrl) => {
|
|
1268
|
+
const links = /* @__PURE__ */ new Set();
|
|
1269
|
+
const pattern = /\[[^\]]*\]\(([^)]+)\)/g;
|
|
1270
|
+
for (const match of markdown.matchAll(pattern)) {
|
|
1271
|
+
const href = match[1];
|
|
1272
|
+
if (!href) continue;
|
|
1273
|
+
try {
|
|
1274
|
+
const url = /^[a-z][a-z0-9+.-]*:/i.test(href) ? new URL(href) : new URL(href, siteUrl || "http://localhost:3000");
|
|
1275
|
+
if (url.pathname.startsWith("/raw/") && url.pathname.endsWith(".md")) links.add(url.pathname);
|
|
1276
|
+
} catch {
|
|
1277
|
+
if (href.startsWith("/raw/") && href.endsWith(".md")) links.add(href);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
return Array.from(links);
|
|
1281
|
+
};
|
|
1282
|
+
const rawMarkdownRouteForPageRoute = (route) => {
|
|
1283
|
+
const normalized = normalizeStaticRoutePath(route);
|
|
1284
|
+
return normalized === "/" ? "/raw/index.md" : `/raw${normalized}.md`;
|
|
1285
|
+
};
|
|
1286
|
+
const collectRawMarkdownRoutesFromGeneratedFrontmatter = (markdown) => {
|
|
1287
|
+
const links = /* @__PURE__ */ new Set();
|
|
1288
|
+
const addRoutePath = (route) => {
|
|
1289
|
+
links.add(rawMarkdownRouteForPageRoute(route));
|
|
1290
|
+
};
|
|
1291
|
+
const addFrontmatterRoute = (frontmatter) => {
|
|
1292
|
+
const route = /^route:\s*"([^"]+)"/m.exec(frontmatter || "")?.[1];
|
|
1293
|
+
if (!route) return;
|
|
1294
|
+
addRoutePath(route);
|
|
1295
|
+
};
|
|
1296
|
+
const addSourceRoute = (source) => {
|
|
1297
|
+
if (!source) return;
|
|
1298
|
+
try {
|
|
1299
|
+
addRoutePath(new URL(source, "http://localhost:3000").pathname);
|
|
1300
|
+
} catch {
|
|
1301
|
+
addRoutePath(source);
|
|
1302
|
+
}
|
|
1303
|
+
};
|
|
1304
|
+
const sourcePattern = /^Source:\s+(\S+)/gm;
|
|
1305
|
+
for (const match of markdown.matchAll(sourcePattern)) {
|
|
1306
|
+
addSourceRoute(match[1]);
|
|
1307
|
+
}
|
|
1308
|
+
const pageFrontmatterPattern = /^Source:\s+[^\n]+\n\n---\n([\s\S]*?)\n---/gm;
|
|
1309
|
+
for (const match of markdown.matchAll(pageFrontmatterPattern)) {
|
|
1310
|
+
addFrontmatterRoute(match[1]);
|
|
1311
|
+
}
|
|
1312
|
+
const firstFrontmatter = /^---\n([\s\S]*?)\n---/.exec(markdown)?.[1];
|
|
1313
|
+
addFrontmatterRoute(firstFrontmatter);
|
|
1314
|
+
return Array.from(links);
|
|
1315
|
+
};
|
|
1316
|
+
const publicOutputPath = (publicDir, route) => join(publicDir, normalizeStaticRoutePath(route).replace(/^\//, ""));
|
|
1317
|
+
const rawMarkdownIndexRouteForRawRoute = (route) => {
|
|
1318
|
+
if (!route.startsWith("/raw/") || !route.endsWith(".md")) return null;
|
|
1319
|
+
const pageRoute = route.replace(/^\/raw/, "").replace(/\.md$/, "");
|
|
1320
|
+
return pageRoute === "/index" ? "/index.md" : `${pageRoute}/index.md`;
|
|
1321
|
+
};
|
|
1322
|
+
|
|
1323
|
+
const hookNuxtBoundary$2 = (nuxt, name, callback) => {
|
|
1324
|
+
const hook = nuxt.hook;
|
|
1325
|
+
hook(name, callback);
|
|
1326
|
+
};
|
|
1327
|
+
const registerStaticOutputGeneration = ({
|
|
1328
|
+
nuxt,
|
|
1329
|
+
options,
|
|
1330
|
+
appContentConfig,
|
|
1331
|
+
contentContext,
|
|
1332
|
+
resolvedI18n,
|
|
1333
|
+
resolveRuntimeModule,
|
|
1334
|
+
getSearchRuntime
|
|
1335
|
+
}) => {
|
|
1336
|
+
if (nuxt.options.dev) return;
|
|
1337
|
+
hookNuxtBoundary$2(nuxt, "nitro:build:before", (nitro) => {
|
|
1338
|
+
nitro.hooks.hook("prerender:init", (prerenderer) => {
|
|
1339
|
+
prerenderer.hooks.hook("compiled", async () => {
|
|
1340
|
+
const searchRuntime = getSearchRuntime();
|
|
1341
|
+
const publicDir = nitro.options.output.publicDir || nuxt.options.nitro?.output?.publicDir || resolve$1(nuxt.options.rootDir, ".output/public");
|
|
1342
|
+
const serverFilename = typeof prerenderer.options.rollupConfig?.output?.entryFileNames === "string" ? prerenderer.options.rollupConfig.output.entryFileNames : "index.mjs";
|
|
1343
|
+
const serverEntrypoint = resolve$1(prerenderer.options.output.serverDir, serverFilename);
|
|
1344
|
+
const { localFetch } = await import(pathToFileURL(serverEntrypoint).href);
|
|
1345
|
+
if (searchRuntime !== false && searchRuntime.engine !== "cms" && (!contentContext.provider || contentContext.provider === "filesystem")) {
|
|
1346
|
+
const response = await localFetch(searchRuntime.indexURL);
|
|
1347
|
+
if (!response.ok) {
|
|
1348
|
+
throw new Error(`Failed to generate search index: [${response.status}] ${response.statusText}`);
|
|
1349
|
+
}
|
|
1350
|
+
const json = await response.text();
|
|
1351
|
+
const indexPath = publicOutputPath(publicDir, searchRuntime.indexURL);
|
|
1352
|
+
mkdirSync(dirname(indexPath), { recursive: true });
|
|
1353
|
+
writeFileSync(indexPath, json, "utf8");
|
|
1354
|
+
if (searchRuntime.engine === "pagefind") {
|
|
1355
|
+
const records = JSON.parse(json);
|
|
1356
|
+
const { writePagefindIndex } = await import(resolveRuntimeModule("./server/pagefind.js"));
|
|
1357
|
+
await writePagefindIndex(records, resolve$1(publicDir, "pagefind"));
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
const agentRoutes = normalizeAgentRouteOptions(options);
|
|
1361
|
+
if (agentRoutes.routes && agentRoutes.prerender && appContentConfig.agent) {
|
|
1362
|
+
const defaultLocale = appContentConfig.agent.site?.defaultLocale || resolvedI18n.defaultLocale;
|
|
1363
|
+
const locales = appContentConfig.agent.site?.locales?.length ? appContentConfig.agent.site.locales : resolvedI18n.locales;
|
|
1364
|
+
const llmsRoutes = [
|
|
1365
|
+
"/llms.txt",
|
|
1366
|
+
"/llms-full.txt",
|
|
1367
|
+
...locales.filter((locale) => locale && locale !== defaultLocale).flatMap((locale) => [`/${locale}/llms.txt`, `/${locale}/llms-full.txt`])
|
|
1368
|
+
];
|
|
1369
|
+
const markdownRoutes = /* @__PURE__ */ new Set();
|
|
1370
|
+
for (const route of llmsRoutes) {
|
|
1371
|
+
const response = await localFetch(route);
|
|
1372
|
+
if (!response.ok) {
|
|
1373
|
+
throw new Error(`Failed to generate agent markdown route ${route}: [${response.status}] ${response.statusText}`);
|
|
1374
|
+
}
|
|
1375
|
+
const body = await response.text();
|
|
1376
|
+
const outputPath = publicOutputPath(publicDir, route);
|
|
1377
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
1378
|
+
writeFileSync(outputPath, body, "utf8");
|
|
1379
|
+
if (/\/llms\.txt$/i.test(route)) {
|
|
1380
|
+
collectRawMarkdownLinksFromLlms(body, appContentConfig.agent.site?.url).forEach((link) => markdownRoutes.add(link));
|
|
1381
|
+
} else if (/\/llms-full\.txt$/i.test(route)) {
|
|
1382
|
+
collectRawMarkdownRoutesFromGeneratedFrontmatter(body).forEach((link) => markdownRoutes.add(link));
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
for (const route of markdownRoutes) {
|
|
1386
|
+
const response = await localFetch(route);
|
|
1387
|
+
if (!response.ok) {
|
|
1388
|
+
throw new Error(`Failed to generate agent markdown route ${route}: [${response.status}] ${response.statusText}`);
|
|
1389
|
+
}
|
|
1390
|
+
const body = await response.text();
|
|
1391
|
+
const outputPath = publicOutputPath(publicDir, route);
|
|
1392
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
1393
|
+
writeFileSync(outputPath, body, "utf8");
|
|
1394
|
+
const indexRoute = rawMarkdownIndexRouteForRawRoute(route);
|
|
1395
|
+
if (indexRoute) {
|
|
1396
|
+
const indexPath = publicOutputPath(publicDir, indexRoute);
|
|
1397
|
+
mkdirSync(dirname(indexPath), { recursive: true });
|
|
1398
|
+
writeFileSync(indexPath, body, "utf8");
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
});
|
|
1403
|
+
});
|
|
1404
|
+
});
|
|
1405
|
+
};
|
|
1406
|
+
|
|
1407
|
+
const hookNuxtBoundary$1 = (nuxt, name, callback) => {
|
|
1408
|
+
const hook = nuxt.hook;
|
|
1409
|
+
hook(name, callback);
|
|
1410
|
+
};
|
|
1411
|
+
const registerContentNitroConfig = ({
|
|
1412
|
+
nuxt,
|
|
1413
|
+
options,
|
|
1414
|
+
appContentConfig,
|
|
1415
|
+
contentContext,
|
|
1416
|
+
runtimeInlineDependencies,
|
|
1417
|
+
buildIntegrity,
|
|
1418
|
+
resolvedI18n,
|
|
1419
|
+
resolveRuntimeModule,
|
|
1420
|
+
resolveModuleFile,
|
|
1421
|
+
getResolvedContentContext,
|
|
1422
|
+
getSearchRuntime
|
|
1423
|
+
}) => {
|
|
1424
|
+
hookNuxtBoundary$1(nuxt, "nitro:config", (nitroConfig) => {
|
|
1425
|
+
const searchRuntime = getSearchRuntime();
|
|
1426
|
+
nitroConfig.prerender = nitroConfig.prerender || {};
|
|
1427
|
+
nitroConfig.prerender.routes = nitroConfig.prerender.routes || [];
|
|
1428
|
+
const usesFilesystemProvider = !contentContext.provider || contentContext.provider === "filesystem";
|
|
1429
|
+
if (!nuxt.options.dev && usesFilesystemProvider) {
|
|
1430
|
+
nitroConfig.prerender.routes.unshift(`${options.api.baseURL}/cache.${buildIntegrity}.json`);
|
|
1431
|
+
}
|
|
1432
|
+
const sources = useContentMounts(nuxt, contentContext.sources);
|
|
1433
|
+
nitroConfig.devStorage = Object.assign(nitroConfig.devStorage || {}, sources);
|
|
1434
|
+
nitroConfig.devStorage["cache:content"] = {
|
|
1435
|
+
driver: "fs",
|
|
1436
|
+
base: resolve$1(nuxt.options.buildDir, "content-cache")
|
|
1437
|
+
};
|
|
1438
|
+
for (const source of Object.values(sources)) {
|
|
1439
|
+
if (source.driver === "fs" && typeof source.base === "string" && source.base.includes(nuxt.options.srcDir)) {
|
|
1440
|
+
const wildcard = join(source.base, "**/*").replace(withTrailingSlash(nuxt.options.srcDir), "");
|
|
1441
|
+
nuxt.options.ignore.push(wildcard, `!${wildcard}.vue`);
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
nitroConfig.bundledStorage = nitroConfig.bundledStorage || [];
|
|
1445
|
+
nitroConfig.bundledStorage.push("cache:content");
|
|
1446
|
+
nitroConfig.externals = defu(typeof nitroConfig.externals === "object" ? nitroConfig.externals : {}, {
|
|
1447
|
+
inline: [
|
|
1448
|
+
resolveModuleFile("./runtime"),
|
|
1449
|
+
...runtimeInlineDependencies
|
|
1450
|
+
]
|
|
1451
|
+
});
|
|
1452
|
+
if (searchRuntime !== false && searchRuntime.engine !== "cms" && usesFilesystemProvider) {
|
|
1453
|
+
nitroConfig.routeRules = nitroConfig.routeRules || {};
|
|
1454
|
+
nitroConfig.routeRules[searchRuntime.indexURL] = {
|
|
1455
|
+
prerender: true,
|
|
1456
|
+
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
1457
|
+
};
|
|
1458
|
+
}
|
|
1459
|
+
if (contentContext.sitemap !== false) {
|
|
1460
|
+
nitroConfig.plugins ||= [];
|
|
1461
|
+
const sitemapPlugin = resolveRuntimeModule("server/plugins/sitemap.js");
|
|
1462
|
+
if (!nitroConfig.plugins.includes(sitemapPlugin)) {
|
|
1463
|
+
nitroConfig.plugins.push(sitemapPlugin);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
if (contentContext.cache) {
|
|
1467
|
+
nitroConfig.plugins ||= [];
|
|
1468
|
+
const cachePlugin = resolveRuntimeModule("server/plugins/cache.js");
|
|
1469
|
+
if (!nitroConfig.plugins.includes(cachePlugin)) {
|
|
1470
|
+
nitroConfig.plugins.push(cachePlugin);
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
registerContentNitroIntegrationHooks(nitroConfig, {
|
|
1474
|
+
rootDir: nuxt.options.rootDir,
|
|
1475
|
+
sitemapPrerenderRoutes: () => contentContext.sitemap === false ? [] : resolveNuxtSitemapPrerenderRoutes(nuxt),
|
|
1476
|
+
resolveContentContext: getResolvedContentContext
|
|
1477
|
+
}, {
|
|
1478
|
+
collections: contentContext.collections,
|
|
1479
|
+
locales: contentContext.locales,
|
|
1480
|
+
defaultLocale: contentContext.defaultLocale,
|
|
1481
|
+
translatedSlugs: contentContext.translatedSlugs,
|
|
1482
|
+
respectPathCase: contentContext.respectPathCase,
|
|
1483
|
+
markdown: processMarkdownOptions(contentContext.markdown),
|
|
1484
|
+
yaml: contentContext.yaml,
|
|
1485
|
+
csv: contentContext.csv,
|
|
1486
|
+
sitemap: contentContext.sitemap,
|
|
1487
|
+
provider: contentContext.provider
|
|
1488
|
+
});
|
|
1489
|
+
const agentRoutes = normalizeAgentRouteOptions(options);
|
|
1490
|
+
if (agentRoutes.routes && agentRoutes.prerender && appContentConfig.agent) {
|
|
1491
|
+
nitroConfig.prerender.routes.push("/llms.txt", "/llms-full.txt");
|
|
1492
|
+
for (const locale of appContentConfig.agent.site?.locales || resolvedI18n.locales || []) {
|
|
1493
|
+
if (locale && locale !== (appContentConfig.agent.site?.defaultLocale || resolvedI18n.defaultLocale)) {
|
|
1494
|
+
nitroConfig.prerender.routes.push(`/${locale}/llms.txt`, `/${locale}/llms-full.txt`);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
for (const page of appContentConfig.agent.pages || []) {
|
|
1498
|
+
const routes = typeof page.route === "string" ? [page.route] : Object.values(page.route);
|
|
1499
|
+
for (const route of routes) {
|
|
1500
|
+
const normalized = route === "/" ? "/" : `/${route.replace(/^\/+|\/+$/g, "")}`;
|
|
1501
|
+
nitroConfig.prerender.routes.push(
|
|
1502
|
+
normalized === "/" ? "/raw/index.md" : `/raw${normalized}.md`,
|
|
1503
|
+
normalized === "/" ? "/index.md" : `${normalized}/index.md`
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
});
|
|
1509
|
+
};
|
|
1510
|
+
|
|
1511
|
+
const BUILTIN_PLUGIN_PEER_DEPS = {
|
|
1512
|
+
highlight: "shiki",
|
|
1513
|
+
math: "katex",
|
|
1514
|
+
mermaid: "beautiful-mermaid"
|
|
1515
|
+
};
|
|
1516
|
+
function assertConfiguredProviderAvailable(contentContext) {
|
|
1517
|
+
const provider = contentContext.provider || "filesystem";
|
|
1518
|
+
if (provider === "filesystem") return;
|
|
1519
|
+
if (contentContext.providers?.[provider]) return;
|
|
1520
|
+
if (provider === "cms") {
|
|
1521
|
+
throw new Error('content.config.ts sets provider "cms", but no CMS provider module registered it. Add @lupinum/ginko-cms to nuxt.config.ts modules or remove provider: "cms".');
|
|
1522
|
+
}
|
|
1523
|
+
throw new Error(`content.config.ts sets provider "${provider}", but no provider module registered it. Register a module for "${provider}" or add it to content providers.`);
|
|
1524
|
+
}
|
|
1525
|
+
function validateCollectionNames(collections) {
|
|
1526
|
+
normalizeContentConfigCollectionNames(collections);
|
|
1527
|
+
}
|
|
1528
|
+
function validateRemovedMarkdownOptions(options) {
|
|
1529
|
+
if (options.highlight !== void 0) {
|
|
1530
|
+
throw new Error("`content.highlight` was removed. Enable syntax highlighting with `content.markdown.plugins`, for example `[['highlight', { ...options }]]`.");
|
|
1531
|
+
}
|
|
1532
|
+
const markdown = options.markdown || {};
|
|
1533
|
+
const removedOptions = ["mdc", "remarkPlugins", "rehypePlugins", "toc"];
|
|
1534
|
+
const removed = removedOptions.filter((key) => typeof markdown[key] !== "undefined");
|
|
1535
|
+
if (removed.length) {
|
|
1536
|
+
throw new Error(`Removed markdown options: ${removed.map((option) => `content.markdown.${String(option)}`).join(", ")}. Use ordered \`content.markdown.plugins\` entries instead.`);
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
async function validateBuiltinMarkdownPlugins(plugins, resolvePath) {
|
|
1540
|
+
for (const plugin of plugins) {
|
|
1541
|
+
const peerDependency = BUILTIN_PLUGIN_PEER_DEPS[plugin.name];
|
|
1542
|
+
if (!peerDependency) {
|
|
1543
|
+
continue;
|
|
1544
|
+
}
|
|
1545
|
+
try {
|
|
1546
|
+
await resolvePath(peerDependency);
|
|
1547
|
+
} catch (error) {
|
|
1548
|
+
const next = new Error(`Markdown plugin "${plugin.name}" requires "${peerDependency}" to be installed.`);
|
|
1549
|
+
next.cause = error;
|
|
1550
|
+
throw next;
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
const contentModuleDefaults = {
|
|
1556
|
+
api: {
|
|
1557
|
+
baseURL: "/api/_content"
|
|
1558
|
+
},
|
|
1559
|
+
i18n: true,
|
|
1560
|
+
sitemap: true,
|
|
1561
|
+
search: {
|
|
1562
|
+
engine: "minisearch",
|
|
1563
|
+
ignoredTags: ["script", "style", "pre"],
|
|
1564
|
+
filterQuery: { _draft: false, _partial: false },
|
|
1565
|
+
extraFields: [],
|
|
1566
|
+
minisearch: {
|
|
1567
|
+
fields: [...defaultMiniSearchOptions.fields],
|
|
1568
|
+
storeFields: [...defaultMiniSearchOptions.storeFields],
|
|
1569
|
+
boost: { ...defaultMiniSearchOptions.boost },
|
|
1570
|
+
fuzzy: defaultMiniSearchOptions.fuzzy,
|
|
1571
|
+
prefix: defaultMiniSearchOptions.prefix
|
|
1572
|
+
}
|
|
1573
|
+
},
|
|
1574
|
+
watch: true,
|
|
1575
|
+
sources: {},
|
|
1576
|
+
ignores: [],
|
|
1577
|
+
collections: {},
|
|
1578
|
+
markdown: {
|
|
1579
|
+
plugins: [],
|
|
1580
|
+
tags: {
|
|
1581
|
+
code: "ProseCode",
|
|
1582
|
+
img: "ProseImg",
|
|
1583
|
+
pre: "ProsePre"
|
|
1584
|
+
},
|
|
1585
|
+
anchorLinks: {
|
|
1586
|
+
depth: 4,
|
|
1587
|
+
exclude: [1]
|
|
1588
|
+
},
|
|
1589
|
+
image: "auto"
|
|
1590
|
+
},
|
|
1591
|
+
yaml: {},
|
|
1592
|
+
csv: {
|
|
1593
|
+
delimiter: ",",
|
|
1594
|
+
json: true
|
|
1595
|
+
},
|
|
1596
|
+
navigation: {
|
|
1597
|
+
fields: []
|
|
1598
|
+
},
|
|
1599
|
+
agent: {
|
|
1600
|
+
routes: true,
|
|
1601
|
+
linkHeaders: true,
|
|
1602
|
+
markdownNegotiation: true,
|
|
1603
|
+
prerender: true
|
|
1604
|
+
},
|
|
1605
|
+
contentHead: true,
|
|
1606
|
+
respectPathCase: false,
|
|
1607
|
+
experimental: {
|
|
1608
|
+
stripQueryParameters: false
|
|
1609
|
+
}
|
|
1610
|
+
};
|
|
1611
|
+
|
|
1612
|
+
const resolveNuxtSiteUrl = (nuxt) => {
|
|
1613
|
+
const publicRuntime = nuxt.options.runtimeConfig.public;
|
|
1614
|
+
const publicContentRuntime = publicRuntime.content;
|
|
1615
|
+
const configuredSiteUrl = publicContentRuntime?.siteUrl || publicRuntime.siteUrl;
|
|
1616
|
+
if (typeof configuredSiteUrl === "string" && configuredSiteUrl.length > 0) {
|
|
1617
|
+
return configuredSiteUrl;
|
|
1618
|
+
}
|
|
1619
|
+
const nuxtSite = nuxt.options.site;
|
|
1620
|
+
return typeof nuxtSite?.url === "string" && nuxtSite.url.length > 0 ? nuxtSite.url : void 0;
|
|
1621
|
+
};
|
|
1622
|
+
const sanitizePublicMarkdownPluginValue = (value) => {
|
|
1623
|
+
if (typeof value === "function" || typeof value === "symbol") {
|
|
1624
|
+
return void 0;
|
|
1625
|
+
}
|
|
1626
|
+
if (Array.isArray(value)) {
|
|
1627
|
+
return value.map((item) => sanitizePublicMarkdownPluginValue(item)).filter((item) => item !== void 0);
|
|
1628
|
+
}
|
|
1629
|
+
if (typeof value !== "object" || value === null) {
|
|
1630
|
+
return value;
|
|
1631
|
+
}
|
|
1632
|
+
const prototype = Object.getPrototypeOf(value);
|
|
1633
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
1634
|
+
return value;
|
|
1635
|
+
}
|
|
1636
|
+
return Object.fromEntries(Object.entries(value).filter(([key]) => key !== "transformers").map(([key, item]) => [key, sanitizePublicMarkdownPluginValue(item)]).filter(([, item]) => item !== void 0));
|
|
1637
|
+
};
|
|
1638
|
+
const sanitizePublicMarkdownPlugins = (plugins) => plugins.map((plugin) => ({
|
|
1639
|
+
name: plugin.name,
|
|
1640
|
+
options: sanitizePublicMarkdownPluginValue(plugin.options || {})
|
|
1641
|
+
}));
|
|
1642
|
+
const sanitizePrivateMarkdownPluginValue = (value) => {
|
|
1643
|
+
if (typeof value === "function" || typeof value === "symbol") {
|
|
1644
|
+
return void 0;
|
|
1645
|
+
}
|
|
1646
|
+
if (Array.isArray(value)) {
|
|
1647
|
+
return value.map((item) => sanitizePrivateMarkdownPluginValue(item)).filter((item) => item !== void 0);
|
|
1648
|
+
}
|
|
1649
|
+
if (typeof value !== "object" || value === null) {
|
|
1650
|
+
return value;
|
|
1651
|
+
}
|
|
1652
|
+
const prototype = Object.getPrototypeOf(value);
|
|
1653
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
1654
|
+
return value;
|
|
1655
|
+
}
|
|
1656
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, sanitizePrivateMarkdownPluginValue(item)]).filter(([, item]) => item !== void 0));
|
|
1657
|
+
};
|
|
1658
|
+
const sanitizePrivateMarkdownPlugins = (plugins) => plugins.map((plugin) => ({
|
|
1659
|
+
name: plugin.name,
|
|
1660
|
+
options: sanitizePrivateMarkdownPluginValue(plugin.options || {})
|
|
1661
|
+
}));
|
|
1662
|
+
const applyContentRuntimeConfig = (nuxt, options, contentContext, runtimeCollections, buildIntegrity, cacheIntegrity) => {
|
|
1663
|
+
const revalidate = options.revalidate === false ? void 0 : options.revalidate;
|
|
1664
|
+
const searchRuntime = contentContext.search === false ? false : {
|
|
1665
|
+
apiBaseURL: contentContext.search.apiBaseURL || `${options.api.baseURL.replace(/\/$/, "")}/search`,
|
|
1666
|
+
indexURL: `${(contentContext.search.apiBaseURL || `${options.api.baseURL.replace(/\/$/, "")}/search`).replace(/\/$/, "")}/index.json`,
|
|
1667
|
+
engine: contentContext.search.engine || "minisearch",
|
|
1668
|
+
minisearch: normalizeMiniSearchOptions(contentContext.search.minisearch)
|
|
1669
|
+
};
|
|
1670
|
+
const siteUrl = resolveNuxtSiteUrl(nuxt);
|
|
1671
|
+
const contentRuntime = defu(nuxt.options.runtimeConfig.public.content, {
|
|
1672
|
+
...siteUrl ? { siteUrl } : {},
|
|
1673
|
+
locales: contentContext.locales,
|
|
1674
|
+
provider: contentContext.provider || "filesystem",
|
|
1675
|
+
providers: contentContext.providers || {},
|
|
1676
|
+
defaultLocale: contentContext.defaultLocale || void 0,
|
|
1677
|
+
localeFallback: contentContext.localeFallback || {},
|
|
1678
|
+
translatedSlugs: contentContext.translatedSlugs ?? false,
|
|
1679
|
+
strictTranslatedSlugs: contentContext.strictTranslatedSlugs ?? false,
|
|
1680
|
+
collections: runtimeCollections,
|
|
1681
|
+
integrity: buildIntegrity,
|
|
1682
|
+
experimental: {
|
|
1683
|
+
stripQueryParameters: options.experimental.stripQueryParameters
|
|
1684
|
+
},
|
|
1685
|
+
respectPathCase: options.respectPathCase ?? false,
|
|
1686
|
+
api: {
|
|
1687
|
+
baseURL: options.api.baseURL
|
|
1688
|
+
},
|
|
1689
|
+
markdown: {
|
|
1690
|
+
plugins: sanitizePublicMarkdownPlugins(contentContext.markdown.plugins),
|
|
1691
|
+
tags: contentContext.markdown.tags,
|
|
1692
|
+
anchorLinks: contentContext.markdown.anchorLinks,
|
|
1693
|
+
image: contentContext.markdown.image || "auto"
|
|
1694
|
+
},
|
|
1695
|
+
sitemap: contentContext.sitemap ? {
|
|
1696
|
+
path: contentContext.sitemap.path || "/sitemap",
|
|
1697
|
+
...contentContext.sitemap.include?.length ? { include: contentContext.sitemap.include } : {},
|
|
1698
|
+
...contentContext.sitemap.exclude?.length ? { exclude: contentContext.sitemap.exclude } : {},
|
|
1699
|
+
...typeof contentContext.sitemap.includeDrafts === "boolean" ? { includeDrafts: contentContext.sitemap.includeDrafts } : {}
|
|
1700
|
+
} : false,
|
|
1701
|
+
search: searchRuntime,
|
|
1702
|
+
navigation: contentContext.navigation,
|
|
1703
|
+
contentHead: options.contentHead ?? true
|
|
1704
|
+
});
|
|
1705
|
+
const privateContentRuntime = {
|
|
1706
|
+
...contentContext,
|
|
1707
|
+
markdown: {
|
|
1708
|
+
...contentContext.markdown,
|
|
1709
|
+
plugins: sanitizePrivateMarkdownPlugins(contentContext.markdown.plugins)
|
|
1710
|
+
}
|
|
1711
|
+
};
|
|
1712
|
+
nuxt.options.runtimeConfig.public.content = contentRuntime;
|
|
1713
|
+
nuxt.options.runtimeConfig.content = defu(nuxt.options.runtimeConfig.content, {
|
|
1714
|
+
cacheVersion: CACHE_VERSION,
|
|
1715
|
+
cacheIntegrity,
|
|
1716
|
+
revalidate: revalidate?.token ? {
|
|
1717
|
+
token: revalidate.token,
|
|
1718
|
+
allowUnsigned: revalidate.allowUnsigned === true
|
|
1719
|
+
} : false,
|
|
1720
|
+
...privateContentRuntime,
|
|
1721
|
+
collections: runtimeCollections
|
|
1722
|
+
});
|
|
1723
|
+
};
|
|
1724
|
+
|
|
1725
|
+
const registerContentContextFinalization = ({
|
|
1726
|
+
nuxt,
|
|
1727
|
+
options,
|
|
1728
|
+
contentContext,
|
|
1729
|
+
buildIntegrity,
|
|
1730
|
+
resolvePath,
|
|
1731
|
+
resolveRuntimeModule,
|
|
1732
|
+
onResolved
|
|
1733
|
+
}) => {
|
|
1734
|
+
nuxt.hook("modules:done", async () => {
|
|
1735
|
+
await nuxt.callHook("content:providers", contentContext.providers ||= {});
|
|
1736
|
+
assertConfiguredProviderAvailable(contentContext);
|
|
1737
|
+
await nuxt.callHook("content:context", contentContext);
|
|
1738
|
+
if (contentContext.search !== false) {
|
|
1739
|
+
registerContentSearchServerHandlers(options.api.baseURL, contentContext.search, resolveRuntimeModule);
|
|
1740
|
+
}
|
|
1741
|
+
contentContext.defaultLocale = contentContext.defaultLocale || contentContext.locales[0];
|
|
1742
|
+
const resolvedContentContext = {
|
|
1743
|
+
...contentContext,
|
|
1744
|
+
markdown: processMarkdownOptions(contentContext.markdown)
|
|
1745
|
+
};
|
|
1746
|
+
onResolved(resolvedContentContext);
|
|
1747
|
+
await validateBuiltinMarkdownPlugins(resolvedContentContext.markdown.plugins, resolvePath);
|
|
1748
|
+
const runtimeCollections = Object.fromEntries(Object.entries(options.collections || {}).map(([name, collection]) => {
|
|
1749
|
+
const references = collectTopLevelReferenceFieldsByTarget(collection.schema);
|
|
1750
|
+
return [
|
|
1751
|
+
name,
|
|
1752
|
+
{
|
|
1753
|
+
...collection.source ? { source: collection.source } : {},
|
|
1754
|
+
...collection.exclude ? { exclude: collection.exclude } : {},
|
|
1755
|
+
...collection.type ? { type: collection.type } : {},
|
|
1756
|
+
strict: collection.strict ?? true,
|
|
1757
|
+
...collection.route ? { route: collection.route } : {},
|
|
1758
|
+
...typeof collection.sitemap === "boolean" ? { sitemap: collection.sitemap } : {},
|
|
1759
|
+
...collection.i18n && collection.i18n !== true ? { i18n: collection.i18n } : {},
|
|
1760
|
+
...Object.keys(references).length ? { references } : {}
|
|
1761
|
+
}
|
|
1762
|
+
];
|
|
1763
|
+
}));
|
|
1764
|
+
const cacheIntegrity = hash({
|
|
1765
|
+
locales: resolvedContentContext.locales,
|
|
1766
|
+
defaultLocale: resolvedContentContext.defaultLocale,
|
|
1767
|
+
localeFallback: resolvedContentContext.localeFallback,
|
|
1768
|
+
translatedSlugs: resolvedContentContext.translatedSlugs,
|
|
1769
|
+
strictTranslatedSlugs: resolvedContentContext.strictTranslatedSlugs,
|
|
1770
|
+
respectPathCase: resolvedContentContext.respectPathCase,
|
|
1771
|
+
collections: runtimeCollections,
|
|
1772
|
+
markdown: resolvedContentContext.markdown,
|
|
1773
|
+
yaml: resolvedContentContext.yaml,
|
|
1774
|
+
csv: resolvedContentContext.csv
|
|
1775
|
+
});
|
|
1776
|
+
applyContentRuntimeConfig(nuxt, options, resolvedContentContext, runtimeCollections, buildIntegrity, cacheIntegrity);
|
|
1777
|
+
});
|
|
1778
|
+
};
|
|
1779
|
+
|
|
1780
|
+
const hookNuxtBoundary = (nuxt, name2, callback) => {
|
|
1781
|
+
const hook = nuxt.hook;
|
|
1782
|
+
hook(name2, callback);
|
|
1783
|
+
};
|
|
1221
1784
|
const module$1 = defineNuxtModule({
|
|
1222
1785
|
meta: {
|
|
1223
1786
|
name,
|
|
@@ -1236,69 +1799,7 @@ const module$1 = defineNuxtModule({
|
|
|
1236
1799
|
}
|
|
1237
1800
|
}
|
|
1238
1801
|
},
|
|
1239
|
-
defaults:
|
|
1240
|
-
api: {
|
|
1241
|
-
baseURL: "/api/_content"
|
|
1242
|
-
},
|
|
1243
|
-
i18n: true,
|
|
1244
|
-
sitemap: true,
|
|
1245
|
-
search: {
|
|
1246
|
-
engine: "minisearch",
|
|
1247
|
-
ignoredTags: ["script", "style", "pre"],
|
|
1248
|
-
filterQuery: { _draft: false, _partial: false },
|
|
1249
|
-
extraFields: [],
|
|
1250
|
-
minisearch: {
|
|
1251
|
-
fields: ["title", "content", "headings"],
|
|
1252
|
-
storeFields: ["path", "title", "excerpt", "anchor", "locale"],
|
|
1253
|
-
boost: {
|
|
1254
|
-
title: 4,
|
|
1255
|
-
headings: 2,
|
|
1256
|
-
content: 1
|
|
1257
|
-
},
|
|
1258
|
-
fuzzy: 0.2,
|
|
1259
|
-
prefix: true
|
|
1260
|
-
}
|
|
1261
|
-
},
|
|
1262
|
-
watch: {
|
|
1263
|
-
ws: {
|
|
1264
|
-
port: {
|
|
1265
|
-
port: 4e3,
|
|
1266
|
-
portRange: [4e3, 4040]
|
|
1267
|
-
},
|
|
1268
|
-
hostname: "localhost",
|
|
1269
|
-
showURL: false
|
|
1270
|
-
}
|
|
1271
|
-
},
|
|
1272
|
-
sources: {},
|
|
1273
|
-
ignores: [],
|
|
1274
|
-
collections: {},
|
|
1275
|
-
markdown: {
|
|
1276
|
-
plugins: [],
|
|
1277
|
-
tags: {
|
|
1278
|
-
code: "ProseCode",
|
|
1279
|
-
img: "ProseImg",
|
|
1280
|
-
pre: "ProsePre"
|
|
1281
|
-
},
|
|
1282
|
-
anchorLinks: {
|
|
1283
|
-
depth: 4,
|
|
1284
|
-
exclude: [1]
|
|
1285
|
-
},
|
|
1286
|
-
image: "auto"
|
|
1287
|
-
},
|
|
1288
|
-
yaml: {},
|
|
1289
|
-
csv: {
|
|
1290
|
-
delimiter: ",",
|
|
1291
|
-
json: true
|
|
1292
|
-
},
|
|
1293
|
-
navigation: {
|
|
1294
|
-
fields: []
|
|
1295
|
-
},
|
|
1296
|
-
contentHead: true,
|
|
1297
|
-
respectPathCase: false,
|
|
1298
|
-
experimental: {
|
|
1299
|
-
stripQueryParameters: false
|
|
1300
|
-
}
|
|
1301
|
-
},
|
|
1802
|
+
defaults: contentModuleDefaults,
|
|
1302
1803
|
async setup(options, nuxt) {
|
|
1303
1804
|
const { resolve, resolvePath } = createResolver(import.meta.url);
|
|
1304
1805
|
const logger = useLogger(name);
|
|
@@ -1317,6 +1818,10 @@ const module$1 = defineNuxtModule({
|
|
|
1317
1818
|
});
|
|
1318
1819
|
const contentConfigPath = resolveContentConfigPath(nuxt);
|
|
1319
1820
|
const appContentConfig = await loadContentConfig(nuxt);
|
|
1821
|
+
const externalGinkoContentConfig = nuxt.options.ginkoContent;
|
|
1822
|
+
if (externalGinkoContentConfig?.agent && options.agent !== false) {
|
|
1823
|
+
options.agent = defu(options.agent || {}, externalGinkoContentConfig.agent);
|
|
1824
|
+
}
|
|
1320
1825
|
if (!contentConfigPath || !appContentConfig.collections || !Object.keys(appContentConfig.collections).length) {
|
|
1321
1826
|
throw new Error("@lupinum/ginko-content requires a content.config.ts with at least one collection. Define collections with defineContentConfig({ collections: { ... } }).");
|
|
1322
1827
|
}
|
|
@@ -1324,6 +1829,10 @@ const module$1 = defineNuxtModule({
|
|
|
1324
1829
|
const resolvedSitemap = normalizeSitemapOptions(options);
|
|
1325
1830
|
const resolvedSearch = normalizeSearchOptions(options);
|
|
1326
1831
|
validateCollectionNames(appContentConfig.collections);
|
|
1832
|
+
if (!hasAgentSurface(appContentConfig)) {
|
|
1833
|
+
options.agent = false;
|
|
1834
|
+
}
|
|
1835
|
+
validateAgentConfig(appContentConfig, options, { dev: nuxt.options.dev });
|
|
1327
1836
|
options.collections = Object.fromEntries(Object.entries(appContentConfig.collections).map(([name2, collection]) => [
|
|
1328
1837
|
name2,
|
|
1329
1838
|
{
|
|
@@ -1353,25 +1862,32 @@ const module$1 = defineNuxtModule({
|
|
|
1353
1862
|
sitemap: resolvedSitemap,
|
|
1354
1863
|
search: resolvedSearch
|
|
1355
1864
|
};
|
|
1865
|
+
let resolvedContentContext;
|
|
1866
|
+
const getResolvedContentContext = () => {
|
|
1867
|
+
if (!resolvedContentContext) {
|
|
1868
|
+
throw new Error("Content runtime config was read before content context resolution completed.");
|
|
1869
|
+
}
|
|
1870
|
+
return resolvedContentContext;
|
|
1871
|
+
};
|
|
1356
1872
|
if (resolvedSitemap !== false) {
|
|
1357
1873
|
configureNuxtSitemapSource(nuxt, options.api.baseURL, resolvedSitemap.path);
|
|
1358
1874
|
}
|
|
1359
1875
|
nuxt.hook("pages:extend", (pages) => {
|
|
1360
|
-
validateContentPageRouteMetadata(pages, options.collections, {
|
|
1876
|
+
validateContentPageRouteMetadata(pages, options.collections || {}, {
|
|
1361
1877
|
locales: resolvedI18n.locales,
|
|
1362
1878
|
defaultLocale: resolvedI18n.defaultLocale
|
|
1363
1879
|
});
|
|
1364
1880
|
});
|
|
1365
1881
|
if (resolvedSitemap && resolvedSitemap.assert.enabled) {
|
|
1366
|
-
nuxt
|
|
1367
|
-
const assertOptions =
|
|
1882
|
+
hookNuxtBoundary(nuxt, "sitemap:prerender:done", async ({ sitemaps }) => {
|
|
1883
|
+
const assertOptions = resolvedSitemap ? resolvedSitemap.assert : void 0;
|
|
1368
1884
|
if (!assertOptions || !shouldRunSitemapAssertionOnPrerenderedSitemaps(assertOptions)) {
|
|
1369
1885
|
return;
|
|
1370
1886
|
}
|
|
1371
1887
|
await assertGeneratedSitemaps({
|
|
1372
1888
|
options: assertOptions,
|
|
1373
1889
|
targets: createSitemapAssertionTargetsFromPrerenderedSitemaps(sitemaps),
|
|
1374
|
-
collectionRouteCounts: await collectSitemapCollectionRouteCounts(nuxt.options.rootDir,
|
|
1890
|
+
collectionRouteCounts: await collectSitemapCollectionRouteCounts(nuxt.options.rootDir, getResolvedContentContext()),
|
|
1375
1891
|
logger
|
|
1376
1892
|
});
|
|
1377
1893
|
});
|
|
@@ -1389,146 +1905,40 @@ const module$1 = defineNuxtModule({
|
|
|
1389
1905
|
Object.keys(appContentConfig.collections),
|
|
1390
1906
|
Object.entries(appContentConfig.collections).filter(([, collection]) => Boolean(collection.i18n)).map(([name2]) => name2)
|
|
1391
1907
|
);
|
|
1392
|
-
await registerUserContentComponents(nuxt
|
|
1908
|
+
await registerUserContentComponents(nuxt);
|
|
1393
1909
|
const getSearchRuntime = () => contentContext.search === false ? false : createSearchRuntimeConfig(contentContext.search, options.api.baseURL);
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
base: resolve(nuxt.options.buildDir, "content-cache")
|
|
1407
|
-
};
|
|
1408
|
-
for (const source of Object.values(sources)) {
|
|
1409
|
-
if (source.driver === "fs" && source.base.includes(nuxt.options.srcDir)) {
|
|
1410
|
-
const wildcard = join(source.base, "**/*").replace(withTrailingSlash(nuxt.options.srcDir), "");
|
|
1411
|
-
nuxt.options.ignore.push(
|
|
1412
|
-
// Remove `srcDir` from the path
|
|
1413
|
-
wildcard,
|
|
1414
|
-
`!${wildcard}.vue`
|
|
1415
|
-
);
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
nitroConfig.bundledStorage = nitroConfig.bundledStorage || [];
|
|
1419
|
-
nitroConfig.bundledStorage.push("cache:content");
|
|
1420
|
-
nitroConfig.externals = defu(typeof nitroConfig.externals === "object" ? nitroConfig.externals : {}, {
|
|
1421
|
-
inline: [
|
|
1422
|
-
resolve("./runtime"),
|
|
1423
|
-
...runtimeInlineDependencies
|
|
1424
|
-
]
|
|
1425
|
-
});
|
|
1426
|
-
if (searchRuntime !== false && searchRuntime.engine !== "cms" && usesFilesystemProvider) {
|
|
1427
|
-
nitroConfig.routeRules = nitroConfig.routeRules || {};
|
|
1428
|
-
nitroConfig.routeRules[searchRuntime.indexURL] = {
|
|
1429
|
-
prerender: true,
|
|
1430
|
-
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
1431
|
-
};
|
|
1432
|
-
}
|
|
1433
|
-
if (contentContext.sitemap !== false) {
|
|
1434
|
-
nitroConfig.plugins ||= [];
|
|
1435
|
-
const sitemapPlugin = resolveRuntimeModule("server/plugins/sitemap.js");
|
|
1436
|
-
if (!nitroConfig.plugins.includes(sitemapPlugin)) {
|
|
1437
|
-
nitroConfig.plugins.push(sitemapPlugin);
|
|
1438
|
-
}
|
|
1439
|
-
}
|
|
1440
|
-
if (contentContext.cache && contentContext.cache !== false) {
|
|
1441
|
-
nitroConfig.plugins ||= [];
|
|
1442
|
-
const cachePlugin = resolveRuntimeModule("server/plugins/cache.js");
|
|
1443
|
-
if (!nitroConfig.plugins.includes(cachePlugin)) {
|
|
1444
|
-
nitroConfig.plugins.push(cachePlugin);
|
|
1445
|
-
}
|
|
1446
|
-
}
|
|
1447
|
-
registerContentNitroIntegrationHooks(nitroConfig, {
|
|
1448
|
-
rootDir: nuxt.options.rootDir,
|
|
1449
|
-
sitemapPrerenderRoutes: () => contentContext.sitemap === false ? [] : resolveNuxtSitemapPrerenderRoutes(nuxt)
|
|
1450
|
-
}, {
|
|
1451
|
-
collections: contentContext.collections,
|
|
1452
|
-
locales: contentContext.locales,
|
|
1453
|
-
defaultLocale: contentContext.defaultLocale,
|
|
1454
|
-
translatedSlugs: contentContext.translatedSlugs,
|
|
1455
|
-
strictTranslatedSlugs: contentContext.strictTranslatedSlugs,
|
|
1456
|
-
respectPathCase: contentContext.respectPathCase,
|
|
1457
|
-
markdown: contentContext.markdown,
|
|
1458
|
-
yaml: contentContext.yaml,
|
|
1459
|
-
csv: contentContext.csv,
|
|
1460
|
-
sitemap: contentContext.sitemap,
|
|
1461
|
-
provider: contentContext.provider
|
|
1462
|
-
});
|
|
1910
|
+
registerContentNitroConfig({
|
|
1911
|
+
nuxt,
|
|
1912
|
+
options,
|
|
1913
|
+
appContentConfig,
|
|
1914
|
+
contentContext,
|
|
1915
|
+
runtimeInlineDependencies,
|
|
1916
|
+
buildIntegrity,
|
|
1917
|
+
resolvedI18n,
|
|
1918
|
+
resolveRuntimeModule,
|
|
1919
|
+
resolveModuleFile: resolve,
|
|
1920
|
+
getResolvedContentContext,
|
|
1921
|
+
getSearchRuntime
|
|
1463
1922
|
});
|
|
1464
|
-
|
|
1465
|
-
nuxt
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
mkdirSync(dirname(indexPath), { recursive: true });
|
|
1483
|
-
writeFileSync(indexPath, json, "utf8");
|
|
1484
|
-
if (searchRuntime.engine === "pagefind") {
|
|
1485
|
-
const records = JSON.parse(json);
|
|
1486
|
-
const { writePagefindIndex } = await import(resolveRuntimeModule("./server/pagefind.js"));
|
|
1487
|
-
await writePagefindIndex(records, resolve$1(publicDir, "pagefind"));
|
|
1488
|
-
}
|
|
1489
|
-
});
|
|
1490
|
-
});
|
|
1491
|
-
});
|
|
1492
|
-
}
|
|
1493
|
-
nuxt.hook("modules:done", async () => {
|
|
1494
|
-
await nuxt.callHook("content:providers", contentContext.providers ||= {});
|
|
1495
|
-
assertConfiguredProviderAvailable(contentContext);
|
|
1496
|
-
await nuxt.callHook("content:context", contentContext);
|
|
1497
|
-
if (contentContext.search !== false) {
|
|
1498
|
-
registerContentSearchServerHandlers(options.api.baseURL, contentContext.search, resolveRuntimeModule);
|
|
1923
|
+
registerStaticOutputGeneration({
|
|
1924
|
+
nuxt,
|
|
1925
|
+
options,
|
|
1926
|
+
appContentConfig,
|
|
1927
|
+
contentContext,
|
|
1928
|
+
resolvedI18n,
|
|
1929
|
+
resolveRuntimeModule,
|
|
1930
|
+
getSearchRuntime
|
|
1931
|
+
});
|
|
1932
|
+
registerContentContextFinalization({
|
|
1933
|
+
nuxt,
|
|
1934
|
+
options,
|
|
1935
|
+
contentContext,
|
|
1936
|
+
buildIntegrity,
|
|
1937
|
+
resolvePath,
|
|
1938
|
+
resolveRuntimeModule,
|
|
1939
|
+
onResolved: (context) => {
|
|
1940
|
+
resolvedContentContext = context;
|
|
1499
1941
|
}
|
|
1500
|
-
contentContext.defaultLocale = contentContext.defaultLocale || contentContext.locales[0];
|
|
1501
|
-
contentContext.markdown = processMarkdownOptions(contentContext.markdown);
|
|
1502
|
-
await validateBuiltinMarkdownPlugins(contentContext.markdown.plugins, resolvePath);
|
|
1503
|
-
const runtimeCollections = Object.fromEntries(Object.entries(options.collections || {}).map(([name2, collection]) => {
|
|
1504
|
-
const references = collectTopLevelReferenceFieldsByTarget(collection.schema);
|
|
1505
|
-
return [
|
|
1506
|
-
name2,
|
|
1507
|
-
{
|
|
1508
|
-
...collection.source ? { source: collection.source } : {},
|
|
1509
|
-
...collection.exclude ? { exclude: collection.exclude } : {},
|
|
1510
|
-
...collection.type ? { type: collection.type } : {},
|
|
1511
|
-
strict: collection.strict ?? true,
|
|
1512
|
-
...collection.route ? { route: collection.route } : {},
|
|
1513
|
-
...typeof collection.sitemap === "boolean" ? { sitemap: collection.sitemap } : {},
|
|
1514
|
-
...collection.i18n && collection.i18n !== true ? { i18n: collection.i18n } : {},
|
|
1515
|
-
...Object.keys(references).length ? { references } : {}
|
|
1516
|
-
}
|
|
1517
|
-
];
|
|
1518
|
-
}));
|
|
1519
|
-
const cacheIntegrity = hash({
|
|
1520
|
-
locales: contentContext.locales,
|
|
1521
|
-
defaultLocale: contentContext.defaultLocale,
|
|
1522
|
-
localeFallback: contentContext.localeFallback,
|
|
1523
|
-
translatedSlugs: contentContext.translatedSlugs,
|
|
1524
|
-
strictTranslatedSlugs: contentContext.strictTranslatedSlugs,
|
|
1525
|
-
respectPathCase: contentContext.respectPathCase,
|
|
1526
|
-
collections: runtimeCollections,
|
|
1527
|
-
markdown: contentContext.markdown,
|
|
1528
|
-
yaml: contentContext.yaml,
|
|
1529
|
-
csv: contentContext.csv
|
|
1530
|
-
});
|
|
1531
|
-
applyContentRuntimeConfig(nuxt, options, contentContext, runtimeCollections, buildIntegrity, cacheIntegrity);
|
|
1532
1942
|
});
|
|
1533
1943
|
if (nuxt.options.dev) {
|
|
1534
1944
|
registerDevRuntimePlugin(resolveRuntimeModule);
|
|
@@ -1536,46 +1946,5 @@ const module$1 = defineNuxtModule({
|
|
|
1536
1946
|
}
|
|
1537
1947
|
}
|
|
1538
1948
|
});
|
|
1539
|
-
function assertConfiguredProviderAvailable(contentContext) {
|
|
1540
|
-
const provider = contentContext.provider || "filesystem";
|
|
1541
|
-
if (provider === "filesystem") return;
|
|
1542
|
-
if (contentContext.providers?.[provider]) return;
|
|
1543
|
-
if (provider === "cms") {
|
|
1544
|
-
throw new Error('content.config.ts sets provider "cms", but no CMS provider module registered it. Add @lupinum/ginko-cms to nuxt.config.ts modules or remove provider: "cms".');
|
|
1545
|
-
}
|
|
1546
|
-
throw new Error(`content.config.ts sets provider "${provider}", but no provider module registered it. Register a module for "${provider}" or add it to content providers.`);
|
|
1547
|
-
}
|
|
1548
|
-
function validateCollectionNames(collections) {
|
|
1549
|
-
normalizeContentConfigCollectionNames(collections);
|
|
1550
|
-
}
|
|
1551
|
-
function validateRemovedMarkdownOptions(options) {
|
|
1552
|
-
if (options.highlight !== void 0) {
|
|
1553
|
-
throw new Error("`content.highlight` was removed. Enable syntax highlighting with `content.markdown.plugins`, for example `[['highlight', { ...options }]]`.");
|
|
1554
|
-
}
|
|
1555
|
-
const markdown = options.markdown || {};
|
|
1556
|
-
const removedOptions = ["mdc", "remarkPlugins", "rehypePlugins", "toc"];
|
|
1557
|
-
const removed = removedOptions.filter((key) => typeof markdown[key] !== "undefined");
|
|
1558
|
-
if (removed.length) {
|
|
1559
|
-
throw new Error(`Removed markdown options: ${removed.map((option) => `content.markdown.${String(option)}`).join(", ")}. Use ordered \`content.markdown.plugins\` entries instead.`);
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
async function validateBuiltinMarkdownPlugins(plugins, resolvePath) {
|
|
1563
|
-
for (const plugin of plugins) {
|
|
1564
|
-
const peerDependency = BUILTIN_PLUGIN_PEER_DEPS[plugin.name];
|
|
1565
|
-
if (!peerDependency) {
|
|
1566
|
-
continue;
|
|
1567
|
-
}
|
|
1568
|
-
try {
|
|
1569
|
-
await resolvePath(peerDependency);
|
|
1570
|
-
} catch (error) {
|
|
1571
|
-
throw new Error(`Markdown plugin "${plugin.name}" requires "${peerDependency}" to be installed.`, { cause: error });
|
|
1572
|
-
}
|
|
1573
|
-
}
|
|
1574
|
-
}
|
|
1575
|
-
const BUILTIN_PLUGIN_PEER_DEPS = {
|
|
1576
|
-
highlight: "shiki",
|
|
1577
|
-
math: "katex",
|
|
1578
|
-
mermaid: "beautiful-mermaid"
|
|
1579
|
-
};
|
|
1580
1949
|
|
|
1581
1950
|
export { module$1 as default };
|