@lupinum/ginko-content 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/compatibility.json +1 -1
  2. package/dist/cli.mjs +2 -2
  3. package/dist/cms-contract/build.js +15 -20
  4. package/dist/cms-contract/types.d.ts +12 -7
  5. package/dist/core/content/document +1 -0
  6. package/dist/core/content/document.d.ts +16 -0
  7. package/dist/core/content/document.js +2 -0
  8. package/dist/core/content/graph.d.ts +3 -1
  9. package/dist/core/content/graph.js +21 -20
  10. package/dist/core/content/locale.d.ts +6 -1
  11. package/dist/core/content/locale.js +17 -6
  12. package/dist/core/content/path.d.ts +5 -5
  13. package/dist/core/content/path.js +8 -8
  14. package/dist/core/content/snapshot +1 -0
  15. package/dist/core/content/snapshot.d.ts +25 -0
  16. package/dist/core/content/snapshot.js +99 -0
  17. package/dist/core/provider-errors.d.ts +1 -1
  18. package/dist/core/provider-errors.js +1 -0
  19. package/dist/core/query/builder.js +3 -3
  20. package/dist/core/query/execute.js +75 -36
  21. package/dist/core/query/filter.js +2 -2
  22. package/dist/core/query/lower.js +79 -3
  23. package/dist/core/query/params.js +7 -7
  24. package/dist/core/query/plan.d.ts +18 -0
  25. package/dist/core/query/plan.js +7 -0
  26. package/dist/core/references/resolve.js +6 -9
  27. package/dist/features/agent/agent-markdown +1 -0
  28. package/dist/features/agent/agent-markdown.d.ts +116 -0
  29. package/dist/features/agent/agent-markdown.js +138 -0
  30. package/dist/features/agent/walker +1 -0
  31. package/dist/features/agent/walker.d.ts +10 -0
  32. package/dist/features/agent/walker.js +174 -0
  33. package/dist/features/collections/resolve.d.ts +2 -2
  34. package/dist/features/collections/resolve.js +19 -16
  35. package/dist/features/localization/links.js +1 -1
  36. package/dist/features/localization/results.d.ts +3 -3
  37. package/dist/features/localization/results.js +46 -41
  38. package/dist/features/localization/translated-slugs.js +5 -5
  39. package/dist/features/navigation/build.d.ts +2 -2
  40. package/dist/features/navigation/build.js +23 -26
  41. package/dist/features/navigation/canonical.d.ts +10 -11
  42. package/dist/features/navigation/canonical.js +26 -21
  43. package/dist/features/navigation/resolve.js +4 -4
  44. package/dist/features/navigation/tree.js +3 -3
  45. package/dist/{runtime → features}/query/backlinks.js +3 -5
  46. package/dist/{runtime → features}/query/documents.js +1 -1
  47. package/dist/{runtime → features}/query/localized-docs.d.ts +1 -1
  48. package/dist/{runtime → features}/query/localized-docs.js +3 -6
  49. package/dist/{runtime → features}/query/navigation.d.ts +1 -1
  50. package/dist/{runtime → features}/query/navigation.js +8 -8
  51. package/dist/{runtime → features}/query/populate.js +6 -14
  52. package/dist/{runtime → features}/query/unified.d.ts +4 -4
  53. package/dist/{runtime → features}/query/unified.js +4 -2
  54. package/dist/{runtime → features}/query/variants.js +4 -4
  55. package/dist/features/search/navigation.js +2 -2
  56. package/dist/features/search/sections.d.ts +1 -1
  57. package/dist/features/search/sections.js +1 -1
  58. package/dist/features/sitemap/query.d.ts +5 -5
  59. package/dist/features/sitemap/query.js +6 -6
  60. package/dist/integrations/nitro/ingest.js +9 -20
  61. package/dist/integrations/nitro/storage.d.ts +1 -0
  62. package/dist/integrations/nitro/storage.js +22 -8
  63. package/dist/module.d.mts +135 -812
  64. package/dist/module.json +1 -1
  65. package/dist/module.mjs +70 -27
  66. package/dist/parsers/csv.js +3 -3
  67. package/dist/parsers/index.js +3 -3
  68. package/dist/parsers/json.js +8 -6
  69. package/dist/parsers/markdown-plugins.js +9 -5
  70. package/dist/parsers/markdown.js +7 -6
  71. package/dist/parsers/path-meta.js +21 -19
  72. package/dist/parsers/reserved +1 -0
  73. package/dist/parsers/reserved.d.ts +15 -0
  74. package/dist/parsers/reserved.js +35 -0
  75. package/dist/parsers/yaml.js +6 -4
  76. package/dist/public/agent +1 -0
  77. package/dist/public/agent.d.ts +17 -0
  78. package/dist/public/agent.js +34 -0
  79. package/dist/public/client.d.ts +2 -3
  80. package/dist/public/client.js +1 -2
  81. package/dist/public/provider-query +1 -0
  82. package/dist/public/provider-query.d.ts +58 -0
  83. package/dist/public/provider-query.js +5 -0
  84. package/dist/public/provider.d.ts +8 -3
  85. package/dist/public/provider.js +2 -0
  86. package/dist/public/server.d.ts +7 -12
  87. package/dist/public/server.js +5 -36
  88. package/dist/runtime/app/components/ContentRenderer.d.vue.ts +3 -3
  89. package/dist/runtime/app/components/ContentRenderer.vue +2 -2
  90. package/dist/runtime/app/components/ContentRenderer.vue.d.ts +3 -3
  91. package/dist/runtime/app/components/ContentRendererInline.d.vue.ts +1 -1
  92. package/dist/runtime/app/components/ContentRendererInline.vue.d.ts +1 -1
  93. package/dist/runtime/app/components/Prose/ProseImg.d.vue.ts +4 -4
  94. package/dist/runtime/app/components/Prose/ProseImg.vue.d.ts +4 -4
  95. package/dist/runtime/app/components/Prose/ProsePre.d.vue.ts +1 -1
  96. package/dist/runtime/app/components/Prose/ProsePre.vue.d.ts +1 -1
  97. package/dist/runtime/app/components/internal/ContentRendererMarkdown.d.vue.ts +1 -1
  98. package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue +4 -4
  99. package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue.d.ts +1 -1
  100. package/dist/runtime/app/components/internal/MarkdownRenderer.d.ts +3 -3
  101. package/dist/runtime/app/composables/preview.d.ts +1 -1
  102. package/dist/runtime/app/composables/query-api.d.ts +5 -5
  103. package/dist/runtime/app/composables/query-api.js +5 -3
  104. package/dist/runtime/app/composables/route.d.ts +1 -1
  105. package/dist/runtime/app/composables/route.js +4 -4
  106. package/dist/runtime/app/composables/search.js +1 -1
  107. package/dist/runtime/app/composables/use-content-document.js +1 -1
  108. package/dist/runtime/app/composables/use-content-list.js +1 -1
  109. package/dist/runtime/app/composables/use-content-navigation.js +2 -2
  110. package/dist/runtime/app/composables/use-content-page.js +4 -4
  111. package/dist/runtime/app/pages/content.vue +2 -1
  112. package/dist/runtime/markdown/plugins.js +6 -8
  113. package/dist/runtime/server/agent-markdown.d.ts +5 -65
  114. package/dist/runtime/server/agent-markdown.js +40 -315
  115. package/dist/runtime/server/agent-site.js +1 -1
  116. package/dist/runtime/server/api/agent-raw.js +1 -1
  117. package/dist/runtime/server/api/cache.d.ts +1 -1
  118. package/dist/runtime/server/api/cache.js +43 -4
  119. package/dist/runtime/server/api/locales.js +3 -3
  120. package/dist/runtime/server/api/navigation.d.ts +1 -1
  121. package/dist/runtime/server/api/navigation.js +3 -1
  122. package/dist/runtime/server/api/query.js +2 -2
  123. package/dist/runtime/server/api/search-index.d.ts +1 -1
  124. package/dist/runtime/server/api/sitemap.d.ts +1 -1
  125. package/dist/runtime/server/cache-adapters.d.ts +18 -0
  126. package/dist/runtime/server/cache-adapters.js +12 -0
  127. package/dist/runtime/server/collection-helpers.d.ts +2 -2
  128. package/dist/runtime/server/collection-helpers.js +15 -11
  129. package/dist/runtime/server/index.d.ts +6 -4
  130. package/dist/runtime/server/index.js +10 -3
  131. package/dist/runtime/server/middleware/agent-link-headers.js +1 -1
  132. package/dist/runtime/server/middleware/agent-markdown.js +1 -1
  133. package/dist/runtime/server/navigation-query.d.ts +2 -2
  134. package/dist/runtime/server/navigation-query.js +52 -7
  135. package/dist/runtime/server/navigation.d.ts +1 -1
  136. package/dist/runtime/server/provider-document +1 -0
  137. package/dist/runtime/server/provider-document.d.ts +59 -0
  138. package/dist/runtime/server/provider-document.js +48 -0
  139. package/dist/runtime/server/provider-query-wire +1 -0
  140. package/dist/runtime/server/provider-query-wire.d.ts +32 -0
  141. package/dist/runtime/server/provider-query-wire.js +27 -0
  142. package/dist/runtime/server/provider-query.d.ts +18 -9
  143. package/dist/runtime/server/provider-query.js +62 -28
  144. package/dist/runtime/server/provider-result.d.ts +4 -4
  145. package/dist/runtime/server/providers/filesystem.js +3 -11
  146. package/dist/runtime/server/providers/index.d.ts +18 -1
  147. package/dist/runtime/server/providers/index.js +72 -20
  148. package/dist/runtime/server/query-api.d.ts +5 -5
  149. package/dist/runtime/server/query-api.js +9 -6
  150. package/dist/runtime/server/query-executor.d.ts +3 -3
  151. package/dist/runtime/server/query-executor.js +43 -59
  152. package/dist/runtime/server/search.d.ts +1 -1
  153. package/dist/runtime/server/search.js +4 -4
  154. package/dist/runtime/server/sitemap.js +5 -5
  155. package/dist/runtime/server/storage-access.d.ts +4 -1
  156. package/dist/runtime/server/storage-access.js +27 -2
  157. package/dist/runtime/transformers/component-resolver.d.ts +1 -1
  158. package/dist/storage/content.d.ts +2 -6
  159. package/dist/storage/content.js +19 -8
  160. package/dist/storage/contents.d.ts +9 -1
  161. package/dist/storage/contents.js +26 -19
  162. package/dist/storage/driver.d.ts +2 -2
  163. package/dist/storage/driver.js +2 -1
  164. package/dist/storage/graph.js +4 -0
  165. package/dist/storage/manifest.js +3 -1
  166. package/dist/storage/references.js +9 -5
  167. package/dist/storage/snapshot-runtime +1 -0
  168. package/dist/storage/snapshot-runtime.d.ts +11 -0
  169. package/dist/storage/snapshot-runtime.js +46 -0
  170. package/dist/storage/validation.d.ts +1 -1
  171. package/dist/storage/validation.js +47 -102
  172. package/dist/testing/provider-contract.d.ts +14 -4
  173. package/dist/testing/provider-contract.js +121 -68
  174. package/dist/testing/provider-fixture.d.ts +1 -1
  175. package/dist/testing/provider-fixture.js +124 -120
  176. package/dist/types/config.d.ts +8 -4
  177. package/dist/types/content.d.ts +104 -70
  178. package/dist/types/fields.js +1 -1
  179. package/dist/types/module.d.ts +1 -1
  180. package/dist/types/query-parts/public.d.ts +14 -5
  181. package/dist/types/query-parts/results.d.ts +6 -2
  182. package/dist/types/query-parts/transport.d.ts +19 -0
  183. package/dist/types/virtual.d.ts +6 -0
  184. package/dist/types.d.mts +2 -2
  185. package/dist/web-types.json +1 -1
  186. package/package.json +39 -9
  187. package/dist/runtime/app/plugins/markdown-components +0 -1
  188. package/dist/runtime/app/plugins/markdown-components.d.ts +0 -2
  189. package/dist/runtime/app/plugins/markdown-components.js +0 -19
  190. /package/dist/{runtime → features/agent}/agent-paths +0 -0
  191. /package/dist/{runtime → features/agent}/agent-paths.d.ts +0 -0
  192. /package/dist/{runtime → features/agent}/agent-paths.js +0 -0
  193. /package/dist/{runtime → features}/query/backlinks +0 -0
  194. /package/dist/{runtime → features}/query/backlinks.d.ts +0 -0
  195. /package/dist/{runtime → features}/query/context +0 -0
  196. /package/dist/{runtime → features}/query/context.d.ts +0 -0
  197. /package/dist/{runtime → features}/query/context.js +0 -0
  198. /package/dist/{runtime → features}/query/documents +0 -0
  199. /package/dist/{runtime → features}/query/documents.d.ts +0 -0
  200. /package/dist/{runtime → features}/query/errors +0 -0
  201. /package/dist/{runtime → features}/query/errors.d.ts +0 -0
  202. /package/dist/{runtime → features}/query/errors.js +0 -0
  203. /package/dist/{runtime → features}/query/handles +0 -0
  204. /package/dist/{runtime → features}/query/handles.d.ts +0 -0
  205. /package/dist/{runtime → features}/query/handles.js +0 -0
  206. /package/dist/{runtime → features}/query/locale-options +0 -0
  207. /package/dist/{runtime → features}/query/locale-options.d.ts +0 -0
  208. /package/dist/{runtime → features}/query/locale-options.js +0 -0
  209. /package/dist/{runtime → features}/query/localized-docs +0 -0
  210. /package/dist/{runtime → features}/query/navigation +0 -0
  211. /package/dist/{runtime → features}/query/pagination +0 -0
  212. /package/dist/{runtime → features}/query/pagination.d.ts +0 -0
  213. /package/dist/{runtime → features}/query/pagination.js +0 -0
  214. /package/dist/{runtime → features}/query/populate +0 -0
  215. /package/dist/{runtime → features}/query/populate.d.ts +0 -0
  216. /package/dist/{runtime → features}/query/public-limits +0 -0
  217. /package/dist/{runtime → features}/query/public-limits.d.ts +0 -0
  218. /package/dist/{runtime → features}/query/public-limits.js +0 -0
  219. /package/dist/{runtime → features}/query/resolve +0 -0
  220. /package/dist/{runtime → features}/query/resolve.d.ts +0 -0
  221. /package/dist/{runtime → features}/query/resolve.js +0 -0
  222. /package/dist/{runtime → features}/query/responses +0 -0
  223. /package/dist/{runtime → features}/query/responses.d.ts +0 -0
  224. /package/dist/{runtime → features}/query/responses.js +0 -0
  225. /package/dist/{runtime → features}/query/routes +0 -0
  226. /package/dist/{runtime → features}/query/routes.d.ts +0 -0
  227. /package/dist/{runtime → features}/query/routes.js +0 -0
  228. /package/dist/{runtime → features}/query/unified +0 -0
  229. /package/dist/{runtime → features}/query/variants +0 -0
  230. /package/dist/{runtime → features}/query/variants.d.ts +0 -0
@@ -32,10 +32,10 @@ const localePathMatches = (entry, path) => {
32
32
  const routeMetaMatchesPath = (value, path) => {
33
33
  if (!value) return false;
34
34
  const normalizedPath = normalizeRoutePath(path);
35
- const legacyPath = value;
36
- if (normalizeRoutePath(legacyPath._path) === normalizedPath || normalizeRoutePath(legacyPath._requestedPath) === normalizedPath || normalizeRoutePath(legacyPath._requestedRoute) === normalizedPath) return true;
37
- const requestedRoute = value.resolved?.requestedRoute ?? value._requestedRoute;
38
- return normalizeRoutePath(value.path) === normalizedPath || normalizeRoutePath(value.canonicalPath) === normalizedPath || normalizeRoutePath(requestedRoute) === normalizedPath || Object.values(value.localePaths || {}).some((entry) => localePathMatches(entry, path));
35
+ const resolved = value.resolved;
36
+ if (normalizeRoutePath(value.path) === normalizedPath || normalizeRoutePath(resolved?.requestedPath) === normalizedPath || normalizeRoutePath(resolved?.requestedRoute) === normalizedPath) return true;
37
+ const requestedRoute = resolved?.requestedRoute;
38
+ return normalizeRoutePath(value.path) === normalizedPath || normalizeRoutePath(value.unprefixedPath) === normalizedPath || normalizeRoutePath(requestedRoute) === normalizedPath || Object.values(value.localePaths || {}).some((entry) => localePathMatches(entry, path));
39
39
  };
40
40
  export async function useContentPage(handle, options = {}) {
41
41
  const route = useRoute();
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
- import { setResponseStatus, useContentPage } from "#imports";
2
+ import { setResponseStatus } from "nuxt/app";
3
+ import { useContentPage } from "../composables/use-content";
3
4
  const { page } = await useContentPage("pages", {
4
5
  notFound: false
5
6
  });
@@ -1,23 +1,21 @@
1
1
  import { defineAsyncComponent } from "vue";
2
2
  export { resolveMarkdownPlugins } from "../../parsers/markdown-plugins";
3
+ const importOptionalMarkdownComponent = async (specifier) => await import(
4
+ /* @vite-ignore */
5
+ specifier
6
+ );
3
7
  const builtinMarkdownPlugins = {
4
8
  math: {
5
9
  componentName: "Math",
6
10
  component: defineAsyncComponent(async () => {
7
- const mod = await import(
8
- /* @vite-ignore */
9
- ["@comark/vue", "plugins/math"].join("/")
10
- );
11
+ const mod = await importOptionalMarkdownComponent("@comark/vue/plugins/math");
11
12
  return mod.Math;
12
13
  })
13
14
  },
14
15
  mermaid: {
15
16
  componentName: "Mermaid",
16
17
  component: defineAsyncComponent(async () => {
17
- const mod = await import(
18
- /* @vite-ignore */
19
- ["@comark/vue", "plugins/mermaid"].join("/")
20
- );
18
+ const mod = await importOptionalMarkdownComponent("@comark/vue/plugins/mermaid");
21
19
  return mod.Mermaid;
22
20
  })
23
21
  }
@@ -1,74 +1,14 @@
1
1
  import type { H3Event } from 'h3';
2
- import type { MarkdownNode, ParsedContent } from '../../types/content';
3
- import type { AgentMetadataField, ContentCollectionConfig } from '../../types/config';
4
- export interface AgentMarkdownPublicSignals {
5
- search?: 'yes' | 'no';
6
- aiInput?: 'yes' | 'no';
7
- aiTrain?: 'yes' | 'no';
8
- }
9
- export interface ResolvedAgentMarkdownOptions {
10
- includeInIndex: boolean;
11
- includeInFull: boolean;
12
- metadata: AgentMetadataField[];
13
- }
14
- export interface AgentMarkdown {
15
- path: string;
16
- markdownPath: string;
17
- rawPath: string;
18
- locale?: string;
19
- collection: string;
20
- title: string;
21
- description: string;
22
- markdown: string;
23
- sourceFile?: string;
24
- canonicalUrl: string;
25
- lastModified?: string;
26
- publicSignals?: AgentMarkdownPublicSignals;
27
- metadataFields: string[];
28
- includeInIndex: boolean;
29
- includeInFull: boolean;
30
- }
31
- export type AgentMarkdownMeta = Omit<AgentMarkdown, 'markdown'>;
32
- export interface AgentMarkdownContext {
33
- collection: string;
34
- page: ParsedContent;
35
- path: string;
36
- locale?: string;
37
- prop: (name: string) => string;
38
- props: (node?: MarkdownNode) => Record<string, unknown>;
39
- cleanProps: (node?: MarkdownNode) => Record<string, unknown>;
40
- children: (node?: MarkdownNode) => string;
41
- renderChildren: (node: MarkdownNode) => string;
42
- renderNode: (node: MarkdownNode) => string;
43
- blockquote: (value: string) => string;
44
- jsonFence: (value: unknown) => string;
45
- link: (label: string, href: string) => string;
46
- omitted: (name: string, reason?: string) => string;
47
- xmlComponent: (name: string, props?: Record<string, unknown>, children?: string) => string;
48
- }
49
- export type AgentMarkdownSerializer = (node: MarkdownNode, ctx: AgentMarkdownContext) => string | null | undefined;
50
- export type AgentMarkdownSerializerMap = Record<string, AgentMarkdownSerializer>;
51
- export interface AgentMarkdownSerializerRegistrationOptions {
52
- override?: boolean;
53
- }
54
- export interface AgentMarkdownComponent {
55
- render: AgentMarkdownSerializer;
56
- }
57
- export type AgentMarkdownComponentMap = Record<string, AgentMarkdownComponent>;
58
- export declare const getMarkdownProp: (node: MarkdownNode, name: string) => string;
59
- export declare const renderMarkdownChildren: (node: MarkdownNode, ctx: AgentMarkdownContext) => string;
60
- export declare const blockquoteMarkdown: (value: string) => string;
61
- export declare const linkMarkdown: (label: string, href: string) => string;
62
- export declare const imageMarkdown: (alt: string, src: string) => string;
63
- export declare const jsonFenceMarkdown: (value: unknown) => string;
64
- export declare const xmlComponentMarkdown: (name: string, props?: Record<string, unknown>, children?: string) => string;
2
+ import type { AgentMarkdown, AgentMarkdownComponent, AgentMarkdownComponentMap, AgentMarkdownMeta, AgentMarkdownRegistry, AgentMarkdownSerializer, AgentMarkdownSerializerMap, AgentMarkdownSerializerRegistrationOptions } from '../../features/agent/agent-markdown';
3
+ export * from '../../features/agent/agent-markdown';
4
+ export { renderAgentMarkdownBody } from '../../features/agent/walker';
5
+ /** The current app's serializer registry the walker resolves tags against. */
6
+ export declare const getAgentMarkdownRegistry: () => AgentMarkdownRegistry;
65
7
  export declare const registerAgentMarkdownSerializer: (name: string, serializer: AgentMarkdownSerializer, options?: AgentMarkdownSerializerRegistrationOptions) => void;
66
8
  export declare const registerAgentMarkdownSerializers: (entries: AgentMarkdownSerializerMap, options?: AgentMarkdownSerializerRegistrationOptions) => void;
67
- export declare const defineAgentMarkdownComponent: (component: AgentMarkdownComponent) => AgentMarkdownComponent;
68
9
  export declare const registerAgentMarkdownComponent: (name: string, component: AgentMarkdownComponent, options?: AgentMarkdownSerializerRegistrationOptions) => void;
69
10
  export declare const registerAgentMarkdownComponents: (entries: AgentMarkdownComponentMap, options?: AgentMarkdownSerializerRegistrationOptions) => void;
70
11
  export declare const clearAgentMarkdownSerializers: () => void;
71
- export declare const resolveAgentMarkdownOptions: (collection: ContentCollectionConfig | undefined) => ResolvedAgentMarkdownOptions | null;
72
12
  export declare function resolveContentMarkdown(event: H3Event, collection: string, routeOrPath?: string, options?: {
73
13
  locale?: string;
74
14
  }): Promise<AgentMarkdown | null>;
@@ -1,324 +1,49 @@
1
- import { kebabCase, pascalCase } from "scule";
2
- import { agentMarkdownPathForRoute, agentRawPathForRoute, normalizeAgentRoutePath } from "../agent-paths.js";
3
- import { getCollectionPath } from "../query/routes.js";
1
+ import {
2
+ createAgentMarkdownRegistry,
3
+ resolveAgentMarkdownOptions
4
+ } from "../../features/agent/agent-markdown";
5
+ import { renderAgentMarkdownBody } from "../../features/agent/walker";
6
+ import { agentMarkdownPathForRoute, agentRawPathForRoute, normalizeAgentRoutePath } from "../../features/agent/agent-paths";
7
+ import { getCollectionPath } from "../../features/query/routes";
4
8
  import { getContentProvider } from "./providers/index.js";
9
+ import { createProviderQuery } from "./provider-query.js";
5
10
  import { contentConfig } from "./storage-access.js";
6
- const serializers = /* @__PURE__ */ new Map();
7
- const isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
11
+ export * from "../../features/agent/agent-markdown";
12
+ export { renderAgentMarkdownBody } from "../../features/agent/walker";
13
+ const appRegistry = createAgentMarkdownRegistry();
14
+ export const getAgentMarkdownRegistry = () => appRegistry;
15
+ export const registerAgentMarkdownSerializer = (name, serializer, options) => appRegistry.register(name, serializer, options);
16
+ export const registerAgentMarkdownSerializers = (entries, options) => appRegistry.registerMany(entries, options);
17
+ export const registerAgentMarkdownComponent = (name, component, options) => appRegistry.registerComponent(name, component, options);
18
+ export const registerAgentMarkdownComponents = (entries, options) => appRegistry.registerComponents(entries, options);
19
+ export const clearAgentMarkdownSerializers = () => appRegistry.clear();
8
20
  const defaultLocale = () => contentConfig().defaultLocale || contentConfig().locales?.[0] || contentConfig().agent?.site?.defaultLocale || "en";
9
21
  const configuredLocales = () => {
10
22
  const locales = contentConfig().agent?.site?.locales?.length ? contentConfig().agent?.site?.locales : contentConfig().locales;
11
23
  return locales?.length ? locales : [defaultLocale()];
12
24
  };
13
- const prefixLocalizedHref = (path, locale) => {
14
- const normalized = normalizeAgentRoutePath(path);
15
- if (!locale || locale === defaultLocale()) return normalized;
16
- if (configuredLocales().some((candidate) => normalized === `/${candidate}` || normalized.startsWith(`/${candidate}/`))) return normalized;
17
- return normalized === "/" ? `/${locale}` : `/${locale}${normalized}`;
18
- };
19
- const isExternalHref = (href) => /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith("//");
20
- const routeMarkdownPathForHref = (href, locale, currentPath = "/") => {
21
- const hash = href.match(/#.*$/)?.[0] || "";
22
- const withoutHash = href.replace(/#.*$/, "");
23
- if (!withoutHash) return href;
24
- if (isExternalHref(withoutHash)) return href;
25
- if (withoutHash.endsWith(".md")) return href;
26
- const target = withoutHash.startsWith("/") ? prefixLocalizedHref(withoutHash, locale) : new URL(withoutHash, `https://agent.local${normalizeAgentRoutePath(currentPath)}`).pathname;
27
- return `${agentRawPathForRoute(target)}${hash}`;
28
- };
29
- export const getMarkdownProp = (node, name) => {
30
- const props = isRecord(node.props) ? node.props : {};
31
- const value = props[name];
32
- return typeof value === "string" ? value : "";
33
- };
34
- export const renderMarkdownChildren = (node, ctx) => ctx.renderChildren(node);
35
- export const blockquoteMarkdown = (value) => value.trim().split("\n").map((line) => line ? `> ${line}` : ">").join("\n");
36
- const escapeMarkdownLinkLabel = (value) => value.replace(/\\/g, "\\\\").replace(/\[/g, "\\[").replace(/\]/g, "\\]");
37
- const escapeMarkdownLinkHref = (value) => value.replace(/\)/g, "%29").replace(/\s/g, "%20");
38
- const isSafeMarkdownHref = (href) => {
39
- if (!href) return false;
40
- if (href.startsWith("//")) return false;
41
- if (href.startsWith("/") || href.startsWith("#") || href.startsWith("./") || href.startsWith("../")) return true;
42
- return /^(https?:|mailto:|tel:)/i.test(href);
43
- };
44
- export const linkMarkdown = (label, href) => {
45
- const resolvedLabel = label || href;
46
- if (!href || !isSafeMarkdownHref(href)) return escapeMarkdownLinkLabel(resolvedLabel);
47
- return `[${escapeMarkdownLinkLabel(resolvedLabel)}](${escapeMarkdownLinkHref(href)})`;
48
- };
49
- export const imageMarkdown = (alt, src) => {
50
- if (!src || !isSafeMarkdownHref(src)) return escapeMarkdownLinkLabel(alt || src);
51
- return `![${escapeMarkdownLinkLabel(alt)}](${escapeMarkdownLinkHref(src)})`;
52
- };
53
- export const jsonFenceMarkdown = (value) => `\`\`\`json
54
- ${JSON.stringify(value, null, 2)}
55
- \`\`\``;
56
- const xmlNamePattern = /^[a-z][\w.:-]*$/i;
57
- const safeXmlName = (name) => xmlNamePattern.test(name) ? name : "component";
58
- const escapeXmlAttribute = (value) => value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
59
- const isScalarXmlAttributeValue = (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean";
60
- const shouldDropAgentProp = (name) => {
61
- const normalized = name.trim();
62
- const sensitive = normalized.toLowerCase();
63
- return !normalized || normalized === "class" || normalized === "style" || normalized === "key" || normalized === "ref" || normalized.startsWith("v-") || normalized.startsWith("@") || normalized.startsWith("on") || normalized.startsWith("data-") || normalized.startsWith("aria-") || /token|secret|password|passwd|credential|authorization|apikey|api-key|clientsecret|client-secret|privatekey|private-key|accesskey|access-key/i.test(sensitive);
64
- };
65
- const normalizeAgentPropName = (name) => {
66
- const normalized = name.trim();
67
- if (normalized.startsWith(":")) return normalized.slice(1);
68
- if (normalized.startsWith("v-bind:")) return normalized.slice("v-bind:".length);
69
- return normalized;
70
- };
71
- const cleanAgentPropValue = (value) => {
72
- if (value === void 0 || value === null || value === "") return void 0;
73
- if (Array.isArray(value)) {
74
- const clean = value.map((entry) => cleanAgentPropValue(entry)).filter((entry) => entry !== void 0);
75
- return clean.length ? clean : void 0;
76
- }
77
- if (isRecord(value)) {
78
- const clean = cleanPropsObject(value);
79
- return Object.keys(clean).length ? clean : void 0;
80
- }
81
- return value;
82
- };
83
- const cleanPropsObject = (props) => {
84
- if (!isRecord(props)) return {};
85
- const clean = {};
86
- for (const [name, value] of Object.entries(props)) {
87
- const normalizedName = normalizeAgentPropName(name);
88
- const cleanedValue = cleanAgentPropValue(value);
89
- if (shouldDropAgentProp(normalizedName) || cleanedValue === void 0) continue;
90
- if (!(normalizedName in clean) || normalizedName === name.trim()) {
91
- clean[normalizedName] = cleanedValue;
92
- }
93
- }
94
- return clean;
95
- };
96
- export const xmlComponentMarkdown = (name, props = {}, children = "") => {
97
- const tagName = safeXmlName(name);
98
- const cleanProps = cleanPropsObject(props);
99
- const attrs = [];
100
- const complexProps = {};
101
- for (const [key, value] of Object.entries(cleanProps)) {
102
- if (!xmlNamePattern.test(key)) {
103
- complexProps[key] = value;
104
- continue;
105
- }
106
- if (isScalarXmlAttributeValue(value)) {
107
- attrs.push(`${key}="${escapeXmlAttribute(String(value))}"`);
108
- continue;
109
- }
110
- complexProps[key] = value;
111
- }
112
- const attrText = attrs.length ? ` ${attrs.join(" ")}` : "";
113
- const bodyParts = [
114
- Object.keys(complexProps).length ? jsonFenceMarkdown(complexProps) : "",
115
- children.trim()
116
- ].filter(Boolean);
117
- if (!bodyParts.length) return `<${tagName}${attrText} />`;
118
- return `<${tagName}${attrText}>
119
- ${bodyParts.join("\n\n")}
120
- </${tagName}>`;
121
- };
122
- export const registerAgentMarkdownSerializer = (name, serializer, options = {}) => {
123
- const existing = serializers.get(name);
124
- if (existing === serializer && !options.override) return;
125
- if (existing && !options.override) {
126
- throw new Error(
127
- `Agent Markdown serializer "${name}" is already registered. Use { override: true } only when replacing an existing serializer intentionally.`
128
- );
129
- }
130
- serializers.set(name, serializer);
131
- };
132
- export const registerAgentMarkdownSerializers = (entries, options = {}) => {
133
- for (const [name, serializer] of Object.entries(entries)) {
134
- registerAgentMarkdownSerializer(name, serializer, options);
135
- }
136
- };
137
- export const defineAgentMarkdownComponent = (component) => component;
138
- export const registerAgentMarkdownComponent = (name, component, options = {}) => {
139
- registerAgentMarkdownSerializer(name, component.render, options);
140
- };
141
- export const registerAgentMarkdownComponents = (entries, options = {}) => {
142
- for (const [name, component] of Object.entries(entries)) {
143
- registerAgentMarkdownComponent(name, component, options);
144
- }
145
- };
146
- export const clearAgentMarkdownSerializers = () => {
147
- serializers.clear();
148
- };
149
- export const resolveAgentMarkdownOptions = (collection) => {
150
- if (!collection || collection.type === "data") return null;
151
- const value = collection.agent?.markdown;
152
- if (value === true) {
153
- return {
154
- includeInIndex: true,
155
- includeInFull: true,
156
- metadata: []
157
- };
158
- }
159
- if (!value || !isRecord(value)) return null;
160
- return {
161
- includeInIndex: value.includeInIndex !== false,
162
- includeInFull: value.includeInFull !== false,
163
- metadata: Array.isArray(value.metadata) ? value.metadata.filter((field) => typeof field === "string" && field.length > 0) : []
164
- };
165
- };
25
+ const buildRenderContext = (collection, page, path, locale) => ({
26
+ collection,
27
+ page,
28
+ path,
29
+ locale,
30
+ registry: appRegistry,
31
+ tagAliases: contentConfig().markdown?.tags || {},
32
+ defaultLocale: defaultLocale(),
33
+ locales: configuredLocales()
34
+ });
166
35
  const collectionConfig = (collection) => contentConfig().collections?.[collection];
167
36
  const markdownEnabledCollectionEntries = (collections) => Object.entries(contentConfig().collections || {}).filter(([name, config]) => (!collections?.length || collections.includes(name)) && resolveAgentMarkdownOptions(config));
168
37
  const isPublicPage = (page, config) => Boolean(
169
- page && config && config.type !== "data" && config.sitemap !== false && !page._draft && !page._partial && !page._navigation && page.navigation !== false && page.robots !== "noindex" && page.sitemap !== false
38
+ page && config && config.type !== "data" && config.sitemap !== false && !page.draft && !page.partial && !page.navigationFile && page.navigation !== false && page.robots !== "noindex" && page.sitemap !== false
170
39
  );
171
40
  const escapeMarkdownText = (value) => value.replace(/\*/g, "\\*").replace(/_/g, "\\_").replace(/\[/g, "\\[").replace(/\]/g, "\\]");
172
- const textValue = (node) => {
173
- if (node.type === "text") return node.value || "";
174
- return (node.children || []).map((child) => textValue(child)).join("");
175
- };
176
- const renderChildren = (node, ctx) => (node.children || []).map((child) => renderNode(child, ctx)).join("").trim();
177
- const block = (value) => value.trim() ? `${value.trim()}
178
-
179
- ` : "";
180
- const renderList = (node, ctx, ordered = false) => block((node.children || []).map((child, index) => {
181
- const body = renderChildren(child, ctx).replace(/\n+/g, "\n ").trim();
182
- return `${ordered ? `${index + 1}.` : "-"} ${body}`;
183
- }).join("\n"));
184
- const renderTable = (node, ctx) => {
185
- const rows = (node.children || []).flatMap(
186
- (section) => section.tag === "thead" || section.tag === "tbody" ? section.children || [] : [section]
187
- ).filter((row) => row.tag === "tr");
188
- if (!rows.length) return "";
189
- const cells = rows.map(
190
- (row) => (row.children || []).filter((cell) => cell.tag === "th" || cell.tag === "td").map((cell) => renderChildren(cell, ctx).replace(/\|/g, "\\|").trim())
191
- );
192
- const width = Math.max(...cells.map((row) => row.length));
193
- const normalized = cells.map((row) => [...row, ...Array.from({ length: width - row.length }, () => "")]);
194
- const [head = [], ...bodyRows] = normalized;
195
- return block([
196
- `| ${head.join(" | ")} |`,
197
- `| ${head.map(() => "---").join(" | ")} |`,
198
- ...bodyRows.map((row) => `| ${row.join(" | ")} |`)
199
- ].join("\n"));
200
- };
201
- const renderUnknownComponentOmission = (name, reason) => `> Component omitted: \`${name}\`.
202
- > ${reason || "This page contains an interactive or site-specific block that has no agent markdown serializer yet."}`;
203
- const renderUnknownComponent = (node, ctx) => {
204
- const tag = node.tag || "component";
205
- const props = cleanPropsObject(node.props);
206
- const children = renderChildren(node, ctx);
207
- if (children || Object.keys(props).length) {
208
- return block(xmlComponentMarkdown(tag, props, children));
209
- }
210
- return block(renderUnknownComponentOmission(tag));
211
- };
212
- const serializerForTag = (tag) => {
213
- const markdownTags = contentConfig().markdown?.tags || {};
214
- const candidates = new Set([
215
- tag,
216
- pascalCase(tag),
217
- kebabCase(tag),
218
- markdownTags[tag],
219
- markdownTags[pascalCase(tag)],
220
- markdownTags[kebabCase(tag)]
221
- ].filter((value) => Boolean(value)));
222
- for (const candidate of candidates) {
223
- const serializer = serializers.get(candidate);
224
- if (serializer) return serializer;
225
- }
226
- };
227
- const renderNode = (node, ctx) => {
228
- if (node.type === "text") return node.value || "";
229
- const tag = node.tag || "";
230
- const serializer = tag ? serializerForTag(tag) : void 0;
231
- if (serializer) {
232
- const nodeCtx = {
233
- ...ctx,
234
- prop: (name) => getMarkdownProp(node, name),
235
- props: (target) => isRecord((target || node).props) ? (target || node).props : {},
236
- cleanProps: (target) => cleanPropsObject((target || node).props),
237
- children: (target) => renderChildren(target || node, nodeCtx)
238
- };
239
- const rendered = serializer(node, nodeCtx);
240
- if (typeof rendered === "string") return block(rendered);
241
- }
242
- if (!tag) return renderChildren(node, ctx);
243
- if (/^h[1-6]$/.test(tag)) {
244
- const depth = Number(tag.slice(1));
245
- return block(`${"#".repeat(Math.max(1, Math.min(6, depth)))} ${renderChildren(node, ctx)}`);
246
- }
247
- switch (tag) {
248
- case "p":
249
- return block(renderChildren(node, ctx));
250
- case "blockquote":
251
- return block(renderChildren(node, ctx).split("\n").map((line) => `> ${line}`).join("\n"));
252
- case "strong":
253
- case "b":
254
- return `**${renderChildren(node, ctx)}**`;
255
- case "em":
256
- case "i":
257
- return `_${renderChildren(node, ctx)}_`;
258
- case "span":
259
- return renderChildren(node, ctx);
260
- case "code":
261
- return `\`${node.value || textValue(node)}\``;
262
- case "pre":
263
- return block(`\`\`\`
264
- ${textValue(node)}
265
- \`\`\``);
266
- case "a": {
267
- const href = typeof node.props?.href === "string" ? node.props.href : "";
268
- const text = renderChildren(node, ctx) || href;
269
- return href ? linkMarkdown(text, routeMarkdownPathForHref(href, ctx.locale, ctx.path)) : text;
270
- }
271
- case "ul":
272
- return renderList(node, ctx);
273
- case "ol":
274
- return renderList(node, ctx, true);
275
- case "li":
276
- return renderChildren(node, ctx);
277
- case "hr":
278
- return "---\n\n";
279
- case "br":
280
- return "\n";
281
- case "img": {
282
- const src = typeof node.props?.src === "string" ? node.props.src : "";
283
- const alt = typeof node.props?.alt === "string" ? node.props.alt : "";
284
- return src ? imageMarkdown(alt, src) : escapeMarkdownLinkLabel(alt);
285
- }
286
- case "table":
287
- return renderTable(node, ctx);
288
- case "thead":
289
- case "tbody":
290
- case "tr":
291
- case "th":
292
- case "td":
293
- return renderChildren(node, ctx);
294
- default:
295
- return renderUnknownComponent(node, ctx);
296
- }
297
- };
298
- const renderMarkdownRoot = (body, context) => {
299
- if (!body?.children?.length) return "";
300
- const ctx = {
301
- ...context,
302
- prop: () => "",
303
- props: (node) => node ? isRecord(node.props) ? node.props : {} : {},
304
- cleanProps: (node) => cleanPropsObject(node?.props),
305
- children: (node) => node ? renderChildren(node, ctx) : "",
306
- renderChildren: (node) => renderChildren(node, ctx),
307
- renderNode: (node) => renderNode(node, ctx),
308
- blockquote: (value) => blockquoteMarkdown(value),
309
- jsonFence: (value) => jsonFenceMarkdown(value),
310
- link: (label, href) => linkMarkdown(label, href),
311
- omitted: (name, reason) => renderUnknownComponentOmission(name, reason),
312
- xmlComponent: (name, props, children) => xmlComponentMarkdown(name, props, children)
313
- };
314
- return body.children.map((node) => renderNode(node, ctx)).join("").trim();
315
- };
316
41
  const hasH1 = (markdown) => /^#\s+/m.test(markdown);
317
42
  const normalizeDescription = (page) => typeof page.description === "string" && page.description.trim() ? page.description.trim() : "";
318
43
  const renderAgentMarkdown = (page, collection, path, locale, _options) => {
319
44
  const title = typeof page.title === "string" && page.title.trim() ? page.title.trim() : path.split("/").filter(Boolean).pop() || "Index";
320
45
  const description = normalizeDescription(page);
321
- const rendered = renderMarkdownRoot(page.body, { collection, page, path, locale });
46
+ const rendered = renderAgentMarkdownBody(page.body, buildRenderContext(collection, page, path, locale));
322
47
  const parts = [];
323
48
  if (!hasH1(rendered)) parts.push(`# ${escapeMarkdownText(title)}`);
324
49
  if (description && !rendered.includes(description)) parts.push(`> ${description}`);
@@ -326,8 +51,8 @@ const renderAgentMarkdown = (page, collection, path, locale, _options) => {
326
51
  return parts.join("\n\n").trim() + "\n";
327
52
  };
328
53
  const toAgentMarkdown = (collection, page, options) => {
329
- const path = normalizeAgentRoutePath(page.path || page._requestedRoute || page._path);
330
- const locale = page.locale || page._resolvedLocale || page._locale;
54
+ const path = normalizeAgentRoutePath(page.path || page.resolved?.requestedRoute);
55
+ const locale = page.locale || page.resolved?.locale || page.locale;
331
56
  const title = typeof page.title === "string" && page.title.trim() ? page.title.trim() : path.split("/").filter(Boolean).pop() || "Index";
332
57
  const description = normalizeDescription(page);
333
58
  return {
@@ -339,7 +64,7 @@ const toAgentMarkdown = (collection, page, options) => {
339
64
  title,
340
65
  description,
341
66
  markdown: renderAgentMarkdown(page, collection, path, locale, options),
342
- ...page._file ? { sourceFile: page._file } : {},
67
+ ...page.file?.path ? { sourceFile: page.file?.path } : {},
343
68
  canonicalUrl: path,
344
69
  ...typeof page.updated === "string" ? { lastModified: page.updated } : {},
345
70
  metadataFields: options.metadata,
@@ -377,11 +102,11 @@ const publicPathForLocale = (collection, config, rowPath, locale, defaultLocale2
377
102
  });
378
103
  };
379
104
  const publicPathForQueryRow = (collection, config, row, locale) => {
380
- const requested = row.path || row._requestedRoute;
105
+ const requested = row.path || row.resolved?.requestedRoute;
381
106
  if (requested) return normalizeAgentRoutePath(requested);
382
107
  const defaultLocale2 = collectionDefaultLocale(config);
383
- const rowPath = normalizeAgentRoutePath(row._path || "/");
384
- const resolvedLocale = row._resolvedLocale || row._locale;
108
+ const rowPath = normalizeAgentRoutePath(row.path || "/");
109
+ const resolvedLocale = row.resolved?.locale || row.locale;
385
110
  if (locale && resolvedLocale && locale !== resolvedLocale) {
386
111
  const sourceLocalePath = publicPathForLocale(collection, config, rowPath, resolvedLocale, defaultLocale2);
387
112
  return prefixRequestedLocale(sourceLocalePath, locale, defaultLocale2);
@@ -416,15 +141,15 @@ export async function queryMarkdownEnabledContent(event, options = {}) {
416
141
  for (const [collection, config] of markdownEnabledCollectionEntries(options.collections)) {
417
142
  const agentOptions = resolveAgentMarkdownOptions(config);
418
143
  if (!agentOptions) continue;
419
- const rows = normalizeQueryResult(await provider.query(event, {
144
+ const rows = normalizeQueryResult(await provider.query(event, createProviderQuery({
420
145
  collection,
421
- only: ["path", "locale", "localePaths", "_path", "_locale", "_resolvedLocale", "_requestedRoute", "_file", "_draft", "_partial", "_navigation", "title", "description", "updated", "navigation", "robots", "sitemap"],
146
+ only: ["path", "locale", "localePaths", "resolved", "file", "draft", "partial", "navigationFile", "title", "description", "updated", "navigation", "robots", "sitemap"],
422
147
  ...options.limit ? { limit: options.limit } : {},
423
148
  ...options.locale ? { resolveLocale: { locale: options.locale, fallback: true } } : {}
424
- }));
149
+ })));
425
150
  for (const row of rows) {
426
151
  if (!isPublicPage(row, config)) continue;
427
- const locale = options.locale || row._resolvedLocale || row._locale;
152
+ const locale = options.locale || row.resolved?.locale || row.locale;
428
153
  const path = publicPathForQueryRow(collection, config, row, locale);
429
154
  const title = typeof row.title === "string" && row.title.trim() ? row.title.trim() : path.split("/").filter(Boolean).pop() || "Index";
430
155
  const description = normalizeDescription(row);
@@ -436,7 +161,7 @@ export async function queryMarkdownEnabledContent(event, options = {}) {
436
161
  collection,
437
162
  title,
438
163
  description,
439
- ...row._file ? { sourceFile: row._file } : {},
164
+ ...row.file?.path ? { sourceFile: row.file?.path } : {},
440
165
  canonicalUrl: path,
441
166
  ...typeof row.updated === "string" ? { lastModified: row.updated } : {},
442
167
  metadataFields: agentOptions.metadata,
@@ -1,6 +1,6 @@
1
1
  import { getRequestURL } from "h3";
2
2
  import { linkMarkdown, queryMarkdownEnabledContent, resolveContentMarkdownByRoute } from "./agent-markdown.js";
3
- import { agentMarkdownPathForRoute, agentRawPathForRoute, agentRoutePathFromIndexSlug, agentRoutePathFromRawSlug, normalizeAgentRoutePath } from "../agent-paths.js";
3
+ import { agentMarkdownPathForRoute, agentRawPathForRoute, agentRoutePathFromIndexSlug, agentRoutePathFromRawSlug, normalizeAgentRoutePath } from "../../features/agent/agent-paths";
4
4
  import { contentConfig } from "./storage-access.js";
5
5
  const localizedValue = (value, locale, fallback = "") => {
6
6
  if (typeof value === "string") return value;
@@ -1,7 +1,7 @@
1
1
  import { createError, defineEventHandler } from "h3";
2
2
  import { localeFromAgentPath, resolveMarkdownForPublicRoute, routePathFromRawSlug } from "../agent-site.js";
3
3
  import { setAgentMarkdownHeaders } from "../agent-http.js";
4
- import { isUnsafeAgentRoutePath } from "../../agent-paths.js";
4
+ import { isUnsafeAgentRoutePath } from "../../../features/agent/agent-paths";
5
5
  export default defineEventHandler(async (event) => {
6
6
  const routePath = routePathFromRawSlug(event.context.params?.slug);
7
7
  if (isUnsafeAgentRoutePath(routePath)) {
@@ -1,8 +1,8 @@
1
1
  import type { NavItem } from '../../../types/content';
2
2
  declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
3
- contents: unknown[];
4
3
  navigation: NavItem[];
5
4
  generatedAt: number;
5
+ documentCount: number;
6
6
  generateTime: number;
7
7
  }>>;
8
8
  export default _default;
@@ -1,26 +1,65 @@
1
1
  import { defineEventHandler } from "h3";
2
+ import { isRealDocument } from "../../../core/content/document";
3
+ import { assertSnapshotComplete, buildContentSnapshot } from "../../../core/content/snapshot";
4
+ import { chunksFromArray, loadContentVariants } from "../../../storage/contents";
2
5
  import { getContentProvider } from "../providers/index.js";
6
+ import { createProviderNavigationQuery } from "../provider-query.js";
3
7
  import { createContentProviderError } from "../../../public/provider-errors";
4
- import { cacheStorage } from "../storage-access.js";
8
+ import { cacheStorage, contentConfig, getSourceContentIds } from "../storage-access.js";
9
+ const hasRoutePath = (document) => typeof document.path === "string" && document.path.length > 0;
10
+ const describeExcludedSource = (variants) => {
11
+ if (variants.every((variant) => !isRealDocument(variant))) {
12
+ return "unreadable (source missing or failed to parse)";
13
+ }
14
+ return "no route path (parsed, but every variant lacks a path)";
15
+ };
5
16
  export default defineEventHandler(async (event) => {
6
17
  const now = Date.now();
7
- const contents = [];
18
+ const config = contentConfig();
19
+ const sourceIds = await getSourceContentIds(event);
20
+ const documents = [];
21
+ const excluded = /* @__PURE__ */ new Map();
22
+ for (const chunk of chunksFromArray(sourceIds, 10)) {
23
+ const results = await Promise.all(chunk.map(async (id) => [id, await loadContentVariants(event, id)]));
24
+ for (const [id, variants] of results) {
25
+ const routable = variants.filter(isRealDocument).filter(hasRoutePath);
26
+ if (routable.length === 0) {
27
+ excluded.set(id, describeExcludedSource(variants));
28
+ }
29
+ documents.push(...routable);
30
+ }
31
+ }
32
+ if (excluded.size > 0) {
33
+ const details = [...excluded.entries()].slice(0, 20).map(([id, reason]) => `${id}: ${reason}`).join("; ");
34
+ throw new Error(
35
+ `[content] snapshot build failed: ${excluded.size} source document(s) produced no servable content and would silently 404 in production. First ${Math.min(excluded.size, 20)} \u2014 ${details}`
36
+ );
37
+ }
38
+ const snapshot = buildContentSnapshot({
39
+ integrity: config.cacheIntegrity,
40
+ documents,
41
+ sourceIds,
42
+ now
43
+ });
44
+ assertSnapshotComplete(snapshot, sourceIds);
45
+ await cacheStorage(event).setItem("snapshot.json", snapshot);
8
46
  const provider = await getContentProvider(event);
9
47
  if (!provider.navigationQuery) {
10
48
  throw createContentProviderError("unsupported_provider_operation", `${provider.name} does not support navigation queries`, {
11
49
  provider: provider.name
12
50
  });
13
51
  }
14
- const navigation = await provider.navigationQuery(event, {});
52
+ const { query: navQuery, options: navOptions } = createProviderNavigationQuery({});
53
+ const navigation = await provider.navigationQuery(event, navQuery, navOptions);
15
54
  await cacheStorage(event).setItem("_nav.json", navigation);
16
55
  const meta = {
17
56
  generatedAt: now,
57
+ documentCount: snapshot.documentIds.length,
18
58
  generateTime: Date.now() - now
19
59
  };
20
60
  await cacheStorage(event).setItem("_meta.json", meta);
21
61
  return {
22
62
  ...meta,
23
- contents,
24
63
  navigation
25
64
  };
26
65
  });