@lupinum/ginko-content 0.1.6 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/compatibility.json +1 -1
  2. package/dist/cli.mjs +2 -2
  3. package/dist/cms-contract/build.js +15 -20
  4. package/dist/cms-contract/types.d.ts +12 -7
  5. package/dist/core/content/document +1 -0
  6. package/dist/core/content/document.d.ts +16 -0
  7. package/dist/core/content/document.js +2 -0
  8. package/dist/core/content/graph.d.ts +3 -1
  9. package/dist/core/content/graph.js +21 -20
  10. package/dist/core/content/locale.d.ts +6 -1
  11. package/dist/core/content/locale.js +17 -6
  12. package/dist/core/content/path.d.ts +5 -5
  13. package/dist/core/content/path.js +8 -8
  14. package/dist/core/content/snapshot +1 -0
  15. package/dist/core/content/snapshot.d.ts +25 -0
  16. package/dist/core/content/snapshot.js +99 -0
  17. package/dist/core/provider-errors.d.ts +1 -1
  18. package/dist/core/provider-errors.js +1 -0
  19. package/dist/core/query/builder.js +3 -3
  20. package/dist/core/query/execute.js +75 -36
  21. package/dist/core/query/filter.js +2 -2
  22. package/dist/core/query/lower.js +79 -3
  23. package/dist/core/query/params.js +7 -7
  24. package/dist/core/query/plan.d.ts +18 -0
  25. package/dist/core/query/plan.js +7 -0
  26. package/dist/core/references/resolve.js +6 -9
  27. package/dist/features/agent/agent-markdown +1 -0
  28. package/dist/features/agent/agent-markdown.d.ts +116 -0
  29. package/dist/features/agent/agent-markdown.js +138 -0
  30. package/dist/features/agent/walker +1 -0
  31. package/dist/features/agent/walker.d.ts +10 -0
  32. package/dist/features/agent/walker.js +174 -0
  33. package/dist/features/collections/resolve.d.ts +2 -2
  34. package/dist/features/collections/resolve.js +19 -16
  35. package/dist/features/localization/links.js +1 -1
  36. package/dist/features/localization/results.d.ts +3 -3
  37. package/dist/features/localization/results.js +46 -41
  38. package/dist/features/localization/translated-slugs.js +5 -5
  39. package/dist/features/navigation/build.d.ts +2 -2
  40. package/dist/features/navigation/build.js +23 -26
  41. package/dist/features/navigation/canonical.d.ts +10 -11
  42. package/dist/features/navigation/canonical.js +26 -21
  43. package/dist/features/navigation/resolve.js +4 -4
  44. package/dist/features/navigation/tree.js +3 -3
  45. package/dist/{runtime → features}/query/backlinks.js +3 -5
  46. package/dist/{runtime → features}/query/documents.js +1 -1
  47. package/dist/{runtime → features}/query/localized-docs.d.ts +1 -1
  48. package/dist/{runtime → features}/query/localized-docs.js +3 -6
  49. package/dist/{runtime → features}/query/navigation.d.ts +1 -1
  50. package/dist/{runtime → features}/query/navigation.js +8 -8
  51. package/dist/{runtime → features}/query/populate.js +6 -14
  52. package/dist/{runtime → features}/query/unified.d.ts +4 -4
  53. package/dist/{runtime → features}/query/unified.js +4 -2
  54. package/dist/{runtime → features}/query/variants.js +4 -4
  55. package/dist/features/search/navigation.js +2 -2
  56. package/dist/features/search/sections.d.ts +1 -1
  57. package/dist/features/search/sections.js +1 -1
  58. package/dist/features/sitemap/query.d.ts +5 -5
  59. package/dist/features/sitemap/query.js +6 -6
  60. package/dist/integrations/nitro/ingest.js +9 -20
  61. package/dist/integrations/nitro/storage.d.ts +1 -0
  62. package/dist/integrations/nitro/storage.js +22 -8
  63. package/dist/module.d.mts +135 -812
  64. package/dist/module.json +1 -1
  65. package/dist/module.mjs +75 -28
  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 +10 -3
  85. package/dist/public/provider.js +3 -0
  86. package/dist/public/server.d.ts +7 -12
  87. package/dist/public/server.js +5 -36
  88. package/dist/runtime/app/components/ContentRenderer.d.vue.ts +3 -3
  89. package/dist/runtime/app/components/ContentRenderer.vue +2 -2
  90. package/dist/runtime/app/components/ContentRenderer.vue.d.ts +3 -3
  91. package/dist/runtime/app/components/ContentRendererInline.d.vue.ts +1 -1
  92. package/dist/runtime/app/components/ContentRendererInline.vue.d.ts +1 -1
  93. package/dist/runtime/app/components/Prose/ProseImg.d.vue.ts +4 -4
  94. package/dist/runtime/app/components/Prose/ProseImg.vue.d.ts +4 -4
  95. package/dist/runtime/app/components/Prose/ProsePre.d.vue.ts +1 -1
  96. package/dist/runtime/app/components/Prose/ProsePre.vue.d.ts +1 -1
  97. package/dist/runtime/app/components/internal/ContentRendererMarkdown.d.vue.ts +1 -1
  98. package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue +4 -4
  99. package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue.d.ts +1 -1
  100. package/dist/runtime/app/components/internal/MarkdownRenderer.d.ts +3 -3
  101. package/dist/runtime/app/composables/preview.d.ts +1 -1
  102. package/dist/runtime/app/composables/query-api.d.ts +5 -5
  103. package/dist/runtime/app/composables/query-api.js +5 -3
  104. package/dist/runtime/app/composables/route.d.ts +1 -1
  105. package/dist/runtime/app/composables/route.js +4 -4
  106. package/dist/runtime/app/composables/search.js +1 -1
  107. package/dist/runtime/app/composables/use-content-document.js +1 -1
  108. package/dist/runtime/app/composables/use-content-list.js +1 -1
  109. package/dist/runtime/app/composables/use-content-navigation.js +2 -2
  110. package/dist/runtime/app/composables/use-content-page.js +4 -4
  111. package/dist/runtime/app/pages/content.vue +2 -1
  112. package/dist/runtime/markdown/plugins.js +6 -8
  113. package/dist/runtime/server/agent-markdown.d.ts +5 -65
  114. package/dist/runtime/server/agent-markdown.js +40 -315
  115. package/dist/runtime/server/agent-site.js +1 -1
  116. package/dist/runtime/server/api/agent-raw.js +1 -1
  117. package/dist/runtime/server/api/cache.d.ts +1 -1
  118. package/dist/runtime/server/api/cache.js +43 -4
  119. package/dist/runtime/server/api/locales.js +3 -3
  120. package/dist/runtime/server/api/navigation.d.ts +1 -1
  121. package/dist/runtime/server/api/navigation.js +3 -1
  122. package/dist/runtime/server/api/query.js +2 -2
  123. package/dist/runtime/server/api/search-index.d.ts +1 -1
  124. package/dist/runtime/server/api/sitemap.d.ts +1 -1
  125. package/dist/runtime/server/cache-adapters.d.ts +18 -0
  126. package/dist/runtime/server/cache-adapters.js +12 -0
  127. package/dist/runtime/server/collection-helpers.d.ts +2 -2
  128. package/dist/runtime/server/collection-helpers.js +15 -11
  129. package/dist/runtime/server/index.d.ts +6 -4
  130. package/dist/runtime/server/index.js +10 -3
  131. package/dist/runtime/server/middleware/agent-link-headers.js +1 -1
  132. package/dist/runtime/server/middleware/agent-markdown.js +1 -1
  133. package/dist/runtime/server/navigation-query.d.ts +2 -2
  134. package/dist/runtime/server/navigation-query.js +52 -7
  135. package/dist/runtime/server/navigation.d.ts +1 -1
  136. package/dist/runtime/server/provider-document +1 -0
  137. package/dist/runtime/server/provider-document.d.ts +59 -0
  138. package/dist/runtime/server/provider-document.js +48 -0
  139. package/dist/runtime/server/provider-query-wire +1 -0
  140. package/dist/runtime/server/provider-query-wire.d.ts +32 -0
  141. package/dist/runtime/server/provider-query-wire.js +27 -0
  142. package/dist/runtime/server/provider-query.d.ts +18 -9
  143. package/dist/runtime/server/provider-query.js +62 -28
  144. package/dist/runtime/server/provider-result.d.ts +4 -4
  145. package/dist/runtime/server/providers/filesystem.js +3 -11
  146. package/dist/runtime/server/providers/index.d.ts +18 -1
  147. package/dist/runtime/server/providers/index.js +72 -20
  148. package/dist/runtime/server/query-api.d.ts +5 -5
  149. package/dist/runtime/server/query-api.js +9 -6
  150. package/dist/runtime/server/query-executor.d.ts +3 -3
  151. package/dist/runtime/server/query-executor.js +43 -59
  152. package/dist/runtime/server/search.d.ts +1 -1
  153. package/dist/runtime/server/search.js +4 -4
  154. package/dist/runtime/server/sitemap.js +5 -5
  155. package/dist/runtime/server/storage-access.d.ts +4 -1
  156. package/dist/runtime/server/storage-access.js +27 -2
  157. package/dist/runtime/transformers/component-resolver.d.ts +1 -1
  158. package/dist/storage/content.d.ts +2 -6
  159. package/dist/storage/content.js +19 -8
  160. package/dist/storage/contents.d.ts +9 -1
  161. package/dist/storage/contents.js +26 -19
  162. package/dist/storage/driver.d.ts +2 -2
  163. package/dist/storage/driver.js +2 -1
  164. package/dist/storage/graph.js +4 -0
  165. package/dist/storage/manifest.js +3 -1
  166. package/dist/storage/references.js +9 -5
  167. package/dist/storage/snapshot-runtime +1 -0
  168. package/dist/storage/snapshot-runtime.d.ts +11 -0
  169. package/dist/storage/snapshot-runtime.js +46 -0
  170. package/dist/storage/validation.d.ts +1 -1
  171. package/dist/storage/validation.js +47 -102
  172. package/dist/testing/provider-contract.d.ts +31 -4
  173. package/dist/testing/provider-contract.js +241 -81
  174. package/dist/testing/provider-fixture.d.ts +1 -1
  175. package/dist/testing/provider-fixture.js +124 -120
  176. package/dist/types/config.d.ts +8 -4
  177. package/dist/types/content.d.ts +104 -70
  178. package/dist/types/fields.js +1 -1
  179. package/dist/types/module.d.ts +1 -1
  180. package/dist/types/query-parts/public.d.ts +14 -5
  181. package/dist/types/query-parts/results.d.ts +6 -2
  182. package/dist/types/query-parts/transport.d.ts +19 -0
  183. package/dist/types/virtual.d.ts +6 -0
  184. package/dist/types.d.mts +2 -2
  185. package/dist/web-types.json +1 -1
  186. package/package.json +39 -9
  187. package/dist/runtime/app/plugins/markdown-components +0 -1
  188. package/dist/runtime/app/plugins/markdown-components.d.ts +0 -2
  189. package/dist/runtime/app/plugins/markdown-components.js +0 -19
  190. /package/dist/{runtime → features/agent}/agent-paths +0 -0
  191. /package/dist/{runtime → features/agent}/agent-paths.d.ts +0 -0
  192. /package/dist/{runtime → features/agent}/agent-paths.js +0 -0
  193. /package/dist/{runtime → features}/query/backlinks +0 -0
  194. /package/dist/{runtime → features}/query/backlinks.d.ts +0 -0
  195. /package/dist/{runtime → features}/query/context +0 -0
  196. /package/dist/{runtime → features}/query/context.d.ts +0 -0
  197. /package/dist/{runtime → features}/query/context.js +0 -0
  198. /package/dist/{runtime → features}/query/documents +0 -0
  199. /package/dist/{runtime → features}/query/documents.d.ts +0 -0
  200. /package/dist/{runtime → features}/query/errors +0 -0
  201. /package/dist/{runtime → features}/query/errors.d.ts +0 -0
  202. /package/dist/{runtime → features}/query/errors.js +0 -0
  203. /package/dist/{runtime → features}/query/handles +0 -0
  204. /package/dist/{runtime → features}/query/handles.d.ts +0 -0
  205. /package/dist/{runtime → features}/query/handles.js +0 -0
  206. /package/dist/{runtime → features}/query/locale-options +0 -0
  207. /package/dist/{runtime → features}/query/locale-options.d.ts +0 -0
  208. /package/dist/{runtime → features}/query/locale-options.js +0 -0
  209. /package/dist/{runtime → features}/query/localized-docs +0 -0
  210. /package/dist/{runtime → features}/query/navigation +0 -0
  211. /package/dist/{runtime → features}/query/pagination +0 -0
  212. /package/dist/{runtime → features}/query/pagination.d.ts +0 -0
  213. /package/dist/{runtime → features}/query/pagination.js +0 -0
  214. /package/dist/{runtime → features}/query/populate +0 -0
  215. /package/dist/{runtime → features}/query/populate.d.ts +0 -0
  216. /package/dist/{runtime → features}/query/public-limits +0 -0
  217. /package/dist/{runtime → features}/query/public-limits.d.ts +0 -0
  218. /package/dist/{runtime → features}/query/public-limits.js +0 -0
  219. /package/dist/{runtime → features}/query/resolve +0 -0
  220. /package/dist/{runtime → features}/query/resolve.d.ts +0 -0
  221. /package/dist/{runtime → features}/query/resolve.js +0 -0
  222. /package/dist/{runtime → features}/query/responses +0 -0
  223. /package/dist/{runtime → features}/query/responses.d.ts +0 -0
  224. /package/dist/{runtime → features}/query/responses.js +0 -0
  225. /package/dist/{runtime → features}/query/routes +0 -0
  226. /package/dist/{runtime → features}/query/routes.d.ts +0 -0
  227. /package/dist/{runtime → features}/query/routes.js +0 -0
  228. /package/dist/{runtime → features}/query/unified +0 -0
  229. /package/dist/{runtime → features}/query/variants +0 -0
  230. /package/dist/{runtime → features}/query/variants.d.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Build the navigation tree from a flat list of content metadata.
3
3
  *
4
- * The input is a flat list of content rows with `title`, `_path`, `_file`, and
4
+ * The input is a flat list of content rows with `title`, `path`, `file`, and
5
5
  * optional extra fields; the output is a `NavItem[]` tree where parent folders
6
6
  * are synthesized from path segments and `/.navigation.yml` config entries
7
7
  * can override titles and metadata per directory.
@@ -14,7 +14,7 @@
14
14
  * - **`.navigation.yml`** — `configs['/guide']` can set `navigation: false`
15
15
  * on a directory to hide the entire subtree from navigation; or
16
16
  * override `title`/other fields.
17
- * - **Natural sort** — siblings sort by `_file` (filename without the
17
+ * - **Natural sort** — siblings sort by `file.path` (filename without the
18
18
  * extension) via `Intl.Collator({ numeric: true })`, so `10-foo` comes
19
19
  * after `2-foo`, not between `1-foo` and `20-foo`.
20
20
  * - **Two-pass shaping** — we build a mutable canonical tree, then project it
@@ -10,19 +10,18 @@ const pick = (keys) => (obj) => {
10
10
  };
11
11
  const isObject = (value) => Object.prototype.toString.call(value) === "[object Object]";
12
12
  const parentCanonicalKey = (content, depth) => {
13
- const canonicalKey = content._canonicalKey;
13
+ const canonicalKey = content.canonicalKey;
14
14
  if (typeof canonicalKey !== "string" || !canonicalKey) {
15
15
  return void 0;
16
16
  }
17
17
  return canonicalKey.split("/").slice(0, depth + 1).join("/") || void 0;
18
18
  };
19
+ const sortBasename = (item) => {
20
+ const path = item.file?.path;
21
+ return typeof path === "string" ? path.split(".").slice(0, -1).join(".") : "";
22
+ };
19
23
  const sortCanonicalTree = (items) => {
20
- items.forEach((item) => {
21
- if (item._file) {
22
- item._file = item._file.split(".").slice(0, -1).join(".");
23
- }
24
- });
25
- const sorted = items.sort((left, right) => collator.compare(left._file || "", right._file || ""));
24
+ const sorted = items.sort((left, right) => collator.compare(sortBasename(left), sortBasename(right)));
26
25
  for (const item of sorted) {
27
26
  if (item.children?.length) {
28
27
  sortCanonicalTree(item.children);
@@ -40,26 +39,25 @@ export const buildCanonicalNavigation = (contents, configs, fields = []) => {
40
39
  ...navigationFields
41
40
  };
42
41
  };
43
- const navigation = contents.sort((left, right) => left._path.localeCompare(right._path)).reduce((nav, content) => {
44
- const parts = content._path.substring(1).split("/");
45
- const idParts = content._id.split(":").slice(1);
42
+ const navigation = contents.sort((left, right) => left.path.localeCompare(right.path)).reduce((nav, content) => {
43
+ const parts = content.path.substring(1).split("/");
44
+ const idParts = content.id.split(":").slice(1);
46
45
  const isIndex = Boolean(idParts[idParts.length - 1]?.match(/([1-9][0-9]*\.)?index.md/g));
47
46
  const navItem = {
48
47
  title: content.title,
49
- _path: content._path,
50
- path: content._path,
51
- _file: content._file,
52
- _id: content._id,
53
- _canonicalKey: content._canonicalKey,
54
- _locale: content._locale,
55
- _navigationKind: "page",
56
- _navigationPath: content._path,
48
+ path: content.path,
49
+ file: content.file,
50
+ id: content.id,
51
+ canonicalKey: content.canonicalKey,
52
+ locale: content.locale,
53
+ navigationKind: "page",
54
+ navigationPath: content.path,
57
55
  children: [],
58
56
  ...pickNavigationFields(content),
59
- ...content._draft ? { _draft: true } : {}
57
+ ...content.draft ? { draft: true } : {}
60
58
  };
61
59
  if (isIndex) {
62
- const dirConfig = navItem._path ? configs[navItem._path] : void 0;
60
+ const dirConfig = navItem.path ? configs[navItem.path] : void 0;
63
61
  if (typeof dirConfig?.navigation !== "undefined" && !dirConfig.navigation) {
64
62
  return nav;
65
63
  }
@@ -82,14 +80,13 @@ export const buildCanonicalNavigation = (contents, configs, fields = []) => {
82
80
  const canonicalKey = parentCanonicalKey(content, index);
83
81
  parent = {
84
82
  title: generateTitle(part),
85
- _path: currentPathPart,
86
83
  path: currentPathPart,
87
- _file: content._file,
88
- _navigationKind: "folder",
89
- _navigationPath: currentPathPart,
84
+ file: content.file,
85
+ navigationKind: "folder",
86
+ navigationPath: currentPathPart,
90
87
  page: false,
91
- ...canonicalKey ? { _canonicalKey: canonicalKey } : {},
92
- ...content._locale ? { _locale: content._locale } : {},
88
+ ...canonicalKey ? { canonicalKey } : {},
89
+ ...content.locale ? { locale: content.locale } : {},
93
90
  children: [],
94
91
  ...config && pickNavigationFields(config)
95
92
  };
@@ -1,20 +1,19 @@
1
- import type { ContentNavigationItem, NavItem } from '../../types/content';
1
+ import type { ContentFileMeta, ContentNavigationItem, NavItem } from '../../types/content';
2
2
  import { type RouteMounts } from '../localization/path';
3
3
  export type NavigationNodeKind = 'page' | 'folder';
4
4
  export interface CanonicalNavigationItem {
5
5
  title: string;
6
6
  path?: string;
7
- _path?: string;
8
7
  stem?: string;
9
8
  page?: false;
10
- _id?: string;
11
- _canonicalKey?: string;
12
- _locale?: string;
13
- _fallback?: boolean;
14
- _draft?: boolean;
15
- _file?: string;
16
- _navigationKind?: NavigationNodeKind;
17
- _navigationPath?: string;
9
+ id?: string;
10
+ canonicalKey?: string;
11
+ locale?: string;
12
+ fallback?: boolean;
13
+ draft?: boolean;
14
+ file?: ContentFileMeta;
15
+ navigationKind?: NavigationNodeKind;
16
+ navigationPath?: string;
18
17
  _collectionRoot?: string;
19
18
  children?: CanonicalNavigationItem[];
20
19
  [key: string]: unknown;
@@ -26,7 +25,7 @@ export interface ProjectNavigationOptions {
26
25
  collection?: string;
27
26
  canonical?: boolean;
28
27
  }
29
- export declare const getNavigationIdentity: (node: Pick<CanonicalNavigationItem, "_canonicalKey" | "_path" | "_id">) => string | undefined;
28
+ export declare const getNavigationIdentity: (node: Pick<CanonicalNavigationItem, "canonicalKey">) => string | undefined;
30
29
  export declare const mergeCanonicalNavigation: (primary?: CanonicalNavigationItem[], fallback?: CanonicalNavigationItem[]) => CanonicalNavigationItem[];
31
30
  export declare const markCollectionNavigationRoot: (navigation?: CanonicalNavigationItem[], collection?: string, options?: Pick<ProjectNavigationOptions, "routeMounts">) => CanonicalNavigationItem[];
32
31
  export declare const scopeNavigationTree: (navigation?: CanonicalNavigationItem[], collection?: string) => CanonicalNavigationItem[];
@@ -1,14 +1,14 @@
1
1
  import { getContentStem, normalizeContentPath, projectContentPathToLocale } from "../localization/path.js";
2
2
  const isString = (value) => typeof value === "string" && value.length > 0;
3
3
  export const getNavigationIdentity = (node) => {
4
- if (isString(node._canonicalKey)) {
5
- return node._canonicalKey;
4
+ if (isString(node.canonicalKey)) {
5
+ return node.canonicalKey;
6
6
  }
7
7
  return void 0;
8
8
  };
9
9
  const cloneFallbackNode = (node) => ({
10
10
  ...node,
11
- _fallback: true,
11
+ fallback: true,
12
12
  children: node.children?.map(cloneFallbackNode)
13
13
  });
14
14
  export const mergeCanonicalNavigation = (primary = [], fallback = []) => {
@@ -55,13 +55,13 @@ const normalizeRoutePath = (path) => {
55
55
  return normalizeContentPath(path);
56
56
  };
57
57
  const isFolderNode = (item) => {
58
- if (item._navigationKind === "folder") {
58
+ if (item.navigationKind === "folder") {
59
59
  return true;
60
60
  }
61
- if (item._navigationKind === "page") {
61
+ if (item.navigationKind === "page") {
62
62
  return false;
63
63
  }
64
- return Boolean(item.children?.length && !item._id && !item._path && !item.path);
64
+ return Boolean(item.children?.length && !item.id && !item.path);
65
65
  };
66
66
  const matchesCollectionRootConfig = (collection, root, options) => {
67
67
  if (!root.children?.length) {
@@ -71,7 +71,7 @@ const matchesCollectionRootConfig = (collection, root, options) => {
71
71
  if (identity === collection || identity === `/${collection}`) {
72
72
  return true;
73
73
  }
74
- const rootPath = normalizeRoutePath(root._path || root._navigationPath || root.path);
74
+ const rootPath = normalizeRoutePath(root.navigationPath || root.path);
75
75
  if (rootPath === "/" || rootPath === `/${collection}`) {
76
76
  return true;
77
77
  }
@@ -102,16 +102,22 @@ export const scopeNavigationTree = (navigation = [], collection) => {
102
102
  };
103
103
  const publicFields = (item) => {
104
104
  const {
105
- children: _children,
106
- path: _path,
107
- _path: _canonicalPath,
108
- stem: _stem,
109
- _file,
110
- _navigationKind,
111
- _navigationPath,
105
+ children,
106
+ path,
107
+ stem,
108
+ file,
109
+ navigationKind,
110
+ navigationPath,
112
111
  _collectionRoot,
113
112
  ...fields
114
113
  } = item;
114
+ void children;
115
+ void path;
116
+ void stem;
117
+ void file;
118
+ void navigationKind;
119
+ void navigationPath;
120
+ void _collectionRoot;
115
121
  return fields;
116
122
  };
117
123
  const projectNavigationItem = (item, options) => {
@@ -119,7 +125,7 @@ const projectNavigationItem = (item, options) => {
119
125
  const hasChildren = Boolean(children?.length);
120
126
  const base = {
121
127
  ...publicFields(item),
122
- _fallback: item._fallback === true
128
+ fallback: item.fallback === true
123
129
  };
124
130
  if (isFolderNode(item)) {
125
131
  return {
@@ -127,20 +133,19 @@ const projectNavigationItem = (item, options) => {
127
133
  ...hasChildren ? { children } : {}
128
134
  };
129
135
  }
130
- const rawPath = item._path || item._navigationPath || item.path;
136
+ const rawPath = item.navigationPath || item.path;
131
137
  if (!rawPath) {
132
138
  return {
133
139
  ...base,
134
140
  ...hasChildren ? { children } : {}
135
141
  };
136
142
  }
137
- const canonicalPath = normalizeContentPath(rawPath);
143
+ const unprefixedPath = normalizeContentPath(rawPath);
138
144
  return {
139
145
  ...base,
140
- _path: canonicalPath,
141
- path: options.canonical ? canonicalPath : projectContentPathToLocale(canonicalPath, options.locale || item._locale, options.defaultLocale, options.routeMounts),
142
- canonicalPath,
143
- stem: item.stem || getContentStem(canonicalPath, item._file),
146
+ path: options.canonical ? unprefixedPath : projectContentPathToLocale(unprefixedPath, options.locale || item.locale, options.defaultLocale, options.routeMounts),
147
+ unprefixedPath,
148
+ stem: item.stem || getContentStem(unprefixedPath, item.file?.path),
144
149
  ...hasChildren ? { children } : {}
145
150
  };
146
151
  };
@@ -4,7 +4,7 @@ export const getNavigationItemPath = (item) => {
4
4
  if (!item || item.page === false) {
5
5
  return void 0;
6
6
  }
7
- return stringValue(item.path) || stringValue(item._path);
7
+ return stringValue(item.path) || stringValue(item.path);
8
8
  };
9
9
  export const resolveNavigationItem = (item) => {
10
10
  const path = getNavigationItemPath(item);
@@ -15,16 +15,16 @@ const fieldMatches = (item, field, value) => {
15
15
  if (!candidate) {
16
16
  return false;
17
17
  }
18
- if (field === "path" || field === "_path" || field === "canonicalPath") {
18
+ if (field === "path" || field === "unprefixedPath") {
19
19
  return normalizePath(candidate) === normalizePath(value);
20
20
  }
21
21
  return candidate === value;
22
22
  };
23
23
  export const matchesNavigationItem = (item, match) => {
24
24
  if (typeof match === "string") {
25
- return fieldMatches(item, "path", match) || fieldMatches(item, "_path", match) || fieldMatches(item, "canonicalPath", match) || fieldMatches(item, "stem", match) || fieldMatches(item, "title", match);
25
+ return fieldMatches(item, "path", match) || fieldMatches(item, "unprefixedPath", match) || fieldMatches(item, "stem", match) || fieldMatches(item, "title", match);
26
26
  }
27
- if (match.path && !(fieldMatches(item, "path", match.path) || fieldMatches(item, "_path", match.path) || fieldMatches(item, "canonicalPath", match.path))) {
27
+ if (match.path && !(fieldMatches(item, "path", match.path) || fieldMatches(item, "unprefixedPath", match.path))) {
28
28
  return false;
29
29
  }
30
30
  if (match.stem && !fieldMatches(item, "stem", match.stem)) {
@@ -1,10 +1,10 @@
1
1
  export function flattenCollectionNavigation(navigation = []) {
2
2
  return navigation.flatMap((item) => {
3
3
  const children = item.children ? flattenCollectionNavigation(item.children) : [];
4
- if (!item._path && !item.path) {
4
+ if (!item.unprefixedPath && !item.path) {
5
5
  return children;
6
6
  }
7
- if (item.page === false || children.length && children.find((child) => child._path === item._path)) {
7
+ if (item.page === false || children.length && children.find((child) => child.unprefixedPath === item.unprefixedPath)) {
8
8
  return children;
9
9
  }
10
10
  return [{ ...item, children: void 0 }, ...children];
@@ -16,7 +16,7 @@ export function createCollectionSurroundings(navigation = [], path, options = {}
16
16
  const items = flattenCollectionNavigation(navigation);
17
17
  const normalizedPath = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
18
18
  const index = items.findIndex((item) => {
19
- const itemPath = typeof item.path === "string" ? item.path : item._path;
19
+ const itemPath = typeof item.path === "string" ? item.path : typeof item.unprefixedPath === "string" ? item.unprefixedPath : void 0;
20
20
  if (!itemPath) {
21
21
  return false;
22
22
  }
@@ -28,11 +28,9 @@ const inferBacklinkFields = (source, targetCollection, runtime) => {
28
28
  const targetReferenceCandidates = (doc) => {
29
29
  const values = [
30
30
  doc.ref,
31
- doc.id,
32
- doc._canonicalKey,
33
- doc._path,
34
- doc._path ? doc.path : void 0,
35
- doc._path ? doc.canonicalPath : void 0
31
+ doc.canonicalKey,
32
+ doc.canonicalKey ? doc.path : void 0,
33
+ doc.canonicalKey ? doc.unprefixedPath : void 0
36
34
  ].filter((value) => typeof value === "string" && value.length > 0).flatMap((value) => [value, normalizeReferenceValue(value)]).filter(Boolean);
37
35
  return Array.from(new Set(values));
38
36
  };
@@ -21,7 +21,7 @@ const explainResolution = (collection, requestedBy, normalizedBy, requestedLocal
21
21
  found: Boolean(doc),
22
22
  collection,
23
23
  ...doc?.path ? { path: doc.path } : {},
24
- ...doc?.canonicalPath ? { canonicalPath: doc.canonicalPath } : {},
24
+ ...doc?.unprefixedPath ? { unprefixedPath: doc.unprefixedPath } : {},
25
25
  ...doc?.ref ? { ref: doc.ref } : {},
26
26
  ...resolvedLocale ? { locale: resolvedLocale } : {}
27
27
  },
@@ -4,7 +4,7 @@ import type { RuntimeContentConfig } from './context';
4
4
  /**
5
5
  * Decorate a raw parsed document with route metadata and locale paths.
6
6
  *
7
- * `localizePageResult` already attaches `path`, `canonicalPath`, `locale`,
7
+ * `localizePageResult` already attaches `path`, `unprefixedPath`, `locale`,
8
8
  * `defaultLocale`, `variants`, and `localePaths`. This helper additionally
9
9
  * fills non-translated locales with fallback paths so app switchers can render
10
10
  * all configured languages without another query.
@@ -20,14 +20,11 @@ export const decorateLocalizedDocument = (doc, collection, runtime, requestedLoc
20
20
  const { locales, defaultLocale, routeMounts, hasLocaleConfig } = collectionLocaleConfig(collection, runtime);
21
21
  const page = hasLocaleConfig ? doc : {
22
22
  ...doc,
23
- _locale: "",
24
- _resolvedLocale: void 0,
25
- _requestedLocale: void 0,
26
- _variantPaths: void 0,
27
- _availableLocales: []
23
+ locale: "",
24
+ resolved: { availableLocales: [] }
28
25
  };
29
26
  const result = localizePageResult(page, hasLocaleConfig ? requestedLocale : void 0, defaultLocale, locales, routeMounts);
30
- const fallbackLocale = doc._resolvedLocale || requestedLocale || defaultLocale;
27
+ const fallbackLocale = doc.resolved?.locale || requestedLocale || defaultLocale;
31
28
  result.localePaths = decorateLocalePathsWithFallbacks(result.localePaths, locales, fallbackLocale, defaultLocale, routeMounts);
32
29
  return result;
33
30
  };
@@ -4,7 +4,7 @@ import type { ContentTreeItem, LocalizedContentDocument, NeighborsOptions, Neigh
4
4
  import type { ContentQueryContext } from './context';
5
5
  export declare const navigationSelectFields: (fields?: ReadonlyArray<string> | undefined) => string[];
6
6
  type OneResolver = <H extends ContentCollectionHandle | string>(context: ContentQueryContext, handle: H, options: OneOptions<H>) => Promise<LocalizedContentDocument<ParsedContent> | null>;
7
- type TreeResolver = <H extends ContentCollectionHandle | string, Fields extends ReadonlyArray<string> | undefined = undefined>(context: ContentQueryContext, handle: H, options?: Omit<TreeOptions<H>, 'fields'> & {
7
+ type TreeResolver = <H extends ContentCollectionHandle | string, Fields extends ReadonlyArray<string> | undefined = undefined>(context: ContentQueryContext, handle: H, options: Omit<TreeOptions<H>, 'fields'> & {
8
8
  fields?: Fields;
9
9
  }) => Promise<unknown[]>;
10
10
  export declare function resolveTree<H extends ContentCollectionHandle | string, Fields extends ReadonlyArray<string> | undefined = undefined>(context: ContentQueryContext, handle: H, options?: Omit<TreeOptions<H>, 'fields'> & {
@@ -3,12 +3,12 @@ import { ensureCollectionName } from "./handles.js";
3
3
  import { isCollectionRouteRoot, isNavigationRootPath } from "./localized-docs.js";
4
4
  import { resolveFallback } from "./locale-options.js";
5
5
  const NAVIGATION_INTERNAL_FIELDS = [
6
- "_id",
7
- "_path",
8
- "_file",
9
- "_canonicalKey",
10
- "_locale",
11
- "_draft",
6
+ "id",
7
+ "path",
8
+ "file",
9
+ "canonicalKey",
10
+ "locale",
11
+ "draft",
12
12
  "navigation",
13
13
  "title"
14
14
  ];
@@ -50,8 +50,8 @@ export async function resolveNeighbors(context, one, tree, handle, options) {
50
50
  const walk = (nodes) => {
51
51
  for (const node of nodes) {
52
52
  const n = node;
53
- if (n.path || n._path) {
54
- flat.push({ path: n.path || n._path || "", item: node });
53
+ if (n.path) {
54
+ flat.push({ path: n.path || "", item: node });
55
55
  }
56
56
  if (Array.isArray(n.children)) walk(n.children);
57
57
  }
@@ -1,20 +1,12 @@
1
1
  import { collectTopLevelReferenceFieldsByTarget } from "../../core/references/schema";
2
2
  import { ensureCollectionName } from "./handles.js";
3
3
  const LOCALIZED_DOC_INTERNAL_FIELDS = [
4
- "_id",
5
- "_path",
6
- "_file",
7
- "_canonicalKey",
8
- "_locale",
9
- "_resolvedLocale",
10
- "_requestedLocale",
11
- "_fallback",
12
- "_availableLocales",
13
- "_variantPaths",
14
- "_requestedPath",
15
- "_requestedRoute",
16
- "_requestedRef",
17
- "_extension"
4
+ "id",
5
+ "path",
6
+ "file",
7
+ "canonicalKey",
8
+ "locale",
9
+ "resolved"
18
10
  ];
19
11
  const wildcardReferenceTarget = "*";
20
12
  const isRecord = (value) => {
@@ -16,7 +16,7 @@
16
16
  */
17
17
  import type { ParsedContent } from '../../types/content';
18
18
  import type { ContentCollectionHandle } from '../../types/config';
19
- import type { BacklinkSource, BacklinksOptions, BacklinksResult, ContentTreeItem, DocumentFromHandle, ManyOptions, LocalizedDoc, NeighborsOptions, NeighborsResult, OneOptions, PopulateSpec, PopulateFromOptions, PopulatedDocument, PaginationOptions, PaginationResult, ResolveOneOptions, ResolveOneResult, TreeOptions, ContentVariant, VariantsOptions } from '../../types/query';
19
+ import type { BacklinkSource, BacklinksOptions, BacklinksResult, ContentTreeItem, DocumentFromHandle, ManyOptions, LocalizedDoc, NeighborsOptions, NeighborsResult, OneOptions, OptionsArg, PopulateSpec, PopulateFromOptions, PopulatedDocument, PaginationOptions, PaginationResult, ResolveOneOptions, ResolveOneResult, TreeOptions, ContentVariant, VariantsOptions } from '../../types/query';
20
20
  import type { ContentQueryContext } from './context';
21
21
  export type { ContentQueryContext, ContentQueryEndpoint, RuntimeContentConfig } from './context';
22
22
  export { navigationSelectFields } from './navigation';
@@ -31,7 +31,7 @@ export declare function one<const H extends ContentCollectionHandle | string, O
31
31
  /**
32
32
  * Resolve a list of documents matching the filter. Always returns an array.
33
33
  */
34
- export declare function many<const H extends ContentCollectionHandle | string, O extends ManyOptions<H, PopulateSpec | undefined>>(context: ContentQueryContext, handle: H, options?: O): Promise<Array<LocalizedDoc<PopulatedDocument<DocumentFromHandle<H>, PopulateFromOptions<O>>>>>;
34
+ export declare function many<const H extends ContentCollectionHandle | string, O extends ManyOptions<H, PopulateSpec | undefined>>(context: ContentQueryContext, handle: H, ...args: OptionsArg<H, O>): Promise<Array<LocalizedDoc<PopulatedDocument<DocumentFromHandle<H>, PopulateFromOptions<O>>>>>;
35
35
  /**
36
36
  * Resolve one page of documents and preserve the query envelope metadata.
37
37
  */
@@ -62,9 +62,9 @@ export declare function variants<H extends ContentCollectionHandle | string>(con
62
62
  * fallback locale's path). This matches legacy navigation semantics —
63
63
  * sidebars are inherently lossy when filtered too strictly.
64
64
  */
65
- export declare function tree<H extends ContentCollectionHandle | string, Fields extends ReadonlyArray<string> | undefined = undefined>(context: ContentQueryContext, handle: H, options?: Omit<TreeOptions<H>, 'fields'> & {
65
+ export declare function tree<H extends ContentCollectionHandle | string, Fields extends ReadonlyArray<string> | undefined = undefined>(context: ContentQueryContext, handle: H, ...args: OptionsArg<H, Omit<TreeOptions<H>, 'fields'> & {
66
66
  fields?: Fields;
67
- }): Promise<ContentTreeItem<H extends {
67
+ }>): Promise<ContentTreeItem<H extends {
68
68
  __schema: {
69
69
  _output: infer O;
70
70
  };
@@ -10,7 +10,8 @@ export async function resolveOne(context, handle, options) {
10
10
  export async function one(context, handle, options) {
11
11
  return resolveDocumentOnly(context, handle, options);
12
12
  }
13
- export async function many(context, handle, options = {}) {
13
+ export async function many(context, handle, ...args) {
14
+ const options = args[0] ?? {};
14
15
  return resolveManyDocuments(context, one, handle, options);
15
16
  }
16
17
  export async function paginate(context, handle, options) {
@@ -22,7 +23,8 @@ export async function backlinks(context, targetHandle, options) {
22
23
  export async function variants(context, handle, options) {
23
24
  return resolveVariants(context, one, handle, options);
24
25
  }
25
- export async function tree(context, handle, options = {}) {
26
+ export async function tree(context, handle, ...args) {
27
+ const options = args[0] ?? {};
26
28
  return resolveTree(context, handle, options);
27
29
  }
28
30
  export async function neighbors(context, handle, options) {
@@ -15,14 +15,14 @@ export async function resolveVariants(context, one, handle, options) {
15
15
  fallback: true
16
16
  });
17
17
  if (!seed) return [];
18
- const variantPaths = seed._variantPaths || {};
18
+ const localePaths = seed.localePaths || {};
19
19
  const sourceLocale = seed.locale || defaultLocale || "";
20
20
  return requestedLocales.map((locale) => {
21
- const variantPath = variantPaths[locale];
22
- if (variantPath) {
21
+ const entry = localePaths[locale];
22
+ if (entry?.translated) {
23
23
  return {
24
24
  locale,
25
- path: seed.localePaths[locale]?.path || variantPath,
25
+ path: entry.path,
26
26
  translated: true
27
27
  };
28
28
  }
@@ -1,5 +1,5 @@
1
- const itemPath = (item) => item.path || item._path;
2
- const searchGroupId = (item, depth, index) => `content-search-group:${String(item._canonicalKey || item.stem || `${depth}:${index}`)}`;
1
+ const itemPath = (item) => item.path || item.path;
2
+ const searchGroupId = (item, depth, index) => `content-search-group:${String(item.canonicalKey || item.stem || `${depth}:${index}`)}`;
3
3
  export function createContentSearchNavigation(items = [], depth = 0) {
4
4
  return items.map((item, index) => {
5
5
  const children = item.children ? createContentSearchNavigation(item.children, depth + 1) : [];
@@ -1,6 +1,6 @@
1
1
  import type { ParsedContent } from '../../types/content';
2
2
  import type { ContentCollectionSearchSectionsOptions, ContentSearchSection } from '../../types/query';
3
- type SearchablePage = Pick<ParsedContent, '_path' | 'title' | 'description' | 'body'> & Record<string, unknown>;
3
+ type SearchablePage = Pick<ParsedContent, 'path' | 'title' | 'description' | 'body'> & Record<string, unknown>;
4
4
  /**
5
5
  * Backing option type for search-section generation.
6
6
  *
@@ -19,7 +19,7 @@ function splitPageIntoSections(page, {
19
19
  minLevel,
20
20
  maxLevel
21
21
  }) {
22
- const path = page._path || "";
22
+ const path = page.path || "";
23
23
  const extraFieldsData = pick(extraFields, page);
24
24
  const body = page.body;
25
25
  const sections = [{
@@ -1,10 +1,10 @@
1
1
  import type { ContentSitemapEntry } from '../../types/query';
2
2
  type ContentLikePage = {
3
- _path?: string;
4
- _collection?: string;
5
- _canonicalKey?: string;
6
- _locale?: string;
7
- _draft?: boolean;
3
+ path?: string;
4
+ collection?: string;
5
+ canonicalKey?: string;
6
+ locale?: string;
7
+ draft?: boolean;
8
8
  sitemap?: unknown;
9
9
  body?: unknown;
10
10
  image?: unknown;
@@ -123,25 +123,25 @@ export async function queryCollectionsSitemapEntriesData(runtime, loaders, optio
123
123
  const collectionPages = await loaders.loadCollectionPages(collection);
124
124
  return collectionPages.map((page) => ({
125
125
  ...page,
126
- _collection: page._collection || collection
126
+ collection: page.collection || collection
127
127
  }));
128
128
  }))).flat().filter((page) => {
129
129
  if (page.sitemap === false) {
130
130
  return false;
131
131
  }
132
- return shouldIncludeDrafts || !page._draft;
132
+ return shouldIncludeDrafts || !page.draft;
133
133
  });
134
134
  const uniquePages = Array.from(new Map(
135
135
  pages.map((page) => [
136
- `${page._collection || ""}:${page._canonicalKey || page._path || ""}`,
136
+ `${page.collection || ""}:${page.canonicalKey || page.path || ""}`,
137
137
  page
138
138
  ])
139
139
  ).values());
140
140
  const rawEntries = await Promise.all(uniquePages.map(async (page) => {
141
- if (!page._path || !page._collection) {
141
+ if (!page.path || !page.collection) {
142
142
  return [];
143
143
  }
144
- const meta = await loaders.loadRouteMeta(page._collection, page._path, page._locale);
144
+ const meta = await loaders.loadRouteMeta(page.collection, page.path, page.locale);
145
145
  if (!meta) {
146
146
  return [];
147
147
  }
@@ -149,7 +149,7 @@ export async function queryCollectionsSitemapEntriesData(runtime, loaders, optio
149
149
  const localizedVariants = variants.filter((variant) => variant.locale);
150
150
  const alternatives = localizedVariants.length > 1 ? buildAlternatives(siteUrl, meta.defaultLocale, localeToLanguage, variants) : void 0;
151
151
  return await Promise.all(variants.map(async (variant) => {
152
- const variantPage = await loaders.loadPage(page._collection, variant.path, variant.locale);
152
+ const variantPage = await loaders.loadPage(page.collection, variant.path, variant.locale);
153
153
  const images = toPageSitemapImages(
154
154
  siteUrl,
155
155
  variantPage ? { ...page, ...variantPage } : page,