fumadocs-mdx 11.10.0 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/bin.cjs +953 -0
  2. package/dist/bin.d.cts +1 -0
  3. package/dist/bin.d.ts +1 -0
  4. package/dist/bin.js +16 -0
  5. package/dist/{browser-B2G8uAF2.d.cts → browser-D5lvL8vv.d.ts} +51 -4
  6. package/dist/{browser-DrH7tKRi.d.ts → browser-DjWADqp8.d.cts} +51 -4
  7. package/dist/bun/index.cjs +129 -109
  8. package/dist/bun/index.js +9 -6
  9. package/dist/chunk-3M4SHY6K.js +80 -0
  10. package/dist/chunk-6Y5JDZHD.js +65 -0
  11. package/dist/{chunk-NUDEC6C5.js → chunk-AUOOMFAI.js} +28 -22
  12. package/dist/chunk-IQAEAI4P.js +66 -0
  13. package/dist/{chunk-5XJM5RPV.js → chunk-KGUBBRL6.js} +13 -13
  14. package/dist/{chunk-SVTXMVLQ.js → chunk-KTDVTBMH.js} +1 -1
  15. package/dist/chunk-POXTQZ4D.js +60 -0
  16. package/dist/chunk-SWNOXPYJ.js +142 -0
  17. package/dist/{chunk-COQ4VMK2.js → chunk-TLD6JMT6.js} +28 -61
  18. package/dist/{chunk-NVX3U5YE.js → chunk-VXEBLM4X.js} +2 -2
  19. package/dist/{chunk-QVZ7JH4H.js → chunk-YC25YEBF.js} +1 -1
  20. package/dist/chunk-ZLCSVXCD.js +10 -0
  21. package/dist/config/index.cjs +18 -97
  22. package/dist/config/index.d.cts +1 -1
  23. package/dist/config/index.d.ts +1 -1
  24. package/dist/config/index.js +48 -9
  25. package/dist/{define-BH4bnHQl.d.cts → define--6HQ1ehX.d.cts} +18 -3
  26. package/dist/{define-BH4bnHQl.d.ts → define--6HQ1ehX.d.ts} +18 -3
  27. package/dist/loader-mdx.cjs +127 -139
  28. package/dist/loader-mdx.js +7 -6
  29. package/dist/next/index.cjs +44 -269
  30. package/dist/next/index.js +30 -46
  31. package/dist/node/loader.cjs +131 -143
  32. package/dist/node/loader.js +7 -6
  33. package/dist/postinstall-U7VROOY7.js +9 -0
  34. package/dist/{mdx-options-T73E4LQB.js → preset-WFEORCAB.js} +1 -1
  35. package/dist/runtime/{async.cjs → next/async.cjs} +202 -154
  36. package/dist/runtime/{async.d.cts → next/async.d.cts} +3 -3
  37. package/dist/runtime/{async.d.ts → next/async.d.ts} +3 -3
  38. package/dist/runtime/next/async.js +92 -0
  39. package/dist/{index.cjs → runtime/next/index.cjs} +35 -26
  40. package/dist/runtime/next/index.d.cts +30 -0
  41. package/dist/runtime/next/index.d.ts +30 -0
  42. package/dist/{index.js → runtime/next/index.js} +2 -1
  43. package/dist/runtime/vite/browser.d.cts +2 -3
  44. package/dist/runtime/vite/browser.d.ts +2 -3
  45. package/dist/runtime/vite/server.cjs +67 -21
  46. package/dist/runtime/vite/server.d.cts +14 -28
  47. package/dist/runtime/vite/server.d.ts +14 -28
  48. package/dist/runtime/vite/server.js +61 -21
  49. package/dist/shared-0QIuV0XZ.d.ts +70 -0
  50. package/dist/shared-CqgMnt9h.d.cts +70 -0
  51. package/dist/{types-DN9KrG7R.d.ts → types-DLIAvrgC.d.ts} +6 -32
  52. package/dist/{types-DT83Ijs6.d.cts → types-Dl8HLbm5.d.cts} +6 -32
  53. package/dist/vite/index.cjs +201 -123
  54. package/dist/vite/index.d.cts +4 -1
  55. package/dist/vite/index.d.ts +4 -1
  56. package/dist/vite/index.js +13 -9
  57. package/package.json +11 -17
  58. package/bin.js +0 -5
  59. package/dist/build-mdx-DnC1jKvn.d.cts +0 -46
  60. package/dist/build-mdx-DnC1jKvn.d.ts +0 -46
  61. package/dist/chunk-2HKRTQYP.js +0 -154
  62. package/dist/chunk-GBMFGEC7.js +0 -57
  63. package/dist/chunk-QQWCBFFE.js +0 -40
  64. package/dist/chunk-SMSNZ6N5.js +0 -155
  65. package/dist/config/zod-3.cjs +0 -422
  66. package/dist/config/zod-3.d.cts +0 -53
  67. package/dist/config/zod-3.d.ts +0 -53
  68. package/dist/config/zod-3.js +0 -40
  69. package/dist/index.d.cts +0 -26
  70. package/dist/index.d.ts +0 -26
  71. package/dist/runtime/async.js +0 -72
package/dist/bin.cjs ADDED
@@ -0,0 +1,953 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+
33
+ // src/mdx/preset.ts
34
+ var preset_exports = {};
35
+ __export(preset_exports, {
36
+ getDefaultMDXOptions: () => getDefaultMDXOptions
37
+ });
38
+ function pluginOption(def, options = []) {
39
+ const list = def(Array.isArray(options) ? options : []).filter(
40
+ Boolean
41
+ );
42
+ if (typeof options === "function") {
43
+ return options(list);
44
+ }
45
+ return list;
46
+ }
47
+ function getDefaultMDXOptions({
48
+ valueToExport = [],
49
+ rehypeCodeOptions,
50
+ remarkImageOptions,
51
+ remarkHeadingOptions,
52
+ remarkStructureOptions,
53
+ remarkCodeTabOptions,
54
+ remarkNpmOptions,
55
+ _withoutBundler = false,
56
+ ...mdxOptions
57
+ }) {
58
+ const remarkPlugins = pluginOption(
59
+ (v) => [
60
+ plugins.remarkGfm,
61
+ [
62
+ plugins.remarkHeading,
63
+ {
64
+ generateToc: false,
65
+ ...remarkHeadingOptions
66
+ }
67
+ ],
68
+ remarkImageOptions !== false && [
69
+ plugins.remarkImage,
70
+ {
71
+ ...remarkImageOptions,
72
+ useImport: _withoutBundler ? false : remarkImageOptions?.useImport
73
+ }
74
+ ],
75
+ "remarkCodeTab" in plugins && remarkCodeTabOptions !== false && [
76
+ plugins.remarkCodeTab,
77
+ remarkCodeTabOptions
78
+ ],
79
+ "remarkNpm" in plugins && remarkNpmOptions !== false && [plugins.remarkNpm, remarkNpmOptions],
80
+ ...v,
81
+ remarkStructureOptions !== false && [
82
+ plugins.remarkStructure,
83
+ remarkStructureOptions
84
+ ],
85
+ () => {
86
+ return (_, file) => {
87
+ file.data["mdx-export"] ??= [];
88
+ for (const name of valueToExport) {
89
+ if (name in file.data)
90
+ file.data["mdx-export"].push({ name, value: file.data[name] });
91
+ }
92
+ };
93
+ }
94
+ ],
95
+ mdxOptions.remarkPlugins
96
+ );
97
+ const rehypePlugins = pluginOption(
98
+ (v) => [
99
+ rehypeCodeOptions !== false && [plugins.rehypeCode, rehypeCodeOptions],
100
+ ...v,
101
+ plugins.rehypeToc
102
+ ],
103
+ mdxOptions.rehypePlugins
104
+ );
105
+ return {
106
+ ...mdxOptions,
107
+ outputFormat: _withoutBundler ? "function-body" : mdxOptions.outputFormat,
108
+ remarkPlugins,
109
+ rehypePlugins
110
+ };
111
+ }
112
+ var plugins;
113
+ var init_preset = __esm({
114
+ "src/mdx/preset.ts"() {
115
+ "use strict";
116
+ plugins = __toESM(require("fumadocs-core/mdx-plugins"), 1);
117
+ }
118
+ });
119
+
120
+ // src/config/build.ts
121
+ function buildConfig(config) {
122
+ const collections = /* @__PURE__ */ new Map();
123
+ let globalConfig = {};
124
+ for (const [k, v] of Object.entries(config)) {
125
+ if (!v) {
126
+ continue;
127
+ }
128
+ if (typeof v === "object" && "type" in v) {
129
+ if (v.type === "docs") {
130
+ collections.set(k, v);
131
+ continue;
132
+ }
133
+ if (v.type === "doc" || v.type === "meta") {
134
+ collections.set(k, v);
135
+ continue;
136
+ }
137
+ }
138
+ if (k === "default" && v) {
139
+ globalConfig = v;
140
+ continue;
141
+ }
142
+ throw new Error(
143
+ `Unknown export "${k}", you can only export collections from source configuration file.`
144
+ );
145
+ }
146
+ const mdxOptionsCache = /* @__PURE__ */ new Map();
147
+ return {
148
+ global: globalConfig,
149
+ collections,
150
+ async getDefaultMDXOptions(mode = "default") {
151
+ const cached = mdxOptionsCache.get(mode);
152
+ if (cached) return cached;
153
+ const input = this.global.mdxOptions;
154
+ async function uncached() {
155
+ const options = typeof input === "function" ? await input() : input;
156
+ const { getDefaultMDXOptions: getDefaultMDXOptions2 } = await Promise.resolve().then(() => (init_preset(), preset_exports));
157
+ if (options?.preset === "minimal") return options;
158
+ return getDefaultMDXOptions2({
159
+ ...options,
160
+ _withoutBundler: mode === "remote"
161
+ });
162
+ }
163
+ const result = uncached();
164
+ mdxOptionsCache.set(mode, result);
165
+ return result;
166
+ }
167
+ };
168
+ }
169
+ var init_build = __esm({
170
+ "src/config/build.ts"() {
171
+ "use strict";
172
+ }
173
+ });
174
+
175
+ // src/utils/config.ts
176
+ function findConfigFile() {
177
+ return path.resolve("source.config.ts");
178
+ }
179
+ async function compileConfig(configPath, outDir) {
180
+ const { build } = await import("esbuild");
181
+ const transformed = await build({
182
+ entryPoints: [{ in: configPath, out: "source.config" }],
183
+ bundle: true,
184
+ outdir: outDir,
185
+ target: "node20",
186
+ write: true,
187
+ platform: "node",
188
+ format: "esm",
189
+ packages: "external",
190
+ outExtension: {
191
+ ".js": ".mjs"
192
+ },
193
+ allowOverwrite: true
194
+ });
195
+ if (transformed.errors.length > 0) {
196
+ throw new Error("failed to compile configuration file");
197
+ }
198
+ }
199
+ async function loadConfig(configPath, outDir, hash, build = false) {
200
+ if (cache && cache.hash === hash) {
201
+ return await cache.config;
202
+ }
203
+ if (build) await compileConfig(configPath, outDir);
204
+ const url = (0, import_node_url.pathToFileURL)(path.resolve(outDir, "source.config.mjs"));
205
+ const config = import(`${url.href}?hash=${hash}`).then((loaded) => {
206
+ return buildConfig(
207
+ // every call to `loadConfig` will cause the previous cache to be ignored
208
+ loaded
209
+ );
210
+ });
211
+ if (hash) cache = { config, hash };
212
+ return await config;
213
+ }
214
+ async function getConfigHash(configPath) {
215
+ const stats = await fs.stat(configPath).catch(() => void 0);
216
+ if (stats) {
217
+ return stats.mtime.getTime().toString();
218
+ }
219
+ throw new Error("Cannot find config file");
220
+ }
221
+ var fs, path, import_node_url, cache;
222
+ var init_config = __esm({
223
+ "src/utils/config.ts"() {
224
+ "use strict";
225
+ fs = __toESM(require("fs/promises"), 1);
226
+ path = __toESM(require("path"), 1);
227
+ import_node_url = require("url");
228
+ init_build();
229
+ cache = null;
230
+ }
231
+ });
232
+
233
+ // src/utils/validation.ts
234
+ async function validate(schema, data, context, errorMessage) {
235
+ if (typeof schema === "function" && !("~standard" in schema)) {
236
+ schema = schema(context);
237
+ }
238
+ if ("~standard" in schema) {
239
+ const result = await schema["~standard"].validate(
240
+ data
241
+ );
242
+ if (result.issues) {
243
+ throw new ValidationError(errorMessage, result.issues);
244
+ }
245
+ return result.value;
246
+ }
247
+ return data;
248
+ }
249
+ var import_picocolors, ValidationError;
250
+ var init_validation = __esm({
251
+ "src/utils/validation.ts"() {
252
+ "use strict";
253
+ import_picocolors = __toESM(require("picocolors"), 1);
254
+ ValidationError = class extends Error {
255
+ constructor(message, issues) {
256
+ super(
257
+ `${message}:
258
+ ${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
259
+ );
260
+ this.title = message;
261
+ this.issues = issues;
262
+ }
263
+ toStringFormatted() {
264
+ return [
265
+ import_picocolors.default.bold(`[MDX] ${this.title}:`),
266
+ ...this.issues.map(
267
+ (issue) => import_picocolors.default.redBright(
268
+ `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
269
+ )
270
+ )
271
+ ].join("\n");
272
+ }
273
+ };
274
+ }
275
+ });
276
+
277
+ // src/map/file-cache.ts
278
+ var import_lru_cache, map, fileCache;
279
+ var init_file_cache = __esm({
280
+ "src/map/file-cache.ts"() {
281
+ "use strict";
282
+ import_lru_cache = require("lru-cache");
283
+ map = new import_lru_cache.LRUCache({
284
+ max: 200
285
+ });
286
+ fileCache = {
287
+ read(namespace, path8) {
288
+ return map.get(`${namespace}.${path8}`);
289
+ },
290
+ write(namespace, path8, data) {
291
+ map.set(`${namespace}.${path8}`, data);
292
+ },
293
+ removeCache(path8) {
294
+ for (const key of map.keys()) {
295
+ const keyPath = key.slice(key.indexOf(".") + 1);
296
+ if (keyPath === path8) map.delete(key);
297
+ }
298
+ }
299
+ };
300
+ }
301
+ });
302
+
303
+ // src/utils/git-timestamp.ts
304
+ async function getGitTimestamp(file) {
305
+ const cached = cache2.get(file);
306
+ if (cached) return cached;
307
+ try {
308
+ const out = await (0, import_tinyexec.x)(
309
+ "git",
310
+ ["log", "-1", '--pretty="%ai"', import_node_path.default.relative(process.cwd(), file)],
311
+ {
312
+ throwOnError: true
313
+ }
314
+ );
315
+ const time = new Date(out.stdout);
316
+ cache2.set(file, time);
317
+ return time;
318
+ } catch {
319
+ return;
320
+ }
321
+ }
322
+ var import_node_path, import_tinyexec, cache2;
323
+ var init_git_timestamp = __esm({
324
+ "src/utils/git-timestamp.ts"() {
325
+ "use strict";
326
+ import_node_path = __toESM(require("path"), 1);
327
+ import_tinyexec = require("tinyexec");
328
+ cache2 = /* @__PURE__ */ new Map();
329
+ }
330
+ });
331
+
332
+ // src/utils/fuma-matter.ts
333
+ function fumaMatter(input) {
334
+ const output = { matter: "", data: {}, content: input };
335
+ const match = regex.exec(input);
336
+ if (!match) {
337
+ return output;
338
+ }
339
+ output.matter = match[0];
340
+ output.content = input.slice(match[0].length);
341
+ const loaded = (0, import_js_yaml.load)(match[1]);
342
+ output.data = loaded ?? {};
343
+ return output;
344
+ }
345
+ var import_js_yaml, regex;
346
+ var init_fuma_matter = __esm({
347
+ "src/utils/fuma-matter.ts"() {
348
+ "use strict";
349
+ import_js_yaml = require("js-yaml");
350
+ regex = /^---\r?\n(.+?)\r?\n---\r?\n/s;
351
+ }
352
+ });
353
+
354
+ // src/utils/import-formatter.ts
355
+ function getImportCode(info) {
356
+ const specifier = JSON.stringify(info.specifier);
357
+ if (info.type === "default") return `import ${info.name} from ${specifier}`;
358
+ if (info.type === "namespace")
359
+ return `import * as ${info.name} from ${specifier}`;
360
+ if (info.type === "named") {
361
+ const names = info.names.map(
362
+ (name) => Array.isArray(name) ? `${name[0]} as ${name[1]}` : name
363
+ );
364
+ return `import { ${names.join(", ")} } from ${specifier}`;
365
+ }
366
+ return `import ${specifier}`;
367
+ }
368
+ function toImportPath(file, config) {
369
+ const ext = import_node_path2.default.extname(file);
370
+ let filename;
371
+ if (ext === ".ts" && config.jsExtension) {
372
+ filename = file.substring(0, file.length - ext.length) + ".js";
373
+ } else if (ext === ".ts") {
374
+ filename = file.substring(0, file.length - ext.length);
375
+ } else {
376
+ filename = file;
377
+ }
378
+ let importPath;
379
+ if ("relativeTo" in config) {
380
+ importPath = import_node_path2.default.relative(config.relativeTo, filename);
381
+ if (!import_node_path2.default.isAbsolute(importPath) && !importPath.startsWith(".")) {
382
+ importPath = `./${importPath}`;
383
+ }
384
+ } else {
385
+ importPath = import_node_path2.default.resolve(filename);
386
+ }
387
+ return importPath.replaceAll(import_node_path2.default.sep, "/");
388
+ }
389
+ function ident(code, tab = 1) {
390
+ return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
391
+ }
392
+ var import_node_path2;
393
+ var init_import_formatter = __esm({
394
+ "src/utils/import-formatter.ts"() {
395
+ "use strict";
396
+ import_node_path2 = __toESM(require("path"), 1);
397
+ }
398
+ });
399
+
400
+ // src/utils/collections.ts
401
+ function getSupportedFormats(collection) {
402
+ return {
403
+ doc: ["mdx", "md"],
404
+ meta: ["json", "yaml"]
405
+ }[collection.type];
406
+ }
407
+ function getGlobPatterns(collection) {
408
+ if (collection.files) return collection.files;
409
+ return [`**/*.{${getSupportedFormats(collection).join(",")}}`];
410
+ }
411
+ function isFileSupported(filePath, collection) {
412
+ for (const format of getSupportedFormats(collection)) {
413
+ if (filePath.endsWith(`.${format}`)) return true;
414
+ }
415
+ return false;
416
+ }
417
+ var init_collections = __esm({
418
+ "src/utils/collections.ts"() {
419
+ "use strict";
420
+ }
421
+ });
422
+
423
+ // src/map/generate.ts
424
+ async function readFileWithCache(file) {
425
+ const cached = fileCache.read("read-file", file);
426
+ if (cached) return cached;
427
+ return (await fs2.readFile(file)).toString();
428
+ }
429
+ async function generateJS(configPath, config, importPath, configHash = false) {
430
+ let asyncInit = false;
431
+ const lines = [
432
+ getImportCode({
433
+ type: "named",
434
+ names: ["_runtime"],
435
+ specifier: "fumadocs-mdx"
436
+ }),
437
+ getImportCode({
438
+ type: "namespace",
439
+ specifier: toImportPath(configPath, importPath),
440
+ name: "_source"
441
+ })
442
+ ];
443
+ const entries = Array.from(config.collections.entries());
444
+ async function getDocEntries(collectionName, files) {
445
+ const items = files.map(async (file, i) => {
446
+ const importId = `${collectionName}_${i}`;
447
+ const params = [`collection=${collectionName}`];
448
+ if (configHash) {
449
+ params.push(`hash=${configHash}`);
450
+ }
451
+ lines.unshift(
452
+ getImportCode({
453
+ type: "namespace",
454
+ name: importId,
455
+ specifier: `${toImportPath(file.fullPath, importPath)}?${params.join("&")}`
456
+ })
457
+ );
458
+ return `{ info: ${JSON.stringify(file)}, data: ${importId} }`;
459
+ });
460
+ return Promise.all(items);
461
+ }
462
+ async function getMetaEntries(collection, files) {
463
+ const items = files.map(async (file) => {
464
+ const source = await readFileWithCache(file.fullPath).catch(() => "");
465
+ let data = source.length === 0 ? {} : parseMetaEntry(file.fullPath, source);
466
+ if (collection?.schema) {
467
+ data = await validate(
468
+ collection.schema,
469
+ data,
470
+ {
471
+ source,
472
+ path: file.fullPath
473
+ },
474
+ `invalid data in ${file.fullPath}`
475
+ );
476
+ }
477
+ return JSON.stringify({
478
+ info: file,
479
+ data
480
+ });
481
+ });
482
+ return Promise.all(items);
483
+ }
484
+ async function getAsyncEntries(collection, files) {
485
+ if (!asyncInit) {
486
+ lines.unshift(
487
+ getImportCode({
488
+ type: "named",
489
+ specifier: "fumadocs-mdx/runtime/async",
490
+ names: ["_runtimeAsync", "buildConfig"]
491
+ }),
492
+ "const _sourceConfig = buildConfig(_source)"
493
+ );
494
+ asyncInit = true;
495
+ }
496
+ const entries2 = files.map(async (file) => {
497
+ const parsed = fumaMatter(
498
+ await readFileWithCache(file.fullPath).catch(() => "")
499
+ );
500
+ let data = parsed.data;
501
+ if (collection.schema) {
502
+ data = await validate(
503
+ collection.schema,
504
+ parsed.data,
505
+ { path: file.fullPath, source: parsed.content },
506
+ `invalid frontmatter in ${file.fullPath}`
507
+ );
508
+ }
509
+ let lastModified;
510
+ if (config.global?.lastModifiedTime === "git") {
511
+ lastModified = await getGitTimestamp(file.fullPath);
512
+ }
513
+ return JSON.stringify({
514
+ info: file,
515
+ lastModified,
516
+ data,
517
+ content: { body: parsed.content, matter: parsed.matter }
518
+ });
519
+ });
520
+ return Promise.all(entries2);
521
+ }
522
+ const declares = entries.map(async ([k, collection]) => {
523
+ if (collection.type === "docs") {
524
+ const docs2 = await getCollectionFiles(collection.docs);
525
+ const metas = await getCollectionFiles(collection.meta);
526
+ const metaEntries = (await getMetaEntries(collection.meta, metas)).join(
527
+ ", "
528
+ );
529
+ if (collection.docs.async) {
530
+ const docsEntries2 = (await getAsyncEntries(collection.docs, docs2)).join(
531
+ ", "
532
+ );
533
+ return `export const ${k} = _runtimeAsync.docs<typeof _source.${k}>([${docsEntries2}], [${metaEntries}], "${k}", _sourceConfig)`;
534
+ }
535
+ const docsEntries = (await getDocEntries(k, docs2)).join(", ");
536
+ return `export const ${k} = _runtime.docs<typeof _source.${k}>([${docsEntries}], [${metaEntries}])`;
537
+ }
538
+ const files = await getCollectionFiles(collection);
539
+ if (collection.type === "doc" && collection.async) {
540
+ return `export const ${k} = _runtimeAsync.doc<typeof _source.${k}>([${(await getAsyncEntries(collection, files)).join(", ")}], "${k}", _sourceConfig)`;
541
+ }
542
+ return `export const ${k} = _runtime.${collection.type}<typeof _source.${k}>([${(await getDocEntries(k, files)).join(", ")}]);`;
543
+ });
544
+ const resolvedDeclares = await Promise.all(declares);
545
+ return [
546
+ `// @ts-nocheck -- skip type checking`,
547
+ ...lines,
548
+ ...resolvedDeclares
549
+ ].join("\n");
550
+ }
551
+ async function getCollectionFiles(collection) {
552
+ const files = /* @__PURE__ */ new Map();
553
+ const dirs = Array.isArray(collection.dir) ? collection.dir : [collection.dir];
554
+ const patterns = getGlobPatterns(collection);
555
+ await Promise.all(
556
+ dirs.map(async (dir) => {
557
+ const result = await (0, import_tinyglobby.glob)(patterns, {
558
+ cwd: path4.resolve(dir)
559
+ });
560
+ for (const item of result) {
561
+ if (!isFileSupported(item, collection)) continue;
562
+ const fullPath = path4.join(dir, item);
563
+ files.set(fullPath, {
564
+ path: item,
565
+ fullPath
566
+ });
567
+ }
568
+ })
569
+ );
570
+ return Array.from(files.values());
571
+ }
572
+ function parseMetaEntry(file, content) {
573
+ const extname2 = path4.extname(file);
574
+ try {
575
+ if (extname2 === ".json") return JSON.parse(content);
576
+ if (extname2 === ".yaml") return (0, import_js_yaml2.load)(content);
577
+ } catch (e) {
578
+ throw new Error(`Failed to parse meta file: ${file}.`, {
579
+ cause: e
580
+ });
581
+ }
582
+ throw new Error(`Unknown meta file format: ${extname2}, in ${file}.`);
583
+ }
584
+ var path4, fs2, import_tinyglobby, import_js_yaml2;
585
+ var init_generate = __esm({
586
+ "src/map/generate.ts"() {
587
+ "use strict";
588
+ path4 = __toESM(require("path"), 1);
589
+ fs2 = __toESM(require("fs/promises"), 1);
590
+ import_tinyglobby = require("tinyglobby");
591
+ init_validation();
592
+ init_file_cache();
593
+ import_js_yaml2 = require("js-yaml");
594
+ init_git_timestamp();
595
+ init_fuma_matter();
596
+ init_import_formatter();
597
+ init_collections();
598
+ }
599
+ });
600
+
601
+ // src/map/watcher.ts
602
+ var watcher_exports = {};
603
+ __export(watcher_exports, {
604
+ watcher: () => watcher
605
+ });
606
+ function watcher(configPath, config, ignored) {
607
+ const watcher2 = new import_chokidar.FSWatcher({
608
+ ignoreInitial: true,
609
+ persistent: true,
610
+ ignored
611
+ });
612
+ watcher2.add(configPath);
613
+ for (const collection of config.collections.values()) {
614
+ if (collection.type === "docs") {
615
+ watcher2.add(collection.docs.dir);
616
+ watcher2.add(collection.meta.dir);
617
+ } else {
618
+ watcher2.add(collection.dir);
619
+ }
620
+ }
621
+ return watcher2;
622
+ }
623
+ var import_chokidar;
624
+ var init_watcher = __esm({
625
+ "src/map/watcher.ts"() {
626
+ "use strict";
627
+ import_chokidar = require("chokidar");
628
+ }
629
+ });
630
+
631
+ // src/map/index.ts
632
+ async function start(dev, configPath, outDir) {
633
+ let configHash = await getConfigHash(configPath);
634
+ let config = await loadConfig(configPath, outDir, configHash, true);
635
+ const outPath = path5.resolve(outDir, `index.ts`);
636
+ async function updateMapFile() {
637
+ const start3 = performance.now();
638
+ try {
639
+ await fs3.writeFile(
640
+ outPath,
641
+ await generateJS(
642
+ configPath,
643
+ config,
644
+ { relativeTo: outDir },
645
+ configHash
646
+ )
647
+ );
648
+ } catch (err) {
649
+ if (err instanceof ValidationError) {
650
+ console.error(err.toStringFormatted());
651
+ } else {
652
+ console.error(err);
653
+ }
654
+ }
655
+ console.log(`[MDX] updated map file in ${performance.now() - start3}ms`);
656
+ }
657
+ await updateMapFile();
658
+ if (dev) {
659
+ const { watcher: watcher2 } = await Promise.resolve().then(() => (init_watcher(), watcher_exports));
660
+ const instance = watcher2(configPath, config, [outPath]);
661
+ instance.on("ready", () => {
662
+ console.log("[MDX] started dev server");
663
+ });
664
+ instance.on("all", (event, file) => {
665
+ if (typeof file !== "string") return;
666
+ const absolutePath = path5.resolve(file);
667
+ const onUpdate = async () => {
668
+ const isConfigFile = absolutePath === configPath;
669
+ if (isConfigFile) {
670
+ configHash = await getConfigHash(configPath);
671
+ config = await loadConfig(configPath, outDir, configHash, true);
672
+ }
673
+ if (event === "change") fileCache.removeCache(absolutePath);
674
+ await updateMapFile();
675
+ };
676
+ void onUpdate();
677
+ });
678
+ process.on("exit", () => {
679
+ console.log("[MDX] closing dev server");
680
+ void instance.close();
681
+ });
682
+ }
683
+ }
684
+ var path5, fs3;
685
+ var init_map = __esm({
686
+ "src/map/index.ts"() {
687
+ "use strict";
688
+ path5 = __toESM(require("path"), 1);
689
+ fs3 = __toESM(require("fs/promises"), 1);
690
+ init_config();
691
+ init_generate();
692
+ init_file_cache();
693
+ init_validation();
694
+ }
695
+ });
696
+
697
+ // src/next/create.ts
698
+ function createMDX({
699
+ configPath = findConfigFile(),
700
+ outDir = ".source"
701
+ } = {}) {
702
+ if (process.env._FUMADOCS_MDX !== "1") {
703
+ process.env._FUMADOCS_MDX = "1";
704
+ void start(process.env.NODE_ENV === "development", configPath, outDir);
705
+ }
706
+ return (nextConfig = {}) => {
707
+ const mdxLoaderOptions = {
708
+ configPath,
709
+ outDir
710
+ };
711
+ const turbo = {
712
+ ...nextConfig.experimental?.turbo,
713
+ ...nextConfig.turbopack,
714
+ rules: {
715
+ ...nextConfig.experimental?.turbo?.rules,
716
+ ...nextConfig.turbopack?.rules,
717
+ "*.{md,mdx}": {
718
+ loaders: [
719
+ {
720
+ loader: "fumadocs-mdx/loader-mdx",
721
+ options: mdxLoaderOptions
722
+ }
723
+ ],
724
+ as: "*.js"
725
+ }
726
+ }
727
+ };
728
+ const updated = {
729
+ ...nextConfig,
730
+ pageExtensions: nextConfig.pageExtensions ?? defaultPageExtensions,
731
+ webpack: (config, options) => {
732
+ config.resolve ||= {};
733
+ config.module ||= {};
734
+ config.module.rules ||= [];
735
+ config.module.rules.push({
736
+ test: /\.mdx?$/,
737
+ use: [
738
+ options.defaultLoaders.babel,
739
+ {
740
+ loader: "fumadocs-mdx/loader-mdx",
741
+ options: mdxLoaderOptions
742
+ }
743
+ ]
744
+ });
745
+ config.plugins ||= [];
746
+ return nextConfig.webpack?.(config, options) ?? config;
747
+ }
748
+ };
749
+ if (isTurboExperimental) {
750
+ updated.experimental = { ...updated.experimental, turbo };
751
+ } else {
752
+ updated.turbopack = turbo;
753
+ }
754
+ return updated;
755
+ };
756
+ }
757
+ var import_node_fs, defaultPageExtensions, isTurboExperimental;
758
+ var init_create = __esm({
759
+ "src/next/create.ts"() {
760
+ "use strict";
761
+ init_config();
762
+ init_map();
763
+ import_node_fs = require("fs");
764
+ defaultPageExtensions = ["mdx", "md", "jsx", "js", "tsx", "ts"];
765
+ try {
766
+ const content = (0, import_node_fs.readFileSync)("./node_modules/next/package.json").toString();
767
+ const version = JSON.parse(content).version;
768
+ isTurboExperimental = version.startsWith("15.0.") || version.startsWith("15.1.") || version.startsWith("15.2.");
769
+ } catch {
770
+ isTurboExperimental = false;
771
+ }
772
+ }
773
+ });
774
+
775
+ // src/next/index.ts
776
+ var next_exports = {};
777
+ __export(next_exports, {
778
+ createMDX: () => createMDX,
779
+ postInstall: () => postInstall,
780
+ start: () => start
781
+ });
782
+ async function postInstall(configPath = findConfigFile(), outDir = ".source") {
783
+ const config = await loadConfig(configPath, outDir, void 0, true);
784
+ const outPath = import_node_path3.default.join(outDir, "index.ts");
785
+ await import_promises.default.rm(outDir, { recursive: true });
786
+ await import_promises.default.mkdir(outDir, { recursive: true });
787
+ const hash = await getConfigHash(configPath);
788
+ await import_promises.default.writeFile(
789
+ outPath,
790
+ await generateJS(configPath, config, { relativeTo: outDir }, hash)
791
+ );
792
+ console.log("[MDX] types generated");
793
+ }
794
+ var import_node_path3, import_promises;
795
+ var init_next = __esm({
796
+ "src/next/index.ts"() {
797
+ "use strict";
798
+ init_config();
799
+ import_node_path3 = __toESM(require("path"), 1);
800
+ import_promises = __toESM(require("fs/promises"), 1);
801
+ init_generate();
802
+ init_create();
803
+ }
804
+ });
805
+
806
+ // src/vite/generate-glob.ts
807
+ function generateGlob(name, patterns, globOptions) {
808
+ const options = {
809
+ ...globOptions,
810
+ query: {
811
+ ...globOptions?.query,
812
+ collection: name
813
+ }
814
+ };
815
+ return `import.meta.glob(${JSON.stringify(mapGlobPatterns(patterns))}, ${JSON.stringify(options, null, 2)})`;
816
+ }
817
+ function mapGlobPatterns(patterns) {
818
+ return patterns.map(enforceRelative);
819
+ }
820
+ function enforceRelative(file) {
821
+ if (file.startsWith("./")) return file;
822
+ if (file.startsWith("/")) return `.${file}`;
823
+ return `./${file}`;
824
+ }
825
+ function getGlobBase(collection) {
826
+ let dir = collection.dir;
827
+ if (Array.isArray(dir)) {
828
+ if (dir.length !== 1)
829
+ throw new Error(
830
+ `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
831
+ );
832
+ dir = dir[0];
833
+ }
834
+ return enforceRelative(dir);
835
+ }
836
+ var init_generate_glob = __esm({
837
+ "src/vite/generate-glob.ts"() {
838
+ "use strict";
839
+ }
840
+ });
841
+
842
+ // src/vite/generate.ts
843
+ function docs(name, collection) {
844
+ const obj = [
845
+ ident(`doc: ${doc(name, collection.docs)}`),
846
+ ident(`meta: ${meta(name, collection.meta)}`)
847
+ ].join(",\n");
848
+ return `{
849
+ ${obj}
850
+ }`;
851
+ }
852
+ function doc(name, collection) {
853
+ const patterns = getGlobPatterns(collection);
854
+ const base = getGlobBase(collection);
855
+ const docGlob = generateGlob(name, patterns, {
856
+ base
857
+ });
858
+ if (collection.async) {
859
+ const headBlob = generateGlob(name, patterns, {
860
+ query: {
861
+ only: "frontmatter"
862
+ },
863
+ import: "frontmatter",
864
+ base
865
+ });
866
+ return `create.docLazy("${name}", "${base}", ${headBlob}, ${docGlob})`;
867
+ }
868
+ return `create.doc("${name}", "${base}", ${docGlob})`;
869
+ }
870
+ function meta(name, collection) {
871
+ const patterns = getGlobPatterns(collection);
872
+ const base = getGlobBase(collection);
873
+ return `create.meta("${name}", "${base}", ${generateGlob(name, patterns, {
874
+ import: "default",
875
+ base
876
+ })})`;
877
+ }
878
+ function entry(configPath, config, outDir, jsExtension) {
879
+ const lines = [
880
+ '/// <reference types="vite/client" />',
881
+ `import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
882
+ `import type * as Config from '${toImportPath(configPath, {
883
+ relativeTo: outDir,
884
+ jsExtension
885
+ })}';`,
886
+ "",
887
+ `export const create = fromConfig<typeof Config>();`
888
+ ];
889
+ for (const [name, collection] of config.collections.entries()) {
890
+ let body;
891
+ if (collection.type === "docs") {
892
+ body = docs(name, collection);
893
+ } else if (collection.type === "meta") {
894
+ body = meta(name, collection);
895
+ } else {
896
+ body = doc(name, collection);
897
+ }
898
+ lines.push("");
899
+ lines.push(`export const ${name} = ${body};`);
900
+ }
901
+ return lines.join("\n");
902
+ }
903
+ var init_generate2 = __esm({
904
+ "src/vite/generate.ts"() {
905
+ "use strict";
906
+ init_import_formatter();
907
+ init_generate_glob();
908
+ init_collections();
909
+ }
910
+ });
911
+
912
+ // src/vite/postinstall.ts
913
+ var postinstall_exports = {};
914
+ __export(postinstall_exports, {
915
+ postInstall: () => postInstall2
916
+ });
917
+ async function postInstall2(configPath = findConfigFile(), outDir, addJsExtension = false) {
918
+ const config = await loadConfig(configPath, "node_modules", void 0, true);
919
+ const outFile = "source.generated.ts";
920
+ if (outDir) {
921
+ await import_promises2.default.mkdir(outDir, { recursive: true });
922
+ }
923
+ await import_promises2.default.writeFile(
924
+ outDir ? import_node_path4.default.join(outDir, outFile) : outFile,
925
+ entry(configPath, config, outDir ?? process.cwd(), addJsExtension)
926
+ );
927
+ console.log("[MDX] types generated");
928
+ }
929
+ var import_promises2, import_node_path4;
930
+ var init_postinstall = __esm({
931
+ "src/vite/postinstall.ts"() {
932
+ "use strict";
933
+ init_config();
934
+ import_promises2 = __toESM(require("fs/promises"), 1);
935
+ import_node_path4 = __toESM(require("path"), 1);
936
+ init_generate2();
937
+ }
938
+ });
939
+
940
+ // src/bin.ts
941
+ var import_node_fs2 = require("fs");
942
+ async function start2() {
943
+ const args = process.argv.slice(2);
944
+ const isNext = (0, import_node_fs2.existsSync)("next.config.js") || (0, import_node_fs2.existsSync)("next.config.mjs") || (0, import_node_fs2.existsSync)("next.config.ts");
945
+ if (isNext) {
946
+ const { postInstall: postInstall3 } = await Promise.resolve().then(() => (init_next(), next_exports));
947
+ await postInstall3(...args);
948
+ } else {
949
+ const { postInstall: postInstall3 } = await Promise.resolve().then(() => (init_postinstall(), postinstall_exports));
950
+ await postInstall3(...args);
951
+ }
952
+ }
953
+ void start2();