@lupinum/ginko-content 0.1.5 → 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 +21 -34
  63. package/dist/module.d.mts +135 -803
  64. package/dist/module.json +1 -1
  65. package/dist/module.mjs +143 -51
  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 +9 -2
  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 +79 -105
  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 +17 -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
@@ -0,0 +1,138 @@
1
+ export const isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
2
+ export const getMarkdownProp = (node, name) => {
3
+ const props = isRecord(node.props) ? node.props : {};
4
+ const value = props[name];
5
+ return typeof value === "string" ? value : "";
6
+ };
7
+ export const renderMarkdownChildren = (node, ctx) => ctx.renderChildren(node);
8
+ export const blockquoteMarkdown = (value) => value.trim().split("\n").map((line) => line ? `> ${line}` : ">").join("\n");
9
+ export const escapeMarkdownLinkLabel = (value) => value.replace(/\\/g, "\\\\").replace(/\[/g, "\\[").replace(/\]/g, "\\]");
10
+ const escapeMarkdownLinkHref = (value) => value.replace(/\)/g, "%29").replace(/\s/g, "%20");
11
+ const isSafeMarkdownHref = (href) => {
12
+ if (!href) return false;
13
+ if (href.startsWith("//")) return false;
14
+ if (href.startsWith("/") || href.startsWith("#") || href.startsWith("./") || href.startsWith("../")) return true;
15
+ return /^(https?:|mailto:|tel:)/i.test(href);
16
+ };
17
+ export const linkMarkdown = (label, href) => {
18
+ const resolvedLabel = label || href;
19
+ if (!href || !isSafeMarkdownHref(href)) return escapeMarkdownLinkLabel(resolvedLabel);
20
+ return `[${escapeMarkdownLinkLabel(resolvedLabel)}](${escapeMarkdownLinkHref(href)})`;
21
+ };
22
+ export const imageMarkdown = (alt, src) => {
23
+ if (!src || !isSafeMarkdownHref(src)) return escapeMarkdownLinkLabel(alt || src);
24
+ return `![${escapeMarkdownLinkLabel(alt)}](${escapeMarkdownLinkHref(src)})`;
25
+ };
26
+ export const jsonFenceMarkdown = (value) => `\`\`\`json
27
+ ${JSON.stringify(value, null, 2)}
28
+ \`\`\``;
29
+ const xmlNamePattern = /^[a-z][\w.:-]*$/i;
30
+ const safeXmlName = (name) => xmlNamePattern.test(name) ? name : "component";
31
+ const escapeXmlAttribute = (value) => value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
32
+ const isScalarXmlAttributeValue = (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean";
33
+ const shouldDropAgentProp = (name) => {
34
+ const normalized = name.trim();
35
+ const sensitive = normalized.toLowerCase();
36
+ 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);
37
+ };
38
+ const normalizeAgentPropName = (name) => {
39
+ const normalized = name.trim();
40
+ if (normalized.startsWith(":")) return normalized.slice(1);
41
+ if (normalized.startsWith("v-bind:")) return normalized.slice("v-bind:".length);
42
+ return normalized;
43
+ };
44
+ const cleanAgentPropValue = (value) => {
45
+ if (value === void 0 || value === null || value === "") return void 0;
46
+ if (Array.isArray(value)) {
47
+ const clean = value.map((entry) => cleanAgentPropValue(entry)).filter((entry) => entry !== void 0);
48
+ return clean.length ? clean : void 0;
49
+ }
50
+ if (isRecord(value)) {
51
+ const clean = cleanPropsObject(value);
52
+ return Object.keys(clean).length ? clean : void 0;
53
+ }
54
+ return value;
55
+ };
56
+ export const cleanPropsObject = (props) => {
57
+ if (!isRecord(props)) return {};
58
+ const clean = {};
59
+ for (const [name, value] of Object.entries(props)) {
60
+ const normalizedName = normalizeAgentPropName(name);
61
+ const cleanedValue = cleanAgentPropValue(value);
62
+ if (shouldDropAgentProp(normalizedName) || cleanedValue === void 0) continue;
63
+ if (!(normalizedName in clean) || normalizedName === name.trim()) {
64
+ clean[normalizedName] = cleanedValue;
65
+ }
66
+ }
67
+ return clean;
68
+ };
69
+ export const xmlComponentMarkdown = (name, props = {}, children = "") => {
70
+ const tagName = safeXmlName(name);
71
+ const cleanProps = cleanPropsObject(props);
72
+ const attrs = [];
73
+ const complexProps = {};
74
+ for (const [key, value] of Object.entries(cleanProps)) {
75
+ if (!xmlNamePattern.test(key)) {
76
+ complexProps[key] = value;
77
+ continue;
78
+ }
79
+ if (isScalarXmlAttributeValue(value)) {
80
+ attrs.push(`${key}="${escapeXmlAttribute(String(value))}"`);
81
+ continue;
82
+ }
83
+ complexProps[key] = value;
84
+ }
85
+ const attrText = attrs.length ? ` ${attrs.join(" ")}` : "";
86
+ const bodyParts = [
87
+ Object.keys(complexProps).length ? jsonFenceMarkdown(complexProps) : "",
88
+ children.trim()
89
+ ].filter(Boolean);
90
+ if (!bodyParts.length) return `<${tagName}${attrText} />`;
91
+ return `<${tagName}${attrText}>
92
+ ${bodyParts.join("\n\n")}
93
+ </${tagName}>`;
94
+ };
95
+ export const defineAgentMarkdownComponent = (component) => component;
96
+ export const createAgentMarkdownRegistry = () => {
97
+ const serializers = /* @__PURE__ */ new Map();
98
+ const register = (name, serializer, options = {}) => {
99
+ const existing = serializers.get(name);
100
+ if (existing === serializer && !options.override) return;
101
+ if (existing && !options.override) {
102
+ throw new Error(
103
+ `Agent Markdown serializer "${name}" is already registered. Use { override: true } only when replacing an existing serializer intentionally.`
104
+ );
105
+ }
106
+ serializers.set(name, serializer);
107
+ };
108
+ const registerComponent = (name, component, options = {}) => register(name, component.render, options);
109
+ return {
110
+ register,
111
+ registerMany: (entries, options) => {
112
+ for (const [name, serializer] of Object.entries(entries)) register(name, serializer, options);
113
+ },
114
+ registerComponent,
115
+ registerComponents: (entries, options) => {
116
+ for (const [name, component] of Object.entries(entries)) registerComponent(name, component, options);
117
+ },
118
+ clear: () => serializers.clear(),
119
+ get: (name) => serializers.get(name)
120
+ };
121
+ };
122
+ export const resolveAgentMarkdownOptions = (collection) => {
123
+ if (!collection || collection.type === "data") return null;
124
+ const value = collection.agent?.markdown;
125
+ if (value === true) {
126
+ return {
127
+ includeInIndex: true,
128
+ includeInFull: true,
129
+ metadata: []
130
+ };
131
+ }
132
+ if (!value || !isRecord(value)) return null;
133
+ return {
134
+ includeInIndex: value.includeInIndex !== false,
135
+ includeInFull: value.includeInFull !== false,
136
+ metadata: Array.isArray(value.metadata) ? value.metadata.filter((field) => typeof field === "string" && field.length > 0) : []
137
+ };
138
+ };
@@ -0,0 +1 @@
1
+ export * from './walker.js'
@@ -0,0 +1,10 @@
1
+ import type { MarkdownRoot } from '../../types/content';
2
+ import type { AgentMarkdownRenderContext } from './agent-markdown';
3
+ /**
4
+ * The pure agent-markdown walker: serializes a parsed markdown body to agent
5
+ * markdown as a function of `(body, context)` alone. Every config- and
6
+ * registry-derived input arrives on {@link AgentMarkdownRenderContext}; the
7
+ * walker reads no module-global state, so identical inputs always produce
8
+ * identical output.
9
+ */
10
+ export declare const renderAgentMarkdownBody: (body: MarkdownRoot | null | undefined, context: AgentMarkdownRenderContext) => string;
@@ -0,0 +1,174 @@
1
+ import { kebabCase, pascalCase } from "scule";
2
+ import {
3
+ blockquoteMarkdown,
4
+ cleanPropsObject,
5
+ escapeMarkdownLinkLabel,
6
+ getMarkdownProp,
7
+ imageMarkdown,
8
+ isRecord,
9
+ jsonFenceMarkdown,
10
+ linkMarkdown,
11
+ xmlComponentMarkdown
12
+ } from "./agent-markdown.js";
13
+ import { agentRawPathForRoute, normalizeAgentRoutePath } from "./agent-paths.js";
14
+ const textValue = (node) => {
15
+ if (node.type === "text") return node.value || "";
16
+ return (node.children || []).map((child) => textValue(child)).join("");
17
+ };
18
+ const renderChildren = (node, ctx) => (node.children || []).map((child) => renderNode(child, ctx)).join("").trim();
19
+ const block = (value) => value.trim() ? `${value.trim()}
20
+
21
+ ` : "";
22
+ const renderList = (node, ctx, ordered = false) => block((node.children || []).map((child, index) => {
23
+ const body = renderChildren(child, ctx).replace(/\n+/g, "\n ").trim();
24
+ return `${ordered ? `${index + 1}.` : "-"} ${body}`;
25
+ }).join("\n"));
26
+ const renderTable = (node, ctx) => {
27
+ const rows = (node.children || []).flatMap(
28
+ (section) => section.tag === "thead" || section.tag === "tbody" ? section.children || [] : [section]
29
+ ).filter((row) => row.tag === "tr");
30
+ if (!rows.length) return "";
31
+ const cells = rows.map(
32
+ (row) => (row.children || []).filter((cell) => cell.tag === "th" || cell.tag === "td").map((cell) => renderChildren(cell, ctx).replace(/\|/g, "\\|").trim())
33
+ );
34
+ const width = Math.max(...cells.map((row) => row.length));
35
+ const normalized = cells.map((row) => [...row, ...Array.from({ length: width - row.length }, () => "")]);
36
+ const [head = [], ...bodyRows] = normalized;
37
+ return block([
38
+ `| ${head.join(" | ")} |`,
39
+ `| ${head.map(() => "---").join(" | ")} |`,
40
+ ...bodyRows.map((row) => `| ${row.join(" | ")} |`)
41
+ ].join("\n"));
42
+ };
43
+ const renderUnknownComponentOmission = (name, reason) => `> Component omitted: \`${name}\`.
44
+ > ${reason || "This page contains an interactive or site-specific block that has no agent markdown serializer yet."}`;
45
+ const renderUnknownComponent = (node, ctx) => {
46
+ const tag = node.tag || "component";
47
+ const props = cleanPropsObject(node.props);
48
+ const children = renderChildren(node, ctx);
49
+ if (children || Object.keys(props).length) {
50
+ return block(xmlComponentMarkdown(tag, props, children));
51
+ }
52
+ return block(renderUnknownComponentOmission(tag));
53
+ };
54
+ const serializerForTag = (tag, ctx) => {
55
+ const markdownTags = ctx.tagAliases || {};
56
+ const candidates = new Set([
57
+ tag,
58
+ pascalCase(tag),
59
+ kebabCase(tag),
60
+ markdownTags[tag],
61
+ markdownTags[pascalCase(tag)],
62
+ markdownTags[kebabCase(tag)]
63
+ ].filter((value) => Boolean(value)));
64
+ for (const candidate of candidates) {
65
+ const serializer = ctx.registry.get(candidate);
66
+ if (serializer) return serializer;
67
+ }
68
+ };
69
+ const isExternalHref = (href) => /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith("//");
70
+ const prefixLocalizedHref = (path, locale, ctx) => {
71
+ const normalized = normalizeAgentRoutePath(path);
72
+ if (!locale || locale === ctx.defaultLocale) return normalized;
73
+ if (ctx.locales.some((candidate) => normalized === `/${candidate}` || normalized.startsWith(`/${candidate}/`))) return normalized;
74
+ return normalized === "/" ? `/${locale}` : `/${locale}${normalized}`;
75
+ };
76
+ const routeMarkdownPathForHref = (href, ctx) => {
77
+ const currentPath = ctx.path || "/";
78
+ const hash = href.match(/#.*$/)?.[0] || "";
79
+ const withoutHash = href.replace(/#.*$/, "");
80
+ if (!withoutHash) return href;
81
+ if (isExternalHref(withoutHash)) return href;
82
+ if (withoutHash.endsWith(".md")) return href;
83
+ const target = withoutHash.startsWith("/") ? prefixLocalizedHref(withoutHash, ctx.locale, ctx) : new URL(withoutHash, `https://agent.local${normalizeAgentRoutePath(currentPath)}`).pathname;
84
+ return `${agentRawPathForRoute(target)}${hash}`;
85
+ };
86
+ const renderNode = (node, ctx) => {
87
+ if (node.type === "text") return node.value || "";
88
+ const tag = node.tag || "";
89
+ const serializer = tag ? serializerForTag(tag, ctx) : void 0;
90
+ if (serializer) {
91
+ const nodeCtx = {
92
+ ...ctx,
93
+ prop: (name) => getMarkdownProp(node, name),
94
+ props: (target) => isRecord((target || node).props) ? (target || node).props : {},
95
+ cleanProps: (target) => cleanPropsObject((target || node).props),
96
+ children: (target) => renderChildren(target || node, nodeCtx)
97
+ };
98
+ const rendered = serializer(node, nodeCtx);
99
+ if (typeof rendered === "string") return block(rendered);
100
+ }
101
+ if (!tag) return renderChildren(node, ctx);
102
+ if (/^h[1-6]$/.test(tag)) {
103
+ const depth = Number(tag.slice(1));
104
+ return block(`${"#".repeat(Math.max(1, Math.min(6, depth)))} ${renderChildren(node, ctx)}`);
105
+ }
106
+ switch (tag) {
107
+ case "p":
108
+ return block(renderChildren(node, ctx));
109
+ case "blockquote":
110
+ return block(renderChildren(node, ctx).split("\n").map((line) => `> ${line}`).join("\n"));
111
+ case "strong":
112
+ case "b":
113
+ return `**${renderChildren(node, ctx)}**`;
114
+ case "em":
115
+ case "i":
116
+ return `_${renderChildren(node, ctx)}_`;
117
+ case "span":
118
+ return renderChildren(node, ctx);
119
+ case "code":
120
+ return `\`${node.value || textValue(node)}\``;
121
+ case "pre":
122
+ return block(`\`\`\`
123
+ ${textValue(node)}
124
+ \`\`\``);
125
+ case "a": {
126
+ const href = typeof node.props?.href === "string" ? node.props.href : "";
127
+ const text = renderChildren(node, ctx) || href;
128
+ return href ? linkMarkdown(text, routeMarkdownPathForHref(href, ctx)) : text;
129
+ }
130
+ case "ul":
131
+ return renderList(node, ctx);
132
+ case "ol":
133
+ return renderList(node, ctx, true);
134
+ case "li":
135
+ return renderChildren(node, ctx);
136
+ case "hr":
137
+ return "---\n\n";
138
+ case "br":
139
+ return "\n";
140
+ case "img": {
141
+ const src = typeof node.props?.src === "string" ? node.props.src : "";
142
+ const alt = typeof node.props?.alt === "string" ? node.props.alt : "";
143
+ return src ? imageMarkdown(alt, src) : escapeMarkdownLinkLabel(alt);
144
+ }
145
+ case "table":
146
+ return renderTable(node, ctx);
147
+ case "thead":
148
+ case "tbody":
149
+ case "tr":
150
+ case "th":
151
+ case "td":
152
+ return renderChildren(node, ctx);
153
+ default:
154
+ return renderUnknownComponent(node, ctx);
155
+ }
156
+ };
157
+ export const renderAgentMarkdownBody = (body, context) => {
158
+ if (!body?.children?.length) return "";
159
+ const ctx = {
160
+ ...context,
161
+ prop: () => "",
162
+ props: (node) => node ? isRecord(node.props) ? node.props : {} : {},
163
+ cleanProps: (node) => cleanPropsObject(node?.props),
164
+ children: (node) => node ? renderChildren(node, ctx) : "",
165
+ renderChildren: (node) => renderChildren(node, ctx),
166
+ renderNode: (node) => renderNode(node, ctx),
167
+ blockquote: (value) => blockquoteMarkdown(value),
168
+ jsonFence: (value) => jsonFenceMarkdown(value),
169
+ link: (label, href) => linkMarkdown(label, href),
170
+ omitted: (name, reason) => renderUnknownComponentOmission(name, reason),
171
+ xmlComponent: (name, props, children) => xmlComponentMarkdown(name, props, children)
172
+ };
173
+ return body.children.map((node) => renderNode(node, ctx)).join("").trim();
174
+ };
@@ -6,7 +6,7 @@ export interface CollectionResolveRuntime extends RuntimeContentI18nInput {
6
6
  localeFallback?: Record<string, string[]>;
7
7
  translatedSlugs?: boolean;
8
8
  }
9
- export declare const resolveCollectionNavigationData: (_collection: string, _runtime: CollectionResolveRuntime, options: {
9
+ export declare const resolveCollectionNavigationData: (collection: string, _runtime: CollectionResolveRuntime, options: {
10
10
  fields?: string[];
11
11
  locale?: string;
12
12
  canonical?: boolean;
@@ -31,7 +31,7 @@ export declare const resolveCollectionSearchSectionsData: (collection: string, r
31
31
  canonical?: boolean;
32
32
  activeLocale?: string;
33
33
  }) & {
34
- loadPages: (extraFields: string[]) => Promise<Array<Pick<ParsedContent, "_path" | "title" | "description" | "body"> & Record<string, unknown>>>;
34
+ loadPages: (extraFields: string[]) => Promise<Array<Pick<ParsedContent, "path" | "title" | "description" | "body"> & Record<string, unknown>>>;
35
35
  }) => Promise<{
36
36
  id: string;
37
37
  title: string;
@@ -2,7 +2,8 @@ import { createCollectionSurroundings } from "../navigation/tree.js";
2
2
  import { createSearchSections } from "../search/sections.js";
3
3
  import { normalizeContentPath, resolveCollectionI18n, resolveRouteContent } from "../localization/path.js";
4
4
  import { createRouteMeta, localizePageResult, localizeSearchSections } from "../localization/results.js";
5
- export const resolveCollectionNavigationData = async (_collection, _runtime, options) => {
5
+ import { sortLocalesCanonically } from "../../core/content/locale";
6
+ export const resolveCollectionNavigationData = async (collection, _runtime, options) => {
6
7
  return await options.loadNavigation();
7
8
  };
8
9
  export const resolveCollectionItemSurroundingsData = async (collection, path, runtime, options) => {
@@ -37,14 +38,15 @@ export const resolveCollectionPageData = async (collection, routeOrPath, runtime
37
38
  return null;
38
39
  }
39
40
  if (options.canonical) {
40
- const canonicalPath = normalizeContentPath(page._path || "/");
41
- const resolvedLocale = page._resolvedLocale || page._locale || resolved.locale || defaultLocale || "";
42
- const requestedLocale = page._requestedLocale || resolved.locale;
43
- const fallback = Boolean(page._fallback || requestedLocale && resolvedLocale && requestedLocale !== resolvedLocale);
41
+ const resolution = page.resolved;
42
+ const unprefixedPath = normalizeContentPath(page.path || "/");
43
+ const resolvedLocale = resolution?.locale || page.locale || resolved.locale || defaultLocale || "";
44
+ const requestedLocale = resolution?.requestedLocale || resolved.locale;
45
+ const fallback = Boolean(resolution?.fallback || requestedLocale && resolvedLocale && requestedLocale !== resolvedLocale);
44
46
  return {
45
47
  ...page,
46
- path: canonicalPath,
47
- canonicalPath,
48
+ path: unprefixedPath,
49
+ unprefixedPath,
48
50
  locale: resolved.locale || resolvedLocale,
49
51
  defaultLocale: defaultLocale || "",
50
52
  variants: [],
@@ -54,14 +56,15 @@ export const resolveCollectionPageData = async (collection, routeOrPath, runtime
54
56
  ...requestedLocale ? { requestedLocale } : {},
55
57
  fallback,
56
58
  ...fallback ? { fallbackLocale: resolvedLocale } : {},
57
- path: canonicalPath,
58
- ...page._requestedPath ? { requestedPath: page._requestedPath } : {},
59
- ...page._requestedRoute ? { requestedRoute: page._requestedRoute } : {},
60
- ...page._requestedRef ? { requestedRef: page._requestedRef } : {},
61
- availableLocales: page._availableLocales || Object.keys(page._variantPaths || {})
59
+ path: unprefixedPath,
60
+ ...resolution?.requestedPath ? { requestedPath: resolution.requestedPath } : {},
61
+ ...resolution?.requestedRoute ? { requestedRoute: resolution.requestedRoute } : {},
62
+ ...resolution?.requestedRef ? { requestedRef: resolution.requestedRef } : {},
63
+ availableLocales: resolution?.availableLocales || sortLocalesCanonically(Object.keys(resolution?.variantPaths || {}), { defaultLocale, locales }),
64
+ ...resolution?.resolvedRefs ? { resolvedRefs: resolution.resolvedRefs } : {}
62
65
  },
63
- stem: canonicalPath.replace(/^\/+/, "") || "index",
64
- extension: page._extension
66
+ stem: unprefixedPath.replace(/^\/+/, "") || "index",
67
+ extension: page.file?.extension
65
68
  };
66
69
  }
67
70
  return localizePageResult(page, resolved.locale, defaultLocale, locales);
@@ -71,6 +74,6 @@ export const resolveCollectionRouteMetaData = async (collection, runtime, option
71
74
  if (!page) {
72
75
  return null;
73
76
  }
74
- const { defaultLocale } = resolveCollectionI18n(collection, runtime);
75
- return createRouteMeta(page, page.locale, defaultLocale);
77
+ const { defaultLocale, locales } = resolveCollectionI18n(collection, runtime);
78
+ return createRouteMeta(page, page.locale, defaultLocale, locales);
76
79
  };
@@ -1,5 +1,5 @@
1
1
  import { localizePath } from "./path.js";
2
- const LOCALIZED_PROP_KEYS = /* @__PURE__ */ new Set(["href", "to", "path", "_path"]);
2
+ const LOCALIZED_PROP_KEYS = /* @__PURE__ */ new Set(["href", "to", "path", "path"]);
3
3
  const LOCALIZED_BOUND_PREFIXES = [":", "v-bind:"];
4
4
  const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
5
5
  const getBoundPropName = (key) => {
@@ -2,9 +2,9 @@ import type { ContentNavigationItem, ParsedContent } from '../../types/content';
2
2
  import type { ContentLocaleEntry, ContentPageResult, ContentRouteMeta, LocalePathEntry } from '../../types/query';
3
3
  import type { SearchSection } from '../search/sections';
4
4
  import { type RouteMounts } from './path';
5
- export declare const createLocaleVariants: (variants: Record<string, string> | ContentLocaleEntry[] | undefined, defaultLocale?: string, routeMounts?: RouteMounts) => {
5
+ export declare const createLocaleVariants: (variants: Record<string, string> | ContentLocaleEntry[] | undefined, defaultLocale?: string, locales?: string[], routeMounts?: RouteMounts) => {
6
6
  locale: string;
7
- canonicalPath: string;
7
+ unprefixedPath: string;
8
8
  path: string;
9
9
  }[];
10
10
  /**
@@ -39,4 +39,4 @@ export declare const localizeSearchSections: (sections?: SearchSection[], locale
39
39
  level: number;
40
40
  content: string;
41
41
  }[];
42
- export declare const createRouteMeta: <T extends ParsedContent & Record<string, unknown>>(page: T, locale?: string, defaultLocale?: string, routeMounts?: RouteMounts) => ContentRouteMeta;
42
+ export declare const createRouteMeta: <T extends ParsedContent & Record<string, unknown>>(page: T, locale?: string, defaultLocale?: string, locales?: string[], routeMounts?: RouteMounts) => ContentRouteMeta;
@@ -1,7 +1,8 @@
1
+ import { sortLocalesCanonically } from "../../core/content/locale";
1
2
  import { localizeLinkProps } from "./links.js";
2
3
  import { getContentStem, localizePath, normalizeContentPath, projectContentPathToLocale } from "./path.js";
3
4
  const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
4
- export const createLocaleVariants = (variants, defaultLocale, routeMounts) => {
5
+ export const createLocaleVariants = (variants, defaultLocale, locales = [], routeMounts) => {
5
6
  if (!variants) {
6
7
  return [];
7
8
  }
@@ -10,9 +11,11 @@ export const createLocaleVariants = (variants, defaultLocale, routeMounts) => {
10
11
  locale,
11
12
  path
12
13
  }));
13
- return entries.filter((entry) => entry.path).map((entry) => ({
14
+ const localeOrder = sortLocalesCanonically(entries.map((entry) => entry.locale), { defaultLocale, locales });
15
+ const rank = new Map(localeOrder.map((locale, index) => [locale, index]));
16
+ return entries.filter((entry) => entry.path).sort((left, right) => (rank.get(left.locale) ?? Number.MAX_SAFE_INTEGER) - (rank.get(right.locale) ?? Number.MAX_SAFE_INTEGER)).map((entry) => ({
14
17
  locale: entry.locale,
15
- canonicalPath: normalizeContentPath(entry.path || "/"),
18
+ unprefixedPath: normalizeContentPath(entry.path || "/"),
16
19
  path: projectContentPathToLocale(entry.path || "/", entry.locale, defaultLocale, routeMounts)
17
20
  }));
18
21
  };
@@ -40,17 +43,18 @@ export const decorateLocalePathsWithFallbacks = (localePaths, configuredLocales,
40
43
  return result;
41
44
  };
42
45
  export const localizePageResult = (page, locale, defaultLocale, locales = [], routeMounts) => {
43
- const canonicalPath = normalizeContentPath(page._path || "/");
44
- const variants = createLocaleVariants(page._variantPaths, defaultLocale, routeMounts);
45
- const path = projectContentPathToLocale(canonicalPath, locale || page._resolvedLocale || page._locale, defaultLocale, routeMounts);
46
- const resolvedLocale = page._resolvedLocale || page._locale || locale || defaultLocale || "";
47
- const requestedLocale = page._requestedLocale || locale;
48
- const fallback = Boolean(page._fallback || requestedLocale && resolvedLocale && requestedLocale !== resolvedLocale);
46
+ const resolution = page.resolved;
47
+ const unprefixedPath = normalizeContentPath(page.path || "/");
48
+ const variants = createLocaleVariants(resolution?.variantPaths, defaultLocale, locales, routeMounts);
49
+ const path = projectContentPathToLocale(unprefixedPath, locale || resolution?.locale || page.locale, defaultLocale, routeMounts);
50
+ const resolvedLocale = resolution?.locale || page.locale || locale || defaultLocale || "";
51
+ const requestedLocale = resolution?.requestedLocale || locale;
52
+ const fallback = Boolean(resolution?.fallback || requestedLocale && resolvedLocale && requestedLocale !== resolvedLocale);
49
53
  const result = {
50
54
  ...page,
51
55
  path,
52
- canonicalPath,
53
- locale: locale || page._resolvedLocale || page._locale || defaultLocale || "",
56
+ unprefixedPath,
57
+ locale: locale || resolution?.locale || page.locale || defaultLocale || "",
54
58
  defaultLocale: defaultLocale || "",
55
59
  variants,
56
60
  localePaths: createLocalePaths(variants),
@@ -60,13 +64,14 @@ export const localizePageResult = (page, locale, defaultLocale, locales = [], ro
60
64
  fallback,
61
65
  ...fallback ? { fallbackLocale: resolvedLocale } : {},
62
66
  path,
63
- ...page._requestedPath ? { requestedPath: page._requestedPath } : {},
64
- ...page._requestedRoute ? { requestedRoute: page._requestedRoute } : {},
65
- ...page._requestedRef ? { requestedRef: page._requestedRef } : {},
66
- availableLocales: page._availableLocales || Object.keys(page._variantPaths || {})
67
+ ...resolution?.requestedPath ? { requestedPath: resolution.requestedPath } : {},
68
+ ...resolution?.requestedRoute ? { requestedRoute: resolution.requestedRoute } : {},
69
+ ...resolution?.requestedRef ? { requestedRef: resolution.requestedRef } : {},
70
+ availableLocales: resolution?.availableLocales || sortLocalesCanonically(Object.keys(resolution?.variantPaths || {}), { defaultLocale, locales }),
71
+ ...resolution?.resolvedRefs ? { resolvedRefs: resolution.resolvedRefs } : {}
67
72
  },
68
- stem: getContentStem(canonicalPath, page._file),
69
- extension: page._extension
73
+ stem: getContentStem(unprefixedPath, page.file?.path),
74
+ extension: page.file?.extension
70
75
  };
71
76
  const links = result.links;
72
77
  if (Array.isArray(links)) {
@@ -83,22 +88,21 @@ export const localizePageResult = (page, locale, defaultLocale, locales = [], ro
83
88
  return result;
84
89
  };
85
90
  const localizeNavigationItem = (item, locale, defaultLocale, locales = [], routeMounts) => {
86
- const rawPath = typeof item._path === "string" ? item._path : typeof item.path === "string" ? item.path : void 0;
91
+ const rawPath = typeof item.unprefixedPath === "string" ? item.unprefixedPath : typeof item.path === "string" ? item.path : void 0;
87
92
  if (!rawPath) {
88
93
  return {
89
94
  ...item,
90
95
  children: item.children?.map((child) => localizeNavigationItem(child, locale, defaultLocale, locales, routeMounts))
91
96
  };
92
97
  }
93
- const canonicalPath = normalizeContentPath(rawPath);
94
- const localizedPath = projectContentPathToLocale(canonicalPath, locale, defaultLocale, routeMounts);
95
- const file = typeof item._file === "string" ? item._file : void 0;
98
+ const unprefixedPath = normalizeContentPath(rawPath);
99
+ const localizedPath = projectContentPathToLocale(unprefixedPath, locale, defaultLocale, routeMounts);
100
+ const file = item.file?.path;
96
101
  return {
97
102
  ...item,
98
- _path: canonicalPath,
99
103
  path: localizedPath,
100
- canonicalPath,
101
- stem: item.stem || getContentStem(canonicalPath, file),
104
+ unprefixedPath,
105
+ stem: item.stem || getContentStem(unprefixedPath, file),
102
106
  children: item.children?.map((child) => localizeNavigationItem(child, locale, defaultLocale, locales, routeMounts))
103
107
  };
104
108
  };
@@ -107,31 +111,31 @@ export const localizeSurround = (items = [], locale, defaultLocale, _locales = [
107
111
  if (!item) {
108
112
  return item;
109
113
  }
110
- const canonicalPath = normalizeContentPath(String(item._path || item.path || "/"));
114
+ const unprefixedPath = normalizeContentPath(String(item.unprefixedPath || item.path || "/"));
111
115
  return {
112
116
  ...item,
113
- _path: canonicalPath,
114
- path: projectContentPathToLocale(canonicalPath, locale, defaultLocale, routeMounts),
115
- canonicalPath,
116
- stem: item.stem || getContentStem(canonicalPath, typeof item._file === "string" ? item._file : void 0)
117
+ path: projectContentPathToLocale(unprefixedPath, locale, defaultLocale, routeMounts),
118
+ unprefixedPath,
119
+ stem: item.stem || getContentStem(unprefixedPath, item.file?.path)
117
120
  };
118
121
  });
119
122
  export const localizeSearchSections = (sections = [], locale, defaultLocale, locales = []) => sections.map((section) => ({
120
123
  ...section,
121
124
  id: localizePath(section.id, locale, defaultLocale, locales) || section.id
122
125
  }));
123
- export const createRouteMeta = (page, locale, defaultLocale, routeMounts) => {
124
- const canonicalPath = normalizeContentPath(page._path || "/");
125
- const resolvedLocale = page._resolvedLocale || page._locale || locale || defaultLocale || "";
126
- const requestedLocale = page._requestedLocale || locale;
127
- const fallback = Boolean(page._fallback || requestedLocale && resolvedLocale && requestedLocale !== resolvedLocale);
128
- const variants = createLocaleVariants(page._variantPaths, defaultLocale, routeMounts);
129
- const path = projectContentPathToLocale(canonicalPath, locale || resolvedLocale, defaultLocale, routeMounts);
126
+ export const createRouteMeta = (page, locale, defaultLocale, locales = [], routeMounts) => {
127
+ const resolution = page.resolved;
128
+ const unprefixedPath = normalizeContentPath(page.path || "/");
129
+ const resolvedLocale = resolution?.locale || page.locale || locale || defaultLocale || "";
130
+ const requestedLocale = resolution?.requestedLocale || locale;
131
+ const fallback = Boolean(resolution?.fallback || requestedLocale && resolvedLocale && requestedLocale !== resolvedLocale);
132
+ const variants = resolution?.variantPaths ? createLocaleVariants(resolution.variantPaths, defaultLocale, locales, routeMounts) : Array.isArray(page.variants) ? page.variants : [];
133
+ const path = projectContentPathToLocale(unprefixedPath, locale || resolvedLocale, defaultLocale, routeMounts);
130
134
  return {
131
135
  locale: locale || resolvedLocale,
132
136
  defaultLocale: defaultLocale || "",
133
137
  path,
134
- canonicalPath,
138
+ unprefixedPath,
135
139
  variants,
136
140
  localePaths: createLocalePaths(variants),
137
141
  resolved: {
@@ -140,10 +144,11 @@ export const createRouteMeta = (page, locale, defaultLocale, routeMounts) => {
140
144
  fallback,
141
145
  ...fallback ? { fallbackLocale: resolvedLocale } : {},
142
146
  path,
143
- ...page._requestedPath ? { requestedPath: page._requestedPath } : {},
144
- ...page._requestedRoute ? { requestedRoute: page._requestedRoute } : {},
145
- ...page._requestedRef ? { requestedRef: page._requestedRef } : {},
146
- availableLocales: page._availableLocales || Object.keys(page._variantPaths || {})
147
+ ...resolution?.requestedPath ? { requestedPath: resolution.requestedPath } : {},
148
+ ...resolution?.requestedRoute ? { requestedRoute: resolution.requestedRoute } : {},
149
+ ...resolution?.requestedRef ? { requestedRef: resolution.requestedRef } : {},
150
+ availableLocales: resolution?.availableLocales || sortLocalesCanonically(Object.keys(resolution?.variantPaths || {}), { defaultLocale, locales }),
151
+ ...resolution?.resolvedRefs ? { resolvedRefs: resolution.resolvedRefs } : {}
147
152
  }
148
153
  };
149
154
  };
@@ -1,12 +1,12 @@
1
1
  const TRANSLATED_SLUG_SEGMENT_RE = /^(\d+)\.(.+)$/;
2
2
  const getTranslatedSlugEntries = (document, locales = []) => {
3
- const file = (document._file || "").replace(/^\/+/, "");
3
+ const file = (document.file?.path || "").replace(/^\/+/, "");
4
4
  const parts = file.split("/").filter(Boolean);
5
5
  const localizedParts = parts[0] && locales.includes(parts[0]) ? parts.slice(1) : parts;
6
6
  if (!localizedParts.length) {
7
7
  return [];
8
8
  }
9
- const locale = document._locale || "";
9
+ const locale = document.locale || "";
10
10
  const directories = localizedParts.slice(0, -1);
11
11
  const basename = localizedParts[localizedParts.length - 1] || "";
12
12
  const entries = [];
@@ -15,7 +15,7 @@ const getTranslatedSlugEntries = (document, locales = []) => {
15
15
  const match = directory.match(TRANSLATED_SLUG_SEGMENT_RE);
16
16
  entries.push({
17
17
  locale,
18
- file: document._file || document._id,
18
+ file: document.file?.path || document.id,
19
19
  parentKey,
20
20
  raw: directory,
21
21
  number: match?.[1],
@@ -27,7 +27,7 @@ const getTranslatedSlugEntries = (document, locales = []) => {
27
27
  const match = basename.match(TRANSLATED_SLUG_SEGMENT_RE);
28
28
  entries.push({
29
29
  locale,
30
- file: document._file || document._id,
30
+ file: document.file?.path || document.id,
31
31
  parentKey,
32
32
  raw: basename,
33
33
  number: match?.[1],
@@ -49,7 +49,7 @@ export const collectTranslatedSlugValidationIssues = (contents, options) => {
49
49
  if (hasMissingPrefix) {
50
50
  issues.push({
51
51
  level: "warn",
52
- file: document._file || document._id,
52
+ file: document.file?.path || document.id,
53
53
  reason: "translated slug mode expects numeric prefixes for localized route segments"
54
54
  });
55
55
  }