fumadocs-core 15.8.0 → 15.8.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.
- package/dist/source/index.d.ts +104 -72
- package/dist/source/index.js +139 -82
- package/package.json +6 -6
package/dist/source/index.d.ts
CHANGED
|
@@ -1,6 +1,46 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { R as Root, I as Item, F as Folder, S as Separator } from '../definitions-Q95-psoo.js';
|
|
1
|
+
import { I as Item, F as Folder, S as Separator, R as Root } from '../definitions-Q95-psoo.js';
|
|
3
2
|
import { I18nConfig } from '../i18n/index.js';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface FileInfo {
|
|
6
|
+
/**
|
|
7
|
+
* File path without extension
|
|
8
|
+
*
|
|
9
|
+
* @deprecated obtain it with `join(dirname, name)`
|
|
10
|
+
*/
|
|
11
|
+
flattenedPath: string;
|
|
12
|
+
/**
|
|
13
|
+
* path of file (unparsed)
|
|
14
|
+
*/
|
|
15
|
+
path: string;
|
|
16
|
+
/**
|
|
17
|
+
* File name without extension
|
|
18
|
+
*/
|
|
19
|
+
name: string;
|
|
20
|
+
/**
|
|
21
|
+
* file extension from the last `.`, like `.md`
|
|
22
|
+
*
|
|
23
|
+
* empty string if no file extension
|
|
24
|
+
*/
|
|
25
|
+
ext: string;
|
|
26
|
+
dirname: string;
|
|
27
|
+
}
|
|
28
|
+
interface FolderInfo {
|
|
29
|
+
/**
|
|
30
|
+
* Original path of folder
|
|
31
|
+
*/
|
|
32
|
+
path: string;
|
|
33
|
+
/**
|
|
34
|
+
* folder name
|
|
35
|
+
*/
|
|
36
|
+
name: string;
|
|
37
|
+
dirname: string;
|
|
38
|
+
}
|
|
39
|
+
declare function parseFilePath(path: string): FileInfo;
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated use `dirname` and `basename` directly.
|
|
42
|
+
*/
|
|
43
|
+
declare function parseFolderPath(path: string): FolderInfo;
|
|
4
44
|
|
|
5
45
|
/**
|
|
6
46
|
* In memory file system.
|
|
@@ -22,8 +62,8 @@ declare class FileSystem<File> {
|
|
|
22
62
|
}
|
|
23
63
|
|
|
24
64
|
interface LoadOptions {
|
|
25
|
-
transformers?: Transformer[];
|
|
26
65
|
buildFile: (file: VirtualFile) => MetaFile | PageFile;
|
|
66
|
+
plugins?: LoaderPlugin[];
|
|
27
67
|
}
|
|
28
68
|
type ContentStorage<Page extends PageData = PageData, Meta extends MetaData = MetaData> = FileSystem<MetaFile<Meta> | PageFile<Page>>;
|
|
29
69
|
interface MetaFile<Data extends MetaData = MetaData> {
|
|
@@ -41,7 +81,6 @@ interface PageFile<Data extends PageData = PageData> {
|
|
|
41
81
|
}
|
|
42
82
|
type Transformer = (context: {
|
|
43
83
|
storage: ContentStorage;
|
|
44
|
-
options: LoadOptions;
|
|
45
84
|
}) => void;
|
|
46
85
|
/**
|
|
47
86
|
* @returns a map of locale and its content storage.
|
|
@@ -50,45 +89,49 @@ type Transformer = (context: {
|
|
|
50
89
|
*/
|
|
51
90
|
declare function loadFiles(files: VirtualFile[], options: LoadOptions, i18n: I18nConfig): Record<string, ContentStorage>;
|
|
52
91
|
|
|
53
|
-
|
|
92
|
+
type LoaderPlugins<Page extends PageData, Meta extends MetaData> = LoaderPlugin<Page, Meta>[];
|
|
93
|
+
interface LoaderPlugin<Page extends PageData = PageData, Meta extends MetaData = MetaData> {
|
|
54
94
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* @deprecated obtain it with `join(dirname, name)`
|
|
95
|
+
* transform the storage after loading
|
|
58
96
|
*/
|
|
59
|
-
|
|
97
|
+
transformStorage?: (context: {
|
|
98
|
+
storage: ContentStorage<Page, Meta>;
|
|
99
|
+
}) => void;
|
|
60
100
|
/**
|
|
61
|
-
*
|
|
101
|
+
* transform the generated page tree
|
|
62
102
|
*/
|
|
63
|
-
|
|
103
|
+
transformPageTree?: PageTreeTransformer<Page, Meta>;
|
|
104
|
+
}
|
|
105
|
+
declare function buildPlugins<Page extends PageData, Meta extends MetaData>(plugins: LoaderPlugins<Page, Meta>): LoaderPlugin<Page, Meta>[];
|
|
106
|
+
|
|
107
|
+
interface LegacyLoaderOptions {
|
|
64
108
|
/**
|
|
65
|
-
*
|
|
109
|
+
* We recommend you to use `plugins` instead
|
|
66
110
|
*/
|
|
67
|
-
|
|
111
|
+
transformers?: Transformer[];
|
|
112
|
+
}
|
|
113
|
+
interface LegacyPageTreeOptions<Page extends PageData, Meta extends MetaData> {
|
|
68
114
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* empty string if no file extension
|
|
115
|
+
* @deprecated use `plugins` instead
|
|
72
116
|
*/
|
|
73
|
-
|
|
74
|
-
dirname: string;
|
|
75
|
-
}
|
|
76
|
-
interface FolderInfo {
|
|
117
|
+
attachFile?: (node: Item, file?: PageFile<Page>) => Item;
|
|
77
118
|
/**
|
|
78
|
-
*
|
|
119
|
+
* @deprecated use `plugins` instead
|
|
79
120
|
*/
|
|
80
|
-
|
|
121
|
+
attachFolder?: (node: Folder, folder: {
|
|
122
|
+
children: (PageFile<Page> | MetaFile<Meta>)[];
|
|
123
|
+
}, meta?: MetaFile<Meta>) => Folder;
|
|
81
124
|
/**
|
|
82
|
-
*
|
|
125
|
+
* @deprecated use `plugins` instead
|
|
83
126
|
*/
|
|
84
|
-
|
|
85
|
-
|
|
127
|
+
attachSeparator?: (node: Separator) => Separator;
|
|
128
|
+
/**
|
|
129
|
+
* We recommend you to use `plugins` instead
|
|
130
|
+
*/
|
|
131
|
+
transformers?: PageTreeTransformer<Page, Meta>[];
|
|
86
132
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
* @deprecated use `dirname` and `basename` directly.
|
|
90
|
-
*/
|
|
91
|
-
declare function parseFolderPath(path: string): FolderInfo;
|
|
133
|
+
|
|
134
|
+
type IconResolver = (icon: string | undefined) => ReactNode;
|
|
92
135
|
|
|
93
136
|
interface LoaderConfig {
|
|
94
137
|
source: SourceConfig;
|
|
@@ -98,21 +141,23 @@ interface SourceConfig {
|
|
|
98
141
|
pageData: PageData;
|
|
99
142
|
metaData: MetaData;
|
|
100
143
|
}
|
|
101
|
-
|
|
144
|
+
type LoaderOptions<Config extends SourceConfig = SourceConfig, I18n extends I18nConfig | undefined = I18nConfig | undefined> = BaseLoaderOptions<NoInfer<Config>> & {
|
|
145
|
+
source: Source<Config> | Source<Config>[];
|
|
146
|
+
/**
|
|
147
|
+
* Configure i18n
|
|
148
|
+
*/
|
|
149
|
+
i18n?: I18n;
|
|
150
|
+
};
|
|
151
|
+
interface BaseLoaderOptions<Config extends SourceConfig> extends LegacyLoaderOptions {
|
|
102
152
|
baseUrl: string;
|
|
103
|
-
icon?:
|
|
153
|
+
icon?: IconResolver;
|
|
104
154
|
slugs?: (info: FileInfo) => string[];
|
|
105
155
|
url?: UrlFn;
|
|
106
|
-
source: Source<T> | Source<T>[];
|
|
107
|
-
transformers?: Transformer[];
|
|
108
156
|
/**
|
|
109
157
|
* Additional options for page tree builder
|
|
110
158
|
*/
|
|
111
|
-
pageTree?: Partial<BaseOptions<
|
|
112
|
-
|
|
113
|
-
* Configure i18n
|
|
114
|
-
*/
|
|
115
|
-
i18n?: I18n;
|
|
159
|
+
pageTree?: Partial<BaseOptions> & LegacyPageTreeOptions<Config['pageData'], Config['metaData']>;
|
|
160
|
+
plugins?: LoaderPlugins<Config['pageData'], Config['metaData']>;
|
|
116
161
|
}
|
|
117
162
|
interface Source<Config extends SourceConfig> {
|
|
118
163
|
/**
|
|
@@ -183,13 +228,19 @@ interface LoaderOutput<Config extends LoaderConfig> {
|
|
|
183
228
|
page: Page<Config['source']['pageData']>;
|
|
184
229
|
hash?: string;
|
|
185
230
|
} | undefined;
|
|
231
|
+
/**
|
|
232
|
+
* @internal
|
|
233
|
+
*/
|
|
186
234
|
_i18n?: I18nConfig;
|
|
187
235
|
/**
|
|
188
|
-
* Get list of pages from language
|
|
236
|
+
* Get a list of pages from specified language
|
|
189
237
|
*
|
|
190
|
-
* @param language - If empty,
|
|
238
|
+
* @param language - If empty, list pages from all languages.
|
|
191
239
|
*/
|
|
192
240
|
getPages: (language?: string) => Page<Config['source']['pageData']>[];
|
|
241
|
+
/**
|
|
242
|
+
* get each language and its pages, empty if i18n is not enabled.
|
|
243
|
+
*/
|
|
193
244
|
getLanguages: () => LanguageEntry<Config['source']['pageData']>[];
|
|
194
245
|
/**
|
|
195
246
|
* Get page with slugs
|
|
@@ -237,53 +288,36 @@ type InferMetaType<Utils extends LoaderOutput<any>> = Utils extends LoaderOutput
|
|
|
237
288
|
*/
|
|
238
289
|
type UrlFn = (slugs: string[], locale?: string) => string;
|
|
239
290
|
|
|
240
|
-
interface LegacyTransformerOptions<Page extends PageData, Meta extends MetaData> {
|
|
241
|
-
/**
|
|
242
|
-
* @deprecated use `transformers` instead
|
|
243
|
-
*/
|
|
244
|
-
attachFile?: (node: Item, file?: PageFile<Page>) => Item;
|
|
245
|
-
/**
|
|
246
|
-
* @deprecated use `transformers` instead
|
|
247
|
-
*/
|
|
248
|
-
attachFolder?: (node: Folder, folder: {
|
|
249
|
-
children: (PageFile<Page> | MetaFile<Meta>)[];
|
|
250
|
-
}, meta?: MetaFile<Meta>) => Folder;
|
|
251
|
-
/**
|
|
252
|
-
* @deprecated use `transformers` instead
|
|
253
|
-
*/
|
|
254
|
-
attachSeparator?: (node: Separator) => Separator;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
291
|
interface PageTreeBuilderContext<Page extends PageData = PageData, Meta extends MetaData = MetaData> {
|
|
258
292
|
/**
|
|
259
293
|
* @internal resolve paths without extensions
|
|
260
294
|
*/
|
|
261
295
|
resolveName: (name: string, format: 'meta' | 'page') => string;
|
|
262
|
-
options: BaseOptions
|
|
296
|
+
options: BaseOptions;
|
|
263
297
|
transformers: PageTreeTransformer<Page, Meta>[];
|
|
264
|
-
builder: PageTreeBuilder
|
|
298
|
+
builder: PageTreeBuilder;
|
|
265
299
|
storage: ContentStorage<Page, Meta>;
|
|
266
300
|
getUrl: UrlFn;
|
|
267
301
|
storages?: Record<string, ContentStorage<Page, Meta>>;
|
|
268
302
|
locale?: string;
|
|
269
303
|
visitedPaths: Set<string>;
|
|
270
304
|
}
|
|
271
|
-
interface PageTreeTransformer<Page extends PageData =
|
|
305
|
+
interface PageTreeTransformer<Page extends PageData = PageData, Meta extends MetaData = MetaData> {
|
|
272
306
|
name?: string;
|
|
273
307
|
file?: (this: PageTreeBuilderContext<Page, Meta>, node: Item, filePath?: string) => Item;
|
|
274
308
|
folder?: (this: PageTreeBuilderContext<Page, Meta>, node: Folder, folderPath: string, metaPath?: string) => Folder;
|
|
275
309
|
separator?: (this: PageTreeBuilderContext<Page, Meta>, node: Separator) => Separator;
|
|
276
310
|
root?: (this: PageTreeBuilderContext<Page, Meta>, node: Root) => Root;
|
|
277
311
|
}
|
|
278
|
-
interface BaseOptions
|
|
312
|
+
interface BaseOptions {
|
|
313
|
+
id?: string;
|
|
279
314
|
/**
|
|
280
315
|
* Remove references to the file path of original nodes (`$ref`)
|
|
281
316
|
*
|
|
282
317
|
* @defaultValue false
|
|
283
318
|
*/
|
|
284
319
|
noRef?: boolean;
|
|
285
|
-
|
|
286
|
-
resolveIcon?: (icon: string | undefined) => ReactNode | undefined;
|
|
320
|
+
plugins?: LoaderPlugin[];
|
|
287
321
|
/**
|
|
288
322
|
* generate fallback page tree
|
|
289
323
|
*
|
|
@@ -291,19 +325,17 @@ interface BaseOptions<Page extends PageData = PageData, Meta extends MetaData =
|
|
|
291
325
|
*/
|
|
292
326
|
generateFallback?: boolean;
|
|
293
327
|
}
|
|
294
|
-
interface PageTreeBuilder
|
|
295
|
-
build: (options: BaseOptions
|
|
296
|
-
|
|
297
|
-
storage: ContentStorage<Page, Meta>;
|
|
328
|
+
interface PageTreeBuilder {
|
|
329
|
+
build: (options: BaseOptions & {
|
|
330
|
+
storage: ContentStorage;
|
|
298
331
|
}) => Root;
|
|
299
332
|
/**
|
|
300
333
|
* Build page tree and fallback to the default language if the localized page doesn't exist
|
|
301
334
|
*/
|
|
302
|
-
buildI18n: (options: BaseOptions
|
|
303
|
-
|
|
304
|
-
storages: Record<string, ContentStorage<Page, Meta>>;
|
|
335
|
+
buildI18n: (options: BaseOptions & {
|
|
336
|
+
storages: Record<string, ContentStorage>;
|
|
305
337
|
}) => Record<string, Root>;
|
|
306
338
|
}
|
|
307
339
|
declare function createPageTreeBuilder(getUrl: UrlFn): PageTreeBuilder;
|
|
308
340
|
|
|
309
|
-
export { type BaseOptions, type ContentStorage, type FileInfo, FileSystem, type FolderInfo, type InferMetaType, type InferPageType, type LanguageEntry, type LoadOptions, type LoaderConfig, type LoaderOptions, type LoaderOutput, type Meta, type MetaData, type MetaFile, type Page, type PageData, type PageFile, type PageTreeBuilder, type PageTreeBuilderContext, type PageTreeTransformer, type Source, type SourceConfig, type Transformer, type UrlFn, type VirtualFile, createGetUrl, createPageTreeBuilder, getSlugs, loadFiles, loader, parseFilePath, parseFolderPath };
|
|
341
|
+
export { type BaseOptions, type ContentStorage, type FileInfo, FileSystem, type FolderInfo, type InferMetaType, type InferPageType, type LanguageEntry, type LoadOptions, type LoaderConfig, type LoaderOptions, type LoaderOutput, type LoaderPlugin, type LoaderPlugins, type Meta, type MetaData, type MetaFile, type Page, type PageData, type PageFile, type PageTreeBuilder, type PageTreeBuilderContext, type PageTreeTransformer, type Source, type SourceConfig, type Transformer, type UrlFn, type VirtualFile, buildPlugins, createGetUrl, createPageTreeBuilder, getSlugs, loadFiles, loader, parseFilePath, parseFolderPath };
|
package/dist/source/index.js
CHANGED
|
@@ -13,36 +13,6 @@ import {
|
|
|
13
13
|
} from "../chunk-PFNP6PEB.js";
|
|
14
14
|
import "../chunk-JSBRDJBE.js";
|
|
15
15
|
|
|
16
|
-
// src/source/page-tree/legacy.ts
|
|
17
|
-
function legacyTransformer(transformer) {
|
|
18
|
-
return {
|
|
19
|
-
file(node, file) {
|
|
20
|
-
if (!transformer.attachFile) return node;
|
|
21
|
-
const content = file ? this.storage.read(file) : void 0;
|
|
22
|
-
return transformer.attachFile(
|
|
23
|
-
node,
|
|
24
|
-
content?.format === "page" ? content : void 0
|
|
25
|
-
);
|
|
26
|
-
},
|
|
27
|
-
folder(node, folderPath, metaPath) {
|
|
28
|
-
if (!transformer.attachFolder) return node;
|
|
29
|
-
const files = this.storage.readDir(folderPath) ?? [];
|
|
30
|
-
const meta = metaPath ? this.storage.read(metaPath) : void 0;
|
|
31
|
-
return transformer.attachFolder(
|
|
32
|
-
node,
|
|
33
|
-
{
|
|
34
|
-
children: files.flatMap((file) => this.storage.read(file) ?? [])
|
|
35
|
-
},
|
|
36
|
-
meta?.format === "meta" ? meta : void 0
|
|
37
|
-
);
|
|
38
|
-
},
|
|
39
|
-
separator(node) {
|
|
40
|
-
if (!transformer.attachSeparator) return node;
|
|
41
|
-
return transformer.attachSeparator(node);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
16
|
// src/source/page-tree/transformer-fallback.ts
|
|
47
17
|
function transformerFallback() {
|
|
48
18
|
const addedFiles = /* @__PURE__ */ new Set();
|
|
@@ -105,13 +75,13 @@ function buildAll(paths, ctx, reversed = false) {
|
|
|
105
75
|
}
|
|
106
76
|
function resolveFolderItem(folderPath, item, ctx, idx) {
|
|
107
77
|
if (item === rest || item === restReversed) return item;
|
|
108
|
-
const {
|
|
78
|
+
const { resolveName } = ctx;
|
|
109
79
|
let match = separator.exec(item);
|
|
110
80
|
if (match?.groups) {
|
|
111
81
|
let node = {
|
|
112
82
|
$id: `${folderPath}#${idx}`,
|
|
113
83
|
type: "separator",
|
|
114
|
-
icon:
|
|
84
|
+
icon: match.groups.icon,
|
|
115
85
|
name: match.groups.name
|
|
116
86
|
};
|
|
117
87
|
for (const transformer of ctx.transformers) {
|
|
@@ -126,7 +96,7 @@ function resolveFolderItem(folderPath, item, ctx, idx) {
|
|
|
126
96
|
const isRelative = url.startsWith("/") || url.startsWith("#") || url.startsWith(".");
|
|
127
97
|
let node = {
|
|
128
98
|
type: "page",
|
|
129
|
-
icon
|
|
99
|
+
icon,
|
|
130
100
|
name,
|
|
131
101
|
url,
|
|
132
102
|
external: !isRelative
|
|
@@ -203,7 +173,7 @@ function buildFolderNode(folderPath, isGlobalRoot, ctx) {
|
|
|
203
173
|
let node = {
|
|
204
174
|
type: "folder",
|
|
205
175
|
name,
|
|
206
|
-
icon:
|
|
176
|
+
icon: meta?.data.icon ?? index?.icon,
|
|
207
177
|
root: meta?.data.root,
|
|
208
178
|
defaultOpen: meta?.data.defaultOpen,
|
|
209
179
|
description: meta?.data.description,
|
|
@@ -230,7 +200,7 @@ function buildFileNode(path, ctx) {
|
|
|
230
200
|
type: "page",
|
|
231
201
|
name: title ?? pathToName(basename(path, extname(path))),
|
|
232
202
|
description,
|
|
233
|
-
icon
|
|
203
|
+
icon,
|
|
234
204
|
url: getUrl(page.slugs, locale),
|
|
235
205
|
$ref: !options.noRef ? {
|
|
236
206
|
file: path
|
|
@@ -257,9 +227,9 @@ function build(id, ctx) {
|
|
|
257
227
|
}
|
|
258
228
|
function createPageTreeBuilder(getUrl) {
|
|
259
229
|
function getTransformers(options, generateFallback) {
|
|
260
|
-
const transformers = [
|
|
261
|
-
|
|
262
|
-
transformers.push(
|
|
230
|
+
const transformers = [];
|
|
231
|
+
for (const plugin of options.plugins ?? []) {
|
|
232
|
+
if (plugin.transformPageTree) transformers.push(plugin.transformPageTree);
|
|
263
233
|
}
|
|
264
234
|
if (generateFallback) {
|
|
265
235
|
transformers.push(transformerFallback());
|
|
@@ -401,7 +371,7 @@ var parsers = {
|
|
|
401
371
|
}
|
|
402
372
|
};
|
|
403
373
|
function loadFiles(files, options, i18n) {
|
|
404
|
-
const { buildFile,
|
|
374
|
+
const { buildFile, plugins = [] } = options;
|
|
405
375
|
const parser = parsers[i18n.parser ?? "dot"];
|
|
406
376
|
const storages = {};
|
|
407
377
|
const normalized = files.map(
|
|
@@ -424,11 +394,11 @@ function loadFiles(files, options, i18n) {
|
|
|
424
394
|
const [path, locale = i18n.defaultLanguage] = parser(item.path);
|
|
425
395
|
if (locale === lang) storage.write(path, item);
|
|
426
396
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
397
|
+
const context = {
|
|
398
|
+
storage
|
|
399
|
+
};
|
|
400
|
+
for (const plugin of plugins) {
|
|
401
|
+
plugin.transformStorage?.(context);
|
|
432
402
|
}
|
|
433
403
|
storages[lang] = storage;
|
|
434
404
|
}
|
|
@@ -442,6 +412,114 @@ function normalizePath(path) {
|
|
|
442
412
|
return segments.join("/");
|
|
443
413
|
}
|
|
444
414
|
|
|
415
|
+
// src/source/plugins/index.ts
|
|
416
|
+
function buildPlugins(plugins) {
|
|
417
|
+
return plugins;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// src/source/plugins/slugs.ts
|
|
421
|
+
function slugsPlugin(slugsFn) {
|
|
422
|
+
function isIndex(file) {
|
|
423
|
+
return basename(file, extname(file)) === "index";
|
|
424
|
+
}
|
|
425
|
+
return {
|
|
426
|
+
transformStorage({ storage }) {
|
|
427
|
+
const indexFiles = /* @__PURE__ */ new Set();
|
|
428
|
+
const taken = /* @__PURE__ */ new Set();
|
|
429
|
+
const autoIndex = slugsFn === void 0;
|
|
430
|
+
for (const path of storage.getFiles()) {
|
|
431
|
+
const file = storage.read(path);
|
|
432
|
+
if (!file || file.format !== "page" || file.slugs) continue;
|
|
433
|
+
if (isIndex(path) && autoIndex) {
|
|
434
|
+
indexFiles.add(path);
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
file.slugs = slugsFn ? slugsFn(parseFilePath(path)) : getSlugs(path);
|
|
438
|
+
const key = file.slugs.join("/");
|
|
439
|
+
if (taken.has(key)) throw new Error("Duplicated slugs");
|
|
440
|
+
taken.add(key);
|
|
441
|
+
}
|
|
442
|
+
for (const path of indexFiles) {
|
|
443
|
+
const file = storage.read(path);
|
|
444
|
+
if (file?.format !== "page") continue;
|
|
445
|
+
file.slugs = getSlugs(path);
|
|
446
|
+
if (taken.has(file.slugs.join("/"))) file.slugs.push("index");
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// src/source/plugins/compat.ts
|
|
453
|
+
function compatPlugin(loader2, {
|
|
454
|
+
attachFile,
|
|
455
|
+
attachSeparator,
|
|
456
|
+
attachFolder,
|
|
457
|
+
transformers
|
|
458
|
+
}) {
|
|
459
|
+
const chunk = [];
|
|
460
|
+
chunk.push({
|
|
461
|
+
transformPageTree: {
|
|
462
|
+
file(node, file) {
|
|
463
|
+
if (!attachFile) return node;
|
|
464
|
+
const content = file ? this.storage.read(file) : void 0;
|
|
465
|
+
return attachFile(
|
|
466
|
+
node,
|
|
467
|
+
content?.format === "page" ? content : void 0
|
|
468
|
+
);
|
|
469
|
+
},
|
|
470
|
+
folder(node, folderPath, metaPath) {
|
|
471
|
+
if (!attachFolder) return node;
|
|
472
|
+
const files = this.storage.readDir(folderPath) ?? [];
|
|
473
|
+
const meta = metaPath ? this.storage.read(metaPath) : void 0;
|
|
474
|
+
return attachFolder(
|
|
475
|
+
node,
|
|
476
|
+
{
|
|
477
|
+
children: files.flatMap((file) => this.storage.read(file) ?? [])
|
|
478
|
+
},
|
|
479
|
+
meta?.format === "meta" ? meta : void 0
|
|
480
|
+
);
|
|
481
|
+
},
|
|
482
|
+
separator(node) {
|
|
483
|
+
if (!attachSeparator) return node;
|
|
484
|
+
return attachSeparator(node);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
for (const transformer of loader2.transformers ?? []) {
|
|
489
|
+
chunk.push(fromStorageTransformer(transformer));
|
|
490
|
+
}
|
|
491
|
+
for (const transformer of transformers ?? []) {
|
|
492
|
+
chunk.push(fromPageTreeTransformer(transformer));
|
|
493
|
+
}
|
|
494
|
+
return chunk;
|
|
495
|
+
}
|
|
496
|
+
function fromPageTreeTransformer(transformer) {
|
|
497
|
+
return {
|
|
498
|
+
transformPageTree: transformer
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
function fromStorageTransformer(transformer) {
|
|
502
|
+
return {
|
|
503
|
+
transformStorage: transformer
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// src/source/plugins/icon.ts
|
|
508
|
+
function iconPlugin(resolveIcon) {
|
|
509
|
+
function replaceIcon(node) {
|
|
510
|
+
if (node.icon === void 0 || typeof node.icon === "string")
|
|
511
|
+
node.icon = resolveIcon(node.icon);
|
|
512
|
+
return node;
|
|
513
|
+
}
|
|
514
|
+
return {
|
|
515
|
+
transformPageTree: {
|
|
516
|
+
file: replaceIcon,
|
|
517
|
+
folder: replaceIcon,
|
|
518
|
+
separator: replaceIcon
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
|
|
445
523
|
// src/source/loader.ts
|
|
446
524
|
function indexPages(storages, getUrl) {
|
|
447
525
|
const result = {
|
|
@@ -500,40 +578,20 @@ function createOutput(options) {
|
|
|
500
578
|
if (!options.url && !options.baseUrl) {
|
|
501
579
|
console.warn("`loader()` now requires a `baseUrl` option to be defined.");
|
|
502
580
|
}
|
|
503
|
-
const {
|
|
504
|
-
source,
|
|
505
|
-
baseUrl = "/",
|
|
506
|
-
i18n,
|
|
507
|
-
slugs: slugsFn,
|
|
508
|
-
url: urlFn,
|
|
509
|
-
transformers = []
|
|
510
|
-
} = options;
|
|
581
|
+
const { source, baseUrl = "/", i18n, slugs: slugsFn, url: urlFn } = options;
|
|
511
582
|
const getUrl = urlFn ? (...args) => normalizeUrl(urlFn(...args)) : createGetUrl(baseUrl, i18n);
|
|
512
583
|
const defaultLanguage = i18n?.defaultLanguage ?? "";
|
|
513
584
|
const files = loadSource(source);
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
}
|
|
525
|
-
file.slugs = slugsFn ? slugsFn(parseFilePath(path)) : getSlugs(path);
|
|
526
|
-
const key = file.slugs.join("/");
|
|
527
|
-
if (taken.has(key)) throw new Error("Duplicated slugs");
|
|
528
|
-
taken.add(key);
|
|
529
|
-
}
|
|
530
|
-
for (const path of indexFiles) {
|
|
531
|
-
const file = storage.read(path);
|
|
532
|
-
if (file?.format !== "page") continue;
|
|
533
|
-
file.slugs = getSlugs(path);
|
|
534
|
-
if (taken.has(file.slugs.join("/"))) file.slugs.push("index");
|
|
535
|
-
}
|
|
536
|
-
};
|
|
585
|
+
const plugins = [slugsPlugin(slugsFn)];
|
|
586
|
+
if (options.icon) {
|
|
587
|
+
plugins.push(iconPlugin(options.icon));
|
|
588
|
+
}
|
|
589
|
+
if (options.plugins) {
|
|
590
|
+
plugins.push(...buildPlugins(options.plugins));
|
|
591
|
+
}
|
|
592
|
+
if (options.pageTree) {
|
|
593
|
+
plugins.push(...compatPlugin(options, options.pageTree));
|
|
594
|
+
}
|
|
537
595
|
const storages = loadFiles(
|
|
538
596
|
files,
|
|
539
597
|
{
|
|
@@ -554,7 +612,7 @@ function createOutput(options) {
|
|
|
554
612
|
data: file.data
|
|
555
613
|
};
|
|
556
614
|
},
|
|
557
|
-
|
|
615
|
+
plugins
|
|
558
616
|
},
|
|
559
617
|
i18n ?? {
|
|
560
618
|
defaultLanguage,
|
|
@@ -570,7 +628,7 @@ function createOutput(options) {
|
|
|
570
628
|
get pageTree() {
|
|
571
629
|
pageTree ??= builder.buildI18n({
|
|
572
630
|
storages,
|
|
573
|
-
|
|
631
|
+
plugins,
|
|
574
632
|
...options.pageTree
|
|
575
633
|
});
|
|
576
634
|
return i18n ? pageTree : pageTree[defaultLanguage];
|
|
@@ -599,10 +657,12 @@ function createOutput(options) {
|
|
|
599
657
|
hash
|
|
600
658
|
};
|
|
601
659
|
},
|
|
602
|
-
getPages(language
|
|
660
|
+
getPages(language) {
|
|
603
661
|
const pages = [];
|
|
604
662
|
for (const [key, value] of walker.pages.entries()) {
|
|
605
|
-
if (key.startsWith(`${language}.`))
|
|
663
|
+
if (language === void 0 || key.startsWith(`${language}.`)) {
|
|
664
|
+
pages.push(value);
|
|
665
|
+
}
|
|
606
666
|
}
|
|
607
667
|
return pages;
|
|
608
668
|
},
|
|
@@ -676,9 +736,6 @@ function fileToPage(file, getUrl, locale) {
|
|
|
676
736
|
};
|
|
677
737
|
}
|
|
678
738
|
var GroupRegex = /^\(.+\)$/;
|
|
679
|
-
function isIndex(file) {
|
|
680
|
-
return basename(file, extname(file)) === "index";
|
|
681
|
-
}
|
|
682
739
|
function getSlugs(file) {
|
|
683
740
|
if (typeof file !== "string") return getSlugs(file.path);
|
|
684
741
|
const dir = dirname(file);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fumadocs-core",
|
|
3
|
-
"version": "15.8.
|
|
3
|
+
"version": "15.8.1",
|
|
4
4
|
"description": "The library for building a documentation website in Next.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NextJs",
|
|
@@ -114,21 +114,21 @@
|
|
|
114
114
|
},
|
|
115
115
|
"devDependencies": {
|
|
116
116
|
"@mdx-js/mdx": "^3.1.1",
|
|
117
|
-
"@mixedbread/sdk": "^0.
|
|
117
|
+
"@mixedbread/sdk": "^0.29.0",
|
|
118
118
|
"@oramacloud/client": "^2.1.4",
|
|
119
|
-
"@tanstack/react-router": "^1.132.
|
|
119
|
+
"@tanstack/react-router": "^1.132.7",
|
|
120
120
|
"@types/estree-jsx": "^1.0.5",
|
|
121
121
|
"@types/hast": "^3.0.4",
|
|
122
122
|
"@types/mdast": "^4.0.3",
|
|
123
123
|
"@types/negotiator": "^0.6.4",
|
|
124
124
|
"@types/node": "24.5.2",
|
|
125
|
-
"@types/react": "^19.1.
|
|
125
|
+
"@types/react": "^19.1.14",
|
|
126
126
|
"@types/react-dom": "^19.1.9",
|
|
127
|
-
"algoliasearch": "5.
|
|
127
|
+
"algoliasearch": "5.39.0",
|
|
128
128
|
"mdast-util-mdx-jsx": "^3.2.0",
|
|
129
129
|
"mdast-util-mdxjs-esm": "^2.0.1",
|
|
130
130
|
"next": "^15.5.4",
|
|
131
|
-
"react-router": "^7.9.
|
|
131
|
+
"react-router": "^7.9.3",
|
|
132
132
|
"remark-mdx": "^3.1.1",
|
|
133
133
|
"remove-markdown": "^0.6.2",
|
|
134
134
|
"typescript": "^5.9.2",
|