@vendure-io/docs-provider 0.7.0 → 0.8.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.
@@ -0,0 +1,326 @@
1
+ # Last Modified Dates
2
+
3
+ This guide explains how to include accurate "last modified" dates in your documentation package. These dates are extracted from git history at build time and displayed on documentation pages.
4
+
5
+ ## The Problem
6
+
7
+ When documentation packages are installed from npm, file modification times (`mtime`) reflect the installation time, not when the content was actually written. This makes it impossible to show meaningful "last edited" information using standard file system stats.
8
+
9
+ ## The Solution
10
+
11
+ The docs-provider library provides utilities to:
12
+
13
+ 1. Extract last-modified dates from git history at **build time**
14
+ 2. Generate a TypeScript file with hardcoded date mappings
15
+ 3. Apply these dates to your navigation nodes
16
+ 4. Include the dates in your published npm package
17
+
18
+ This means dates are resolved once during build, then shipped as static data with no git access needed at runtime.
19
+
20
+ ## Quick Start
21
+
22
+ ### Step 1: Generate Dates File
23
+
24
+ Create a script to generate dates during your build process:
25
+
26
+ ```typescript
27
+ // scripts/generate-dates.ts
28
+ import { generateDatesFile } from '@vendure-io/docs-provider'
29
+ import { dirname, join } from 'path'
30
+ import { fileURLToPath } from 'url'
31
+
32
+ const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)))
33
+
34
+ await generateDatesFile({
35
+ docsDir: join(packageRoot, 'docs'),
36
+ outputPath: join(packageRoot, 'src/dates.generated.ts'),
37
+ gitCwd: packageRoot,
38
+ })
39
+
40
+ console.log('Generated dates.generated.ts')
41
+ ```
42
+
43
+ ### Step 2: Add Prebuild Script
44
+
45
+ Update your `package.json` to run the generation before building:
46
+
47
+ ```json
48
+ {
49
+ "scripts": {
50
+ "generate-dates": "tsx scripts/generate-dates.ts",
51
+ "prebuild": "npm run generate-dates",
52
+ "build": "tsc"
53
+ }
54
+ }
55
+ ```
56
+
57
+ ### Step 3: Apply Dates to Manifest
58
+
59
+ Import the generated dates and apply them to your navigation:
60
+
61
+ ```typescript
62
+ // src/manifest.ts
63
+ import {
64
+ applyLastModifiedDates,
65
+ createNavigationFromFolder,
66
+ resolveManifest,
67
+ type DocsPackageManifestInput,
68
+ } from '@vendure-io/docs-provider'
69
+ import { dirname, join } from 'path'
70
+ import { fileURLToPath } from 'url'
71
+ import { lastModifiedDates } from './dates.generated'
72
+
73
+ const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)))
74
+ const file = (relativePath: string) => join(packageRoot, relativePath)
75
+
76
+ const manifestInput: DocsPackageManifestInput = {
77
+ id: 'my-plugin',
78
+ name: 'My Plugin Documentation',
79
+ version: '1.0.0',
80
+ vendureVersion: 'v3',
81
+ basePath: packageRoot,
82
+ navigation: [
83
+ { file: file('docs/getting-started.mdx') },
84
+ {
85
+ title: 'Guides',
86
+ slug: 'guides',
87
+ children: createNavigationFromFolder(join(packageRoot, 'docs/guides')),
88
+ },
89
+ ],
90
+ }
91
+
92
+ // Resolve the manifest first (derives title/slug from files)
93
+ const resolvedManifest = resolveManifest(manifestInput)
94
+
95
+ // Apply dates from the generated file
96
+ export const manifest = {
97
+ ...resolvedManifest,
98
+ navigation: applyLastModifiedDates(
99
+ resolvedManifest.navigation,
100
+ lastModifiedDates,
101
+ { basePath: 'docs' }
102
+ ),
103
+ }
104
+ ```
105
+
106
+ ### Step 4: Include in Package Files
107
+
108
+ Ensure the generated file is included when publishing:
109
+
110
+ ```json
111
+ {
112
+ "files": ["src", "docs", "dist"]
113
+ }
114
+ ```
115
+
116
+ ## API Reference
117
+
118
+ ### generateDatesFile
119
+
120
+ Generates a TypeScript file containing last-modified dates for all MDX files in a directory.
121
+
122
+ ```typescript
123
+ import { generateDatesFile } from '@vendure-io/docs-provider'
124
+
125
+ const result = await generateDatesFile({
126
+ // Directory containing MDX files to scan
127
+ docsDir: '/path/to/docs',
128
+
129
+ // Where to write the generated TypeScript file
130
+ outputPath: '/path/to/src/dates.generated.ts',
131
+
132
+ // Git working directory (defaults to parent of docsDir)
133
+ gitCwd: '/path/to/repo',
134
+
135
+ // File extensions to include (defaults to ['.mdx', '.md'])
136
+ extensions: ['.mdx', '.md'],
137
+ })
138
+
139
+ console.log(`Extracted dates for ${result.filesWithDates} files`)
140
+ console.log(`Skipped ${result.filesSkipped} files (untracked or new)`)
141
+ ```
142
+
143
+ **Generated Output:**
144
+
145
+ ```typescript
146
+ // dates.generated.ts (auto-generated, do not edit)
147
+ // Generated at: 2024-01-22T10:30:00.000Z
148
+ // Total files: 15
149
+
150
+ export const lastModifiedDates: Record<string, string> = {
151
+ 'docs/getting-started.mdx': '2024-01-15T10:30:00+01:00',
152
+ 'docs/guides/installation.mdx': '2024-01-10T08:00:00+01:00',
153
+ 'docs/guides/configuration.mdx': '2024-01-12T14:00:00+01:00',
154
+ }
155
+ ```
156
+
157
+ ### applyLastModifiedDates
158
+
159
+ Applies dates from a map to navigation nodes. This function is browser-safe and doesn't require Node.js.
160
+
161
+ ```typescript
162
+ import { applyLastModifiedDates } from '@vendure-io/docs-provider'
163
+
164
+ const navigationWithDates = applyLastModifiedDates(
165
+ navigation, // NavigationNode[]
166
+ lastModifiedDates, // Record<string, string>
167
+ {
168
+ // Optional: prefix to prepend to file paths when looking up dates
169
+ basePath: 'docs'
170
+ }
171
+ )
172
+ ```
173
+
174
+ **How it works:**
175
+
176
+ 1. Recursively walks the navigation tree
177
+ 2. For each node with a `file` property, looks up the date in the map
178
+ 3. Adds `lastModified` property with the ISO 8601 date string
179
+ 4. Returns a new tree (does not mutate the original)
180
+
181
+ ### Git Utility Functions
182
+
183
+ Lower-level utilities for working with git dates directly:
184
+
185
+ ```typescript
186
+ import {
187
+ isGitRepository,
188
+ getGitLastModified,
189
+ getGitLastModifiedBatch,
190
+ } from '@vendure-io/docs-provider'
191
+
192
+ // Check if a directory is a git repository
193
+ const isGit = await isGitRepository('/path/to/dir')
194
+
195
+ // Get date for a single file
196
+ const date = await getGitLastModified('docs/intro.mdx', {
197
+ cwd: '/path/to/repo'
198
+ })
199
+ // Returns: '2024-01-15T10:30:00+01:00' or null
200
+
201
+ // Get dates for multiple files efficiently
202
+ const result = await getGitLastModifiedBatch(
203
+ ['docs/intro.mdx', 'docs/guide.mdx'],
204
+ { cwd: '/path/to/repo' }
205
+ )
206
+ // Returns: { dates: { 'docs/intro.mdx': '2024-...' }, skipped: [] }
207
+ ```
208
+
209
+ ## Date Format
210
+
211
+ All dates use ISO 8601 format with timezone offset:
212
+
213
+ ```
214
+ 2024-01-15T10:30:00+01:00
215
+ ```
216
+
217
+ This format is:
218
+ - Human-readable
219
+ - Machine-parseable
220
+ - Timezone-aware
221
+ - Compatible with JavaScript's `new Date()` constructor
222
+
223
+ ## Edge Cases
224
+
225
+ ### Untracked Files
226
+
227
+ Files not yet committed to git will be skipped (no date assigned). This is intentional - new files don't have a meaningful "last modified" date until they're part of the git history.
228
+
229
+ ### Non-Git Directories
230
+
231
+ If `generateDatesFile` is run outside a git repository:
232
+ - A warning is logged
233
+ - An empty dates file is generated
234
+ - No errors are thrown
235
+
236
+ This allows the build to succeed in CI environments that might do shallow clones or lack git history.
237
+
238
+ ### Frontmatter Override
239
+
240
+ You can manually specify a `lastModified` date in frontmatter to override the git-derived date:
241
+
242
+ ```mdx
243
+ ---
244
+ title: My Page
245
+ lastModified: '2024-01-20T12:00:00Z'
246
+ ---
247
+
248
+ # My Page
249
+
250
+ Content here...
251
+ ```
252
+
253
+ The frontmatter date takes precedence over the git date when both are present.
254
+
255
+ ## Complete Example
256
+
257
+ See the full workflow in a docs package:
258
+
259
+ **Project structure:**
260
+
261
+ ```
262
+ @vendure/docs-my-plugin/
263
+ ├── scripts/
264
+ │ └── generate-dates.ts
265
+ ├── src/
266
+ │ ├── index.ts
267
+ │ ├── manifest.ts
268
+ │ └── dates.generated.ts # Generated
269
+ ├── docs/
270
+ │ ├── getting-started.mdx
271
+ │ └── guides/
272
+ │ └── installation.mdx
273
+ ├── package.json
274
+ └── tsconfig.json
275
+ ```
276
+
277
+ **package.json:**
278
+
279
+ ```json
280
+ {
281
+ "name": "@vendure/docs-my-plugin",
282
+ "scripts": {
283
+ "generate-dates": "tsx scripts/generate-dates.ts",
284
+ "prebuild": "npm run generate-dates",
285
+ "build": "tsc"
286
+ },
287
+ "files": ["src", "docs", "dist"]
288
+ }
289
+ ```
290
+
291
+ **.gitignore:**
292
+
293
+ ```
294
+ # Generated files (regenerated on each build)
295
+ src/dates.generated.ts
296
+ ```
297
+
298
+ ## Best Practices
299
+
300
+ 1. **Run generation in prebuild**: This ensures dates are always fresh when publishing
301
+
302
+ 2. **Commit or ignore the generated file**: Either approach works:
303
+ - **Ignore**: Cleaner git history, regenerated on each build
304
+ - **Commit**: Visible history of date changes, works without git in CI
305
+
306
+ 3. **Use appropriate basePath**: Match the path structure between your dates map keys and navigation file paths
307
+
308
+ 4. **Handle missing dates gracefully**: The docs application shows nothing when `lastModified` is null, so missing dates won't break your site
309
+
310
+ ## Troubleshooting
311
+
312
+ ### Dates not appearing
313
+
314
+ 1. Check that `lastModifiedDates` is being imported correctly
315
+ 2. Verify the file paths in the dates map match your navigation's `file` properties
316
+ 3. Try different `basePath` values in `applyLastModifiedDates`
317
+
318
+ ### All files skipped
319
+
320
+ 1. Ensure you're running in a git repository
321
+ 2. Check that files are committed (not just staged)
322
+ 3. Verify the `gitCwd` option points to the repository root
323
+
324
+ ### Wrong dates
325
+
326
+ Git uses the committer date, not the author date. If you've rebased or amended commits, dates may not reflect the original authoring time.
@@ -77,7 +77,7 @@ Tests all MDX files referenced in a manifest's navigation tree.
77
77
  ```typescript
78
78
  async function testManifestMdx(
79
79
  manifest: DocsPackageManifest,
80
- options?: TestManifestOptions
80
+ options?: TestManifestOptions,
81
81
  ): Promise<MdxTestReport>
82
82
  ```
83
83
 
@@ -88,12 +88,12 @@ async function testManifestMdx(
88
88
 
89
89
  **Options:**
90
90
 
91
- | Option | Type | Default | Description |
92
- |--------|------|---------|-------------|
93
- | `failFast` | `boolean` | `false` | Stop on first failure |
91
+ | Option | Type | Default | Description |
92
+ | --------------- | --------------- | --------------- | --------------------- |
93
+ | `failFast` | `boolean` | `false` | Stop on first failure |
94
94
  | `remarkPlugins` | `PluggableList` | Default plugins | Custom remark plugins |
95
95
  | `rehypePlugins` | `PluggableList` | Default plugins | Custom rehype plugins |
96
- | `onProgress` | `Function` | `undefined` | Progress callback |
96
+ | `onProgress` | `Function` | `undefined` | Progress callback |
97
97
 
98
98
  **Example with progress reporting:**
99
99
 
@@ -114,7 +114,7 @@ Compiles a single MDX string and returns the result.
114
114
  async function compileMdx(
115
115
  content: string,
116
116
  filePath: string,
117
- options?: CompileMdxOptions
117
+ options?: CompileMdxOptions,
118
118
  ): Promise<MdxCompilationResult>
119
119
  ```
120
120
 
@@ -186,7 +186,7 @@ Creates a simple progress reporter for console output.
186
186
  function createProgressReporter(): (
187
187
  current: number,
188
188
  total: number,
189
- result: MdxCompilationResult
189
+ result: MdxCompilationResult,
190
190
  ) => void
191
191
  ```
192
192
 
@@ -304,13 +304,15 @@ Supported types: `info`, `note`, `tip`, `warning`, `caution`, `danger`
304
304
 
305
305
  ### Code Fence Metadata
306
306
 
307
- ```mdx
307
+ ````mdx
308
308
  ```typescript title="src/example.ts"
309
309
  export function example() {
310
310
  return 'Hello'
311
311
  }
312
312
  ```
313
- ```
313
+ ````
314
+
315
+ ````
314
316
 
315
317
  ### GitHub Flavored Markdown
316
318
 
@@ -325,7 +327,7 @@ export function example() {
325
327
  <Callout type="info" title="Note">
326
328
  Custom JSX components work as expected.
327
329
  </Callout>
328
- ```
330
+ ````
329
331
 
330
332
  ## Common Errors
331
333
 
@@ -339,13 +341,13 @@ Ensure all JSX tags are properly closed:
339
341
 
340
342
  ```mdx
341
343
  <!-- Wrong -->
344
+
342
345
  <div>
343
346
  Content here
344
347
 
345
348
  <!-- Correct -->
346
- <div>
347
- Content here
348
- </div>
349
+
350
+ <div>Content here</div>
349
351
  ```
350
352
 
351
353
  ### Invalid JSX Syntax
@@ -355,6 +357,7 @@ Error (line 8:5): Unexpected token
355
357
  ```
356
358
 
357
359
  Check for:
360
+
358
361
  - Missing quotes around attribute values
359
362
  - Unescaped special characters (`<`, `>`, `{`, `}`)
360
363
  - JavaScript expressions not wrapped in curly braces
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vendure-io/docs-provider",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Contract types and utilities for Vendure documentation packages",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -1 +0,0 @@
1
- "use strict";var D=Object.defineProperty;var j=(i,t,n)=>t in i?D(i,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):i[t]=n;var f=(i,t,n)=>j(i,typeof t!="symbol"?t+"":t,n);const e=require("zod"),g=e.z.enum(["v1","v2","v3"]),d=e.z.object({indexFields:e.z.array(e.z.enum(["title","description","content","keywords"])),boosts:e.z.record(e.z.string(),e.z.number()).optional()}),u=e.z.object({repository:e.z.string().regex(/^[^/]+\/[^/]+$/,'Repository must be in format "owner/repo"'),branch:e.z.string().optional(),docsPath:e.z.string().optional()}),l=e.z.lazy(()=>e.z.object({title:e.z.string().min(1,"Navigation title is required"),slug:e.z.string().min(1,"Navigation slug is required"),file:e.z.string().optional(),children:e.z.array(l).optional(),badge:e.z.string().optional(),hidden:e.z.boolean().optional()})),h=e.z.object({id:e.z.string().min(1,"Package ID is required"),name:e.z.string().min(1,"Package name is required"),version:e.z.string().regex(/^\d+\.\d+\.\d+/,"Version must be valid semver"),vendureVersion:g,navigation:e.z.array(l),search:d.optional(),github:u.optional(),basePath:e.z.string().optional()}),p=e.z.object({title:e.z.string().min(1,"Page title is required"),description:e.z.string().optional(),keywords:e.z.array(e.z.string()).optional(),sidebarLabel:e.z.string().optional(),hidden:e.z.boolean().optional(),order:e.z.number().int().optional()}),k=e.z.object({meta:p,content:e.z.string(),filePath:e.z.string()}),I=e.z.object({manifest:h,basePath:e.z.string()}),M=e.z.object({title:e.z.string(),slug:e.z.string(),path:e.z.string()}),V=e.z.object({title:e.z.string(),slug:e.z.string(),file:e.z.string().optional(),children:e.z.array(e.z.lazy(()=>l)).optional(),badge:e.z.string().optional(),hidden:e.z.boolean().optional(),path:e.z.string(),depth:e.z.number().int().min(0),parentPath:e.z.string().optional()}),z=e.z.lazy(()=>e.z.object({title:e.z.string().min(1).optional(),slug:e.z.string().min(1).optional(),file:e.z.string().optional(),children:e.z.array(z).optional(),badge:e.z.string().optional(),hidden:e.z.boolean().optional()})),x=e.z.object({id:e.z.string().min(1,"Package ID is required"),name:e.z.string().min(1,"Package name is required"),version:e.z.string().regex(/^\d+\.\d+\.\d+/,"Version must be valid semver"),vendureVersion:g,navigation:e.z.array(z),search:d.optional(),github:u.optional(),basePath:e.z.string().optional()});class b extends Error{constructor(n,o){super(n);f(this,"issues");this.name="ManifestValidationError",this.issues=o}}function q(i){const t=h.safeParse(i);if(!t.success){const n=t.error.issues.map(o=>`${o.path.join(".")}: ${o.message}`);throw new b("Invalid manifest",n)}return t.data}function B(i,t){const n=t.split("/").filter(Boolean);return v(i.navigation,n)}function v(i,t){if(t.length===0)return;const[n,...o]=t,a=i.find(r=>r.slug===n);if(a){if(o.length===0)return a;if(a.children)return v(a.children,o)}}function m(i){const t=[];return N(i.navigation,"",0,void 0,t),t}function N(i,t,n,o,a){for(const r of i){const s=t?`${t}/${r.slug}`:r.slug;a.push({...r,path:s,depth:n,parentPath:o}),r.children&&r.children.length>0&&N(r.children,s,n+1,s,a)}}function $(i,t){const n=t.split("/").filter(Boolean),o=[];let a=i.navigation,r="";for(const s of n){const c=a.find(y=>y.slug===s);if(!c)break;r=r?`${r}/${s}`:s,o.push({title:c.title,slug:c.slug,path:r,file:c.file}),a=c.children??[]}return o}function S(i){return m(i).filter(t=>t.file!==void 0)}function w(i,t){const n=S(i),o=n.findIndex(a=>a.path===t);return o===-1?{}:{prev:o>0?n[o-1]:void 0,next:o<n.length-1?n[o+1]:void 0}}function P(i,t){const n=t.split("/").filter(Boolean);if(n.length===0)return!1;if(i.slug===n[0]){if(n.length===1)return!0;if(i.children){const o=n.slice(1).join("/");return i.children.some(a=>P(a,o))}}return!1}function L(i,t){return m(i).filter(n=>n.depth===t)}exports.BreadcrumbItemSchema=M;exports.DocPageMetaSchema=p;exports.DocPageSchema=k;exports.DocsPackageManifestInputSchema=x;exports.DocsPackageManifestSchema=h;exports.FlatNavigationNodeSchema=V;exports.GitHubConfigSchema=u;exports.LoadedDocsPackageSchema=I;exports.ManifestValidationError=b;exports.NavigationNodeInputSchema=z;exports.NavigationNodeSchema=l;exports.SearchConfigSchema=d;exports.VendureVersionSchema=g;exports.buildBreadcrumbs=$;exports.findNavigationNode=B;exports.flattenNavigation=m;exports.getLeafNodes=S;exports.getNodesAtDepth=L;exports.getPrevNextNodes=w;exports.isNodeActive=P;exports.validateManifest=q;
@@ -1,182 +0,0 @@
1
- var P = Object.defineProperty;
2
- var S = (i, t, e) => t in i ? P(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
3
- var g = (i, t, e) => S(i, typeof t != "symbol" ? t + "" : t, e);
4
- import { z as n } from "zod";
5
- const d = n.enum(["v1", "v2", "v3"]), u = n.object({
6
- indexFields: n.array(n.enum(["title", "description", "content", "keywords"])),
7
- boosts: n.record(n.string(), n.number()).optional()
8
- }), f = n.object({
9
- repository: n.string().regex(/^[^/]+\/[^/]+$/, 'Repository must be in format "owner/repo"'),
10
- branch: n.string().optional(),
11
- docsPath: n.string().optional()
12
- }), c = n.lazy(
13
- () => n.object({
14
- title: n.string().min(1, "Navigation title is required"),
15
- slug: n.string().min(1, "Navigation slug is required"),
16
- file: n.string().optional(),
17
- children: n.array(c).optional(),
18
- badge: n.string().optional(),
19
- hidden: n.boolean().optional()
20
- })
21
- ), h = n.object({
22
- id: n.string().min(1, "Package ID is required"),
23
- name: n.string().min(1, "Package name is required"),
24
- version: n.string().regex(/^\d+\.\d+\.\d+/, "Version must be valid semver"),
25
- vendureVersion: d,
26
- navigation: n.array(c),
27
- search: u.optional(),
28
- github: f.optional(),
29
- basePath: n.string().optional()
30
- }), y = n.object({
31
- title: n.string().min(1, "Page title is required"),
32
- description: n.string().optional(),
33
- keywords: n.array(n.string()).optional(),
34
- sidebarLabel: n.string().optional(),
35
- hidden: n.boolean().optional(),
36
- order: n.number().int().optional()
37
- }), I = n.object({
38
- meta: y,
39
- content: n.string(),
40
- filePath: n.string()
41
- }), q = n.object({
42
- manifest: h,
43
- basePath: n.string()
44
- }), B = n.object({
45
- title: n.string(),
46
- slug: n.string(),
47
- path: n.string()
48
- }), M = n.object({
49
- title: n.string(),
50
- slug: n.string(),
51
- file: n.string().optional(),
52
- children: n.array(n.lazy(() => c)).optional(),
53
- badge: n.string().optional(),
54
- hidden: n.boolean().optional(),
55
- path: n.string(),
56
- depth: n.number().int().min(0),
57
- parentPath: n.string().optional()
58
- }), m = n.lazy(
59
- () => n.object({
60
- title: n.string().min(1).optional(),
61
- slug: n.string().min(1).optional(),
62
- file: n.string().optional(),
63
- children: n.array(m).optional(),
64
- badge: n.string().optional(),
65
- hidden: n.boolean().optional()
66
- })
67
- ), $ = n.object({
68
- id: n.string().min(1, "Package ID is required"),
69
- name: n.string().min(1, "Package name is required"),
70
- version: n.string().regex(/^\d+\.\d+\.\d+/, "Version must be valid semver"),
71
- vendureVersion: d,
72
- navigation: n.array(m),
73
- search: u.optional(),
74
- github: f.optional(),
75
- basePath: n.string().optional()
76
- });
77
- class j extends Error {
78
- constructor(e, o) {
79
- super(e);
80
- g(this, "issues");
81
- this.name = "ManifestValidationError", this.issues = o;
82
- }
83
- }
84
- function w(i) {
85
- const t = h.safeParse(i);
86
- if (!t.success) {
87
- const e = t.error.issues.map((o) => `${o.path.join(".")}: ${o.message}`);
88
- throw new j("Invalid manifest", e);
89
- }
90
- return t.data;
91
- }
92
- function z(i, t) {
93
- const e = t.split("/").filter(Boolean);
94
- return p(i.navigation, e);
95
- }
96
- function p(i, t) {
97
- if (t.length === 0) return;
98
- const [e, ...o] = t, a = i.find((r) => r.slug === e);
99
- if (a) {
100
- if (o.length === 0) return a;
101
- if (a.children)
102
- return p(a.children, o);
103
- }
104
- }
105
- function b(i) {
106
- const t = [];
107
- return v(i.navigation, "", 0, void 0, t), t;
108
- }
109
- function v(i, t, e, o, a) {
110
- for (const r of i) {
111
- const s = t ? `${t}/${r.slug}` : r.slug;
112
- a.push({
113
- ...r,
114
- path: s,
115
- depth: e,
116
- parentPath: o
117
- }), r.children && r.children.length > 0 && v(r.children, s, e + 1, s, a);
118
- }
119
- }
120
- function L(i, t) {
121
- const e = t.split("/").filter(Boolean), o = [];
122
- let a = i.navigation, r = "";
123
- for (const s of e) {
124
- const l = a.find((N) => N.slug === s);
125
- if (!l) break;
126
- r = r ? `${r}/${s}` : s, o.push({
127
- title: l.title,
128
- slug: l.slug,
129
- path: r,
130
- file: l.file
131
- }), a = l.children ?? [];
132
- }
133
- return o;
134
- }
135
- function k(i) {
136
- return b(i).filter((t) => t.file !== void 0);
137
- }
138
- function E(i, t) {
139
- const e = k(i), o = e.findIndex((a) => a.path === t);
140
- return o === -1 ? {} : {
141
- prev: o > 0 ? e[o - 1] : void 0,
142
- next: o < e.length - 1 ? e[o + 1] : void 0
143
- };
144
- }
145
- function x(i, t) {
146
- const e = t.split("/").filter(Boolean);
147
- if (e.length === 0) return !1;
148
- if (i.slug === e[0]) {
149
- if (e.length === 1) return !0;
150
- if (i.children) {
151
- const o = e.slice(1).join("/");
152
- return i.children.some((a) => x(a, o));
153
- }
154
- }
155
- return !1;
156
- }
157
- function F(i, t) {
158
- return b(i).filter((e) => e.depth === t);
159
- }
160
- export {
161
- B,
162
- y as D,
163
- M as F,
164
- f as G,
165
- q as L,
166
- j as M,
167
- m as N,
168
- u as S,
169
- d as V,
170
- I as a,
171
- $ as b,
172
- h as c,
173
- c as d,
174
- L as e,
175
- z as f,
176
- b as g,
177
- k as h,
178
- F as i,
179
- E as j,
180
- x as k,
181
- w as v
182
- };