@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.
- package/compatibility.json +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/cms-contract/build.js +15 -20
- package/dist/cms-contract/types.d.ts +12 -7
- package/dist/core/content/document +1 -0
- package/dist/core/content/document.d.ts +16 -0
- package/dist/core/content/document.js +2 -0
- package/dist/core/content/graph.d.ts +3 -1
- package/dist/core/content/graph.js +21 -20
- package/dist/core/content/locale.d.ts +6 -1
- package/dist/core/content/locale.js +17 -6
- package/dist/core/content/path.d.ts +5 -5
- package/dist/core/content/path.js +8 -8
- package/dist/core/content/snapshot +1 -0
- package/dist/core/content/snapshot.d.ts +25 -0
- package/dist/core/content/snapshot.js +99 -0
- package/dist/core/provider-errors.d.ts +1 -1
- package/dist/core/provider-errors.js +1 -0
- package/dist/core/query/builder.js +3 -3
- package/dist/core/query/execute.js +75 -36
- package/dist/core/query/filter.js +2 -2
- package/dist/core/query/lower.js +79 -3
- package/dist/core/query/params.js +7 -7
- package/dist/core/query/plan.d.ts +18 -0
- package/dist/core/query/plan.js +7 -0
- package/dist/core/references/resolve.js +6 -9
- package/dist/features/agent/agent-markdown +1 -0
- package/dist/features/agent/agent-markdown.d.ts +116 -0
- package/dist/features/agent/agent-markdown.js +138 -0
- package/dist/features/agent/walker +1 -0
- package/dist/features/agent/walker.d.ts +10 -0
- package/dist/features/agent/walker.js +174 -0
- package/dist/features/collections/resolve.d.ts +2 -2
- package/dist/features/collections/resolve.js +19 -16
- package/dist/features/localization/links.js +1 -1
- package/dist/features/localization/results.d.ts +3 -3
- package/dist/features/localization/results.js +46 -41
- package/dist/features/localization/translated-slugs.js +5 -5
- package/dist/features/navigation/build.d.ts +2 -2
- package/dist/features/navigation/build.js +23 -26
- package/dist/features/navigation/canonical.d.ts +10 -11
- package/dist/features/navigation/canonical.js +26 -21
- package/dist/features/navigation/resolve.js +4 -4
- package/dist/features/navigation/tree.js +3 -3
- package/dist/{runtime → features}/query/backlinks.js +3 -5
- package/dist/{runtime → features}/query/documents.js +1 -1
- package/dist/{runtime → features}/query/localized-docs.d.ts +1 -1
- package/dist/{runtime → features}/query/localized-docs.js +3 -6
- package/dist/{runtime → features}/query/navigation.d.ts +1 -1
- package/dist/{runtime → features}/query/navigation.js +8 -8
- package/dist/{runtime → features}/query/populate.js +6 -14
- package/dist/{runtime → features}/query/unified.d.ts +4 -4
- package/dist/{runtime → features}/query/unified.js +4 -2
- package/dist/{runtime → features}/query/variants.js +4 -4
- package/dist/features/search/navigation.js +2 -2
- package/dist/features/search/sections.d.ts +1 -1
- package/dist/features/search/sections.js +1 -1
- package/dist/features/sitemap/query.d.ts +5 -5
- package/dist/features/sitemap/query.js +6 -6
- package/dist/integrations/nitro/ingest.js +9 -20
- package/dist/integrations/nitro/storage.d.ts +1 -0
- package/dist/integrations/nitro/storage.js +21 -34
- package/dist/module.d.mts +135 -803
- package/dist/module.json +1 -1
- package/dist/module.mjs +143 -51
- package/dist/parsers/csv.js +3 -3
- package/dist/parsers/index.js +3 -3
- package/dist/parsers/json.js +8 -6
- package/dist/parsers/markdown-plugins.js +9 -5
- package/dist/parsers/markdown.js +7 -6
- package/dist/parsers/path-meta.js +21 -19
- package/dist/parsers/reserved +1 -0
- package/dist/parsers/reserved.d.ts +15 -0
- package/dist/parsers/reserved.js +35 -0
- package/dist/parsers/yaml.js +6 -4
- package/dist/public/agent +1 -0
- package/dist/public/agent.d.ts +17 -0
- package/dist/public/agent.js +34 -0
- package/dist/public/client.d.ts +2 -3
- package/dist/public/client.js +1 -2
- package/dist/public/provider-query +1 -0
- package/dist/public/provider-query.d.ts +58 -0
- package/dist/public/provider-query.js +5 -0
- package/dist/public/provider.d.ts +8 -3
- package/dist/public/provider.js +2 -0
- package/dist/public/server.d.ts +7 -12
- package/dist/public/server.js +5 -36
- package/dist/runtime/app/components/ContentRenderer.d.vue.ts +3 -3
- package/dist/runtime/app/components/ContentRenderer.vue +2 -2
- package/dist/runtime/app/components/ContentRenderer.vue.d.ts +3 -3
- package/dist/runtime/app/components/ContentRendererInline.d.vue.ts +1 -1
- package/dist/runtime/app/components/ContentRendererInline.vue.d.ts +1 -1
- package/dist/runtime/app/components/Prose/ProseImg.d.vue.ts +4 -4
- package/dist/runtime/app/components/Prose/ProseImg.vue.d.ts +4 -4
- package/dist/runtime/app/components/Prose/ProsePre.d.vue.ts +1 -1
- package/dist/runtime/app/components/Prose/ProsePre.vue.d.ts +1 -1
- package/dist/runtime/app/components/internal/ContentRendererMarkdown.d.vue.ts +1 -1
- package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue +4 -4
- package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue.d.ts +1 -1
- package/dist/runtime/app/components/internal/MarkdownRenderer.d.ts +3 -3
- package/dist/runtime/app/composables/preview.d.ts +1 -1
- package/dist/runtime/app/composables/query-api.d.ts +5 -5
- package/dist/runtime/app/composables/query-api.js +5 -3
- package/dist/runtime/app/composables/route.d.ts +1 -1
- package/dist/runtime/app/composables/route.js +4 -4
- package/dist/runtime/app/composables/search.js +1 -1
- package/dist/runtime/app/composables/use-content-document.js +1 -1
- package/dist/runtime/app/composables/use-content-list.js +1 -1
- package/dist/runtime/app/composables/use-content-navigation.js +2 -2
- package/dist/runtime/app/composables/use-content-page.js +4 -4
- package/dist/runtime/app/pages/content.vue +2 -1
- package/dist/runtime/markdown/plugins.js +6 -8
- package/dist/runtime/server/agent-markdown.d.ts +5 -65
- package/dist/runtime/server/agent-markdown.js +40 -315
- package/dist/runtime/server/agent-site.js +9 -2
- package/dist/runtime/server/api/agent-raw.js +1 -1
- package/dist/runtime/server/api/cache.d.ts +1 -1
- package/dist/runtime/server/api/cache.js +43 -4
- package/dist/runtime/server/api/locales.js +3 -3
- package/dist/runtime/server/api/navigation.d.ts +1 -1
- package/dist/runtime/server/api/navigation.js +3 -1
- package/dist/runtime/server/api/query.js +2 -2
- package/dist/runtime/server/api/search-index.d.ts +1 -1
- package/dist/runtime/server/api/sitemap.d.ts +1 -1
- package/dist/runtime/server/cache-adapters.d.ts +18 -0
- package/dist/runtime/server/cache-adapters.js +12 -0
- package/dist/runtime/server/collection-helpers.d.ts +2 -2
- package/dist/runtime/server/collection-helpers.js +15 -11
- package/dist/runtime/server/index.d.ts +6 -4
- package/dist/runtime/server/index.js +10 -3
- package/dist/runtime/server/middleware/agent-link-headers.js +1 -1
- package/dist/runtime/server/middleware/agent-markdown.js +1 -1
- package/dist/runtime/server/navigation-query.d.ts +2 -2
- package/dist/runtime/server/navigation-query.js +52 -7
- package/dist/runtime/server/navigation.d.ts +1 -1
- package/dist/runtime/server/provider-document +1 -0
- package/dist/runtime/server/provider-document.d.ts +59 -0
- package/dist/runtime/server/provider-document.js +48 -0
- package/dist/runtime/server/provider-query-wire +1 -0
- package/dist/runtime/server/provider-query-wire.d.ts +32 -0
- package/dist/runtime/server/provider-query-wire.js +27 -0
- package/dist/runtime/server/provider-query.d.ts +18 -9
- package/dist/runtime/server/provider-query.js +62 -28
- package/dist/runtime/server/provider-result.d.ts +4 -4
- package/dist/runtime/server/providers/filesystem.js +3 -11
- package/dist/runtime/server/providers/index.d.ts +18 -1
- package/dist/runtime/server/providers/index.js +72 -20
- package/dist/runtime/server/query-api.d.ts +5 -5
- package/dist/runtime/server/query-api.js +9 -6
- package/dist/runtime/server/query-executor.d.ts +3 -3
- package/dist/runtime/server/query-executor.js +43 -59
- package/dist/runtime/server/search.d.ts +1 -1
- package/dist/runtime/server/search.js +4 -4
- package/dist/runtime/server/sitemap.js +5 -5
- package/dist/runtime/server/storage-access.d.ts +4 -1
- package/dist/runtime/server/storage-access.js +27 -2
- package/dist/runtime/transformers/component-resolver.d.ts +1 -1
- package/dist/storage/content.d.ts +2 -6
- package/dist/storage/content.js +19 -8
- package/dist/storage/contents.d.ts +9 -1
- package/dist/storage/contents.js +26 -19
- package/dist/storage/driver.d.ts +2 -2
- package/dist/storage/driver.js +2 -1
- package/dist/storage/graph.js +4 -0
- package/dist/storage/manifest.js +3 -1
- package/dist/storage/references.js +9 -5
- package/dist/storage/snapshot-runtime +1 -0
- package/dist/storage/snapshot-runtime.d.ts +11 -0
- package/dist/storage/snapshot-runtime.js +46 -0
- package/dist/storage/validation.d.ts +1 -1
- package/dist/storage/validation.js +79 -105
- package/dist/testing/provider-contract.d.ts +14 -4
- package/dist/testing/provider-contract.js +121 -68
- package/dist/testing/provider-fixture.d.ts +1 -1
- package/dist/testing/provider-fixture.js +124 -120
- package/dist/types/config.d.ts +17 -4
- package/dist/types/content.d.ts +104 -70
- package/dist/types/fields.js +1 -1
- package/dist/types/module.d.ts +1 -1
- package/dist/types/query-parts/public.d.ts +14 -5
- package/dist/types/query-parts/results.d.ts +6 -2
- package/dist/types/query-parts/transport.d.ts +19 -0
- package/dist/types/virtual.d.ts +6 -0
- package/dist/types.d.mts +2 -2
- package/dist/web-types.json +1 -1
- package/package.json +39 -9
- package/dist/runtime/app/plugins/markdown-components +0 -1
- package/dist/runtime/app/plugins/markdown-components.d.ts +0 -2
- package/dist/runtime/app/plugins/markdown-components.js +0 -19
- /package/dist/{runtime → features/agent}/agent-paths +0 -0
- /package/dist/{runtime → features/agent}/agent-paths.d.ts +0 -0
- /package/dist/{runtime → features/agent}/agent-paths.js +0 -0
- /package/dist/{runtime → features}/query/backlinks +0 -0
- /package/dist/{runtime → features}/query/backlinks.d.ts +0 -0
- /package/dist/{runtime → features}/query/context +0 -0
- /package/dist/{runtime → features}/query/context.d.ts +0 -0
- /package/dist/{runtime → features}/query/context.js +0 -0
- /package/dist/{runtime → features}/query/documents +0 -0
- /package/dist/{runtime → features}/query/documents.d.ts +0 -0
- /package/dist/{runtime → features}/query/errors +0 -0
- /package/dist/{runtime → features}/query/errors.d.ts +0 -0
- /package/dist/{runtime → features}/query/errors.js +0 -0
- /package/dist/{runtime → features}/query/handles +0 -0
- /package/dist/{runtime → features}/query/handles.d.ts +0 -0
- /package/dist/{runtime → features}/query/handles.js +0 -0
- /package/dist/{runtime → features}/query/locale-options +0 -0
- /package/dist/{runtime → features}/query/locale-options.d.ts +0 -0
- /package/dist/{runtime → features}/query/locale-options.js +0 -0
- /package/dist/{runtime → features}/query/localized-docs +0 -0
- /package/dist/{runtime → features}/query/navigation +0 -0
- /package/dist/{runtime → features}/query/pagination +0 -0
- /package/dist/{runtime → features}/query/pagination.d.ts +0 -0
- /package/dist/{runtime → features}/query/pagination.js +0 -0
- /package/dist/{runtime → features}/query/populate +0 -0
- /package/dist/{runtime → features}/query/populate.d.ts +0 -0
- /package/dist/{runtime → features}/query/public-limits +0 -0
- /package/dist/{runtime → features}/query/public-limits.d.ts +0 -0
- /package/dist/{runtime → features}/query/public-limits.js +0 -0
- /package/dist/{runtime → features}/query/resolve +0 -0
- /package/dist/{runtime → features}/query/resolve.d.ts +0 -0
- /package/dist/{runtime → features}/query/resolve.js +0 -0
- /package/dist/{runtime → features}/query/responses +0 -0
- /package/dist/{runtime → features}/query/responses.d.ts +0 -0
- /package/dist/{runtime → features}/query/responses.js +0 -0
- /package/dist/{runtime → features}/query/routes +0 -0
- /package/dist/{runtime → features}/query/routes.d.ts +0 -0
- /package/dist/{runtime → features}/query/routes.js +0 -0
- /package/dist/{runtime → features}/query/unified +0 -0
- /package/dist/{runtime → features}/query/variants +0 -0
- /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 `})`;
|
|
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, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
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: (
|
|
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, "
|
|
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
|
-
|
|
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
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
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:
|
|
47
|
-
|
|
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:
|
|
58
|
-
...
|
|
59
|
-
...
|
|
60
|
-
...
|
|
61
|
-
availableLocales:
|
|
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:
|
|
64
|
-
extension: page.
|
|
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", "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
const
|
|
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
|
-
|
|
53
|
-
locale: locale ||
|
|
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
|
-
...
|
|
64
|
-
...
|
|
65
|
-
...
|
|
66
|
-
availableLocales:
|
|
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(
|
|
69
|
-
extension: page.
|
|
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.
|
|
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
|
|
94
|
-
const localizedPath = projectContentPathToLocale(
|
|
95
|
-
const file =
|
|
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
|
-
|
|
101
|
-
stem: item.stem || getContentStem(
|
|
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
|
|
114
|
+
const unprefixedPath = normalizeContentPath(String(item.unprefixedPath || item.path || "/"));
|
|
111
115
|
return {
|
|
112
116
|
...item,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
|
125
|
-
const
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
const
|
|
129
|
-
const
|
|
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
|
-
|
|
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
|
-
...
|
|
144
|
-
...
|
|
145
|
-
...
|
|
146
|
-
availableLocales:
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
52
|
+
file: document.file?.path || document.id,
|
|
53
53
|
reason: "translated slug mode expects numeric prefixes for localized route segments"
|
|
54
54
|
});
|
|
55
55
|
}
|