fumadocs-mdx 12.0.3 → 13.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 (80) hide show
  1. package/dist/bin.cjs +1033 -308
  2. package/dist/bin.js +4 -4
  3. package/dist/build-mdx-BHG-_uxo.d.cts +53 -0
  4. package/dist/build-mdx-CzrQDBRZ.d.ts +53 -0
  5. package/dist/bun/index.cjs +92 -28
  6. package/dist/bun/index.js +6 -7
  7. package/dist/{chunk-QAUWMR5D.js → chunk-3J3WL7WN.js} +23 -5
  8. package/dist/chunk-4MAYA5QX.js +44 -0
  9. package/dist/{chunk-RMDXSZYE.js → chunk-CEA6MYJU.js} +13 -8
  10. package/dist/{chunk-IQAEAI4P.js → chunk-HI62EXSB.js} +63 -2
  11. package/dist/{chunk-46UPKP5R.js → chunk-II3H5ZVZ.js} +5 -5
  12. package/dist/{chunk-LGYVNESJ.js → chunk-JVZFH6ND.js} +6 -22
  13. package/dist/{chunk-LMG6UWCL.js → chunk-K5ZLPEIQ.js} +56 -16
  14. package/dist/{chunk-OMAMTKDE.js → chunk-KILFIBVW.js} +3 -12
  15. package/dist/chunk-NVRDCY6Z.js +30 -0
  16. package/dist/{chunk-VXEBLM4X.js → chunk-XV5Z4BFL.js} +1 -1
  17. package/dist/config/index.cjs +56 -16
  18. package/dist/config/index.d.cts +2 -1
  19. package/dist/config/index.d.ts +2 -1
  20. package/dist/config/index.js +1 -1
  21. package/dist/{define-DJbJduHy.d.ts → define-BCNh3n4O.d.cts} +40 -16
  22. package/dist/{define-DJbJduHy.d.cts → define-bck_EB4t.d.ts} +40 -16
  23. package/dist/index.cjs +0 -109
  24. package/dist/index.d.cts +73 -12
  25. package/dist/index.d.ts +73 -12
  26. package/dist/index.js +0 -11
  27. package/dist/{load-UUXLUBHL.js → load-MNG3CLET.js} +1 -3
  28. package/dist/loader-mdx.cjs +153 -60
  29. package/dist/loader-mdx.d.cts +1 -0
  30. package/dist/loader-mdx.d.ts +1 -0
  31. package/dist/loader-mdx.js +23 -9
  32. package/dist/next/index.cjs +213 -181
  33. package/dist/next/index.d.cts +2 -11
  34. package/dist/next/index.d.ts +2 -11
  35. package/dist/next/index.js +145 -117
  36. package/dist/node/loader.cjs +128 -70
  37. package/dist/node/loader.js +14 -9
  38. package/dist/plugins/index.cjs +78 -0
  39. package/dist/plugins/index.d.cts +7 -0
  40. package/dist/plugins/index.d.ts +7 -0
  41. package/dist/plugins/index.js +6 -0
  42. package/dist/plugins/json-schema.cjs +61 -0
  43. package/dist/plugins/json-schema.d.cts +16 -0
  44. package/dist/plugins/json-schema.d.ts +16 -0
  45. package/dist/plugins/json-schema.js +40 -0
  46. package/dist/remark-postprocess-K233ZVBK.d.cts +22 -0
  47. package/dist/remark-postprocess-K233ZVBK.d.ts +22 -0
  48. package/dist/runtime/next/async.cjs +108 -70
  49. package/dist/runtime/next/async.d.cts +9 -6
  50. package/dist/runtime/next/async.d.ts +9 -6
  51. package/dist/runtime/next/async.js +9 -19
  52. package/dist/runtime/next/index.cjs +25 -14
  53. package/dist/runtime/next/index.d.cts +11 -8
  54. package/dist/runtime/next/index.d.ts +11 -8
  55. package/dist/runtime/next/index.js +2 -2
  56. package/dist/runtime/vite/browser.cjs +7 -3
  57. package/dist/runtime/vite/browser.d.cts +56 -7
  58. package/dist/runtime/vite/browser.d.ts +56 -7
  59. package/dist/runtime/vite/browser.js +2 -1
  60. package/dist/runtime/vite/server.cjs +40 -34
  61. package/dist/runtime/vite/server.d.cts +13 -10
  62. package/dist/runtime/vite/server.d.ts +13 -10
  63. package/dist/runtime/vite/server.js +8 -23
  64. package/dist/{types-TeHjsmja.d.ts → types-1cCFEzWt.d.ts} +3 -10
  65. package/dist/{types-BRx1QsIJ.d.cts → types-D5NhXTJY.d.cts} +3 -10
  66. package/dist/vite/index.cjs +386 -224
  67. package/dist/vite/index.d.cts +23 -10
  68. package/dist/vite/index.d.ts +23 -10
  69. package/dist/vite/index.js +211 -37
  70. package/dist/{watcher-HGOH3APP.js → watcher-WXJDWRZY.js} +1 -1
  71. package/package.json +28 -15
  72. package/dist/browser-BupUnhpC.d.ts +0 -98
  73. package/dist/browser-R0x9IPaQ.d.cts +0 -98
  74. package/dist/chunk-ADR6R7HM.js +0 -29
  75. package/dist/chunk-XMFLD5J6.js +0 -30
  76. package/dist/chunk-ZLCSVXCD.js +0 -10
  77. package/dist/chunk-ZX7TM4AR.js +0 -127
  78. package/dist/postinstall-SCSXM4IM.js +0 -10
  79. package/dist/shared-CfiiRctw.d.ts +0 -70
  80. package/dist/shared-fFqiuWJC.d.cts +0 -70
package/dist/bin.cjs CHANGED
@@ -30,6 +30,73 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  mod
31
31
  ));
32
32
 
33
+ // src/loaders/config/index.ts
34
+ function findConfigFile() {
35
+ return import_node_path.default.resolve("source.config.ts");
36
+ }
37
+ function resolvedConfig(loaded) {
38
+ return {
39
+ getConfig() {
40
+ return loaded;
41
+ }
42
+ };
43
+ }
44
+ var import_node_path, import_promises;
45
+ var init_config = __esm({
46
+ "src/loaders/config/index.ts"() {
47
+ "use strict";
48
+ import_node_path = __toESM(require("path"), 1);
49
+ import_promises = __toESM(require("fs/promises"), 1);
50
+ }
51
+ });
52
+
53
+ // src/plugins/index.ts
54
+ function createPluginHandler(context, defaultPlugins = []) {
55
+ const plugins2 = [];
56
+ async function write(entry) {
57
+ const file = import_node_path2.default.join(context.outDir, entry.path);
58
+ await import_promises2.default.mkdir(import_node_path2.default.dirname(file), { recursive: true });
59
+ await import_promises2.default.writeFile(file, entry.content);
60
+ }
61
+ return {
62
+ async init(config) {
63
+ if (config.global.plugins) {
64
+ defaultPlugins.push(...config.global.plugins);
65
+ }
66
+ for await (const option of defaultPlugins) {
67
+ if (!option) continue;
68
+ if (Array.isArray(option)) plugins2.push(...option);
69
+ else plugins2.push(option);
70
+ }
71
+ for (const plugin of plugins2) {
72
+ const out = await plugin.config?.call(context, config);
73
+ if (out) config = out;
74
+ }
75
+ return config;
76
+ },
77
+ async emit() {
78
+ const out = await Promise.all(
79
+ plugins2.map((plugin) => {
80
+ return plugin.emit?.call(context) ?? [];
81
+ })
82
+ );
83
+ return out.flat();
84
+ },
85
+ async emitAndWrite() {
86
+ const entries = await this.emit();
87
+ await Promise.all(entries.map(write));
88
+ }
89
+ };
90
+ }
91
+ var import_node_path2, import_promises2;
92
+ var init_plugins = __esm({
93
+ "src/plugins/index.ts"() {
94
+ "use strict";
95
+ import_node_path2 = __toESM(require("path"), 1);
96
+ import_promises2 = __toESM(require("fs/promises"), 1);
97
+ }
98
+ });
99
+
33
100
  // src/loaders/mdx/preset.ts
34
101
  var preset_exports = {};
35
102
  __export(preset_exports, {
@@ -173,6 +240,10 @@ var init_build = __esm({
173
240
  });
174
241
 
175
242
  // src/loaders/config/load.ts
243
+ var load_exports = {};
244
+ __export(load_exports, {
245
+ loadConfig: () => loadConfig
246
+ });
176
247
  async function compileConfig(configPath, outDir) {
177
248
  const { build } = await import("esbuild");
178
249
  const transformed = await build({
@@ -193,37 +264,53 @@ async function compileConfig(configPath, outDir) {
193
264
  throw new Error("failed to compile configuration file");
194
265
  }
195
266
  }
196
- async function loadConfig(configPath, outDir, hash, build = false) {
197
- if (cache && cache.hash === hash) {
198
- return await cache.config;
199
- }
267
+ async function loadConfig(configPath, outDir, build = false) {
200
268
  if (build) await compileConfig(configPath, outDir);
201
- const url = (0, import_node_url.pathToFileURL)(path.resolve(outDir, "source.config.mjs"));
202
- const config = import(`${url.href}?hash=${hash}`).then((loaded) => {
203
- return buildConfig(
204
- // every call to `loadConfig` will cause the previous cache to be ignored
205
- loaded
206
- );
207
- });
208
- if (hash) cache = { config, hash };
269
+ const url = (0, import_node_url.pathToFileURL)(path3.resolve(outDir, "source.config.mjs"));
270
+ url.searchParams.set("hash", Date.now().toString());
271
+ const config = import(url.href).then(
272
+ (loaded) => buildConfig(loaded)
273
+ );
209
274
  return await config;
210
275
  }
211
- async function getConfigHash(configPath) {
212
- const stats = await fs.stat(configPath).catch(() => void 0);
213
- if (stats) {
214
- return stats.mtime.getTime().toString();
215
- }
216
- throw new Error("Cannot find config file");
217
- }
218
- var fs, path, import_node_url, cache;
276
+ var path3, import_node_url;
219
277
  var init_load = __esm({
220
278
  "src/loaders/config/load.ts"() {
221
279
  "use strict";
222
- fs = __toESM(require("fs/promises"), 1);
223
- path = __toESM(require("path"), 1);
280
+ path3 = __toESM(require("path"), 1);
224
281
  import_node_url = require("url");
225
282
  init_build();
226
- cache = null;
283
+ }
284
+ });
285
+
286
+ // src/next/file-cache.ts
287
+ function toFullPath(file) {
288
+ if (import_node_path3.default.isAbsolute(file)) {
289
+ return import_node_path3.default.relative(process.cwd(), file);
290
+ }
291
+ return file;
292
+ }
293
+ async function readFileWithCache(file) {
294
+ const fullPath = toFullPath(file);
295
+ const cached = map.get(fullPath);
296
+ if (cached) return cached;
297
+ const read = import_promises3.default.readFile(fullPath).then((s) => s.toString());
298
+ map.set(fullPath, read);
299
+ return read;
300
+ }
301
+ function removeFileCache(file) {
302
+ map.delete(toFullPath(file));
303
+ }
304
+ var import_lru_cache, import_promises3, import_node_path3, map;
305
+ var init_file_cache = __esm({
306
+ "src/next/file-cache.ts"() {
307
+ "use strict";
308
+ import_lru_cache = require("lru-cache");
309
+ import_promises3 = __toESM(require("fs/promises"), 1);
310
+ import_node_path3 = __toESM(require("path"), 1);
311
+ map = new import_lru_cache.LRUCache({
312
+ max: 100
313
+ });
227
314
  }
228
315
  });
229
316
 
@@ -271,63 +358,32 @@ ${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
271
358
  }
272
359
  });
273
360
 
274
- // src/next/map/file-cache.ts
275
- function toFullPath(file) {
276
- if (import_node_path.default.isAbsolute(file)) {
277
- return import_node_path.default.relative(process.cwd(), file);
278
- }
279
- return file;
280
- }
281
- async function readFileWithCache(file) {
282
- const fullPath = toFullPath(file);
283
- const cached = map.get(fullPath);
284
- if (cached) return cached;
285
- const read = import_promises.default.readFile(fullPath).then((s) => s.toString());
286
- map.set(fullPath, read);
287
- return read;
288
- }
289
- function removeFileCache(file) {
290
- map.delete(toFullPath(file));
291
- }
292
- var import_lru_cache, import_promises, import_node_path, map;
293
- var init_file_cache = __esm({
294
- "src/next/map/file-cache.ts"() {
295
- "use strict";
296
- import_lru_cache = require("lru-cache");
297
- import_promises = __toESM(require("fs/promises"), 1);
298
- import_node_path = __toESM(require("path"), 1);
299
- map = new import_lru_cache.LRUCache({
300
- max: 100
301
- });
302
- }
303
- });
304
-
305
361
  // src/utils/git-timestamp.ts
306
362
  async function getGitTimestamp(file) {
307
- const cached = cache2.get(file);
363
+ const cached = cache.get(file);
308
364
  if (cached) return cached;
309
365
  try {
310
366
  const out = await (0, import_tinyexec.x)(
311
367
  "git",
312
- ["log", "-1", '--pretty="%ai"', import_node_path2.default.relative(process.cwd(), file)],
368
+ ["log", "-1", '--pretty="%ai"', import_node_path4.default.relative(process.cwd(), file)],
313
369
  {
314
370
  throwOnError: true
315
371
  }
316
372
  );
317
373
  const time = new Date(out.stdout);
318
- cache2.set(file, time);
374
+ cache.set(file, time);
319
375
  return time;
320
376
  } catch {
321
377
  return;
322
378
  }
323
379
  }
324
- var import_node_path2, import_tinyexec, cache2;
380
+ var import_node_path4, import_tinyexec, cache;
325
381
  var init_git_timestamp = __esm({
326
382
  "src/utils/git-timestamp.ts"() {
327
383
  "use strict";
328
- import_node_path2 = __toESM(require("path"), 1);
384
+ import_node_path4 = __toESM(require("path"), 1);
329
385
  import_tinyexec = require("tinyexec");
330
- cache2 = /* @__PURE__ */ new Map();
386
+ cache = /* @__PURE__ */ new Map();
331
387
  }
332
388
  });
333
389
 
@@ -368,7 +424,7 @@ function getImportCode(info) {
368
424
  return `import ${specifier}`;
369
425
  }
370
426
  function toImportPath(file, config) {
371
- const ext = import_node_path3.default.extname(file);
427
+ const ext = import_node_path5.default.extname(file);
372
428
  let filename;
373
429
  if (ext === ".ts" && config.jsExtension) {
374
430
  filename = file.substring(0, file.length - ext.length) + ".js";
@@ -379,23 +435,23 @@ function toImportPath(file, config) {
379
435
  }
380
436
  let importPath;
381
437
  if ("relativeTo" in config) {
382
- importPath = import_node_path3.default.relative(config.relativeTo, filename);
383
- if (!import_node_path3.default.isAbsolute(importPath) && !importPath.startsWith(".")) {
438
+ importPath = import_node_path5.default.relative(config.relativeTo, filename);
439
+ if (!import_node_path5.default.isAbsolute(importPath) && !importPath.startsWith(".")) {
384
440
  importPath = `./${importPath}`;
385
441
  }
386
442
  } else {
387
- importPath = import_node_path3.default.resolve(filename);
443
+ importPath = import_node_path5.default.resolve(filename);
388
444
  }
389
- return importPath.replaceAll(import_node_path3.default.sep, "/");
445
+ return importPath.replaceAll(import_node_path5.default.sep, "/");
390
446
  }
391
447
  function ident(code, tab = 1) {
392
448
  return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
393
449
  }
394
- var import_node_path3;
450
+ var import_node_path5;
395
451
  var init_import_formatter = __esm({
396
452
  "src/utils/import-formatter.ts"() {
397
453
  "use strict";
398
- import_node_path3 = __toESM(require("path"), 1);
454
+ import_node_path5 = __toESM(require("path"), 1);
399
455
  }
400
456
  });
401
457
 
@@ -422,8 +478,26 @@ var init_collections = __esm({
422
478
  }
423
479
  });
424
480
 
425
- // src/next/map/generate.ts
426
- async function generateJS(configPath, config, importPath, configHash = false) {
481
+ // src/plugins/next.ts
482
+ function next() {
483
+ let config;
484
+ return {
485
+ config(v) {
486
+ config = v;
487
+ },
488
+ async emit() {
489
+ return [
490
+ {
491
+ path: "index.ts",
492
+ content: await indexFile(this.configPath, config, {
493
+ relativeTo: this.outDir
494
+ })
495
+ }
496
+ ];
497
+ }
498
+ };
499
+ }
500
+ async function indexFile(configPath, config, importPath, configHash = false) {
427
501
  let asyncInit = false;
428
502
  const lines = [
429
503
  getImportCode({
@@ -525,18 +599,18 @@ async function generateJS(configPath, config, importPath, configHash = false) {
525
599
  }
526
600
  const declares = entries.map(async ([k, collection]) => {
527
601
  if (collection.type === "docs") {
528
- const docs2 = await getCollectionFiles(collection.docs);
602
+ const docs = await getCollectionFiles(collection.docs);
529
603
  const metas = await getCollectionFiles(collection.meta);
530
604
  const metaEntries = (await getMetaEntries(collection.meta, metas)).join(
531
605
  ", "
532
606
  );
533
607
  if (collection.docs.async) {
534
- const docsEntries2 = (await getAsyncEntries(collection.docs, docs2)).join(
608
+ const docsEntries2 = (await getAsyncEntries(collection.docs, docs)).join(
535
609
  ", "
536
610
  );
537
611
  return `export const ${k} = _runtimeAsync.docs<typeof _source.${k}>([${docsEntries2}], [${metaEntries}], "${k}", _sourceConfig)`;
538
612
  }
539
- const docsEntries = (await getDocEntries(k, docs2)).join(", ");
613
+ const docsEntries = (await getDocEntries(k, docs)).join(", ");
540
614
  return `export const ${k} = _runtime.docs<typeof _source.${k}>([${docsEntries}], [${metaEntries}])`;
541
615
  }
542
616
  const files = await getCollectionFiles(collection);
@@ -559,11 +633,11 @@ async function getCollectionFiles(collection) {
559
633
  await Promise.all(
560
634
  dirs.map(async (dir) => {
561
635
  const result = await (0, import_tinyglobby.glob)(patterns, {
562
- cwd: path5.resolve(dir)
636
+ cwd: path7.resolve(dir)
563
637
  });
564
638
  for (const item of result) {
565
639
  if (!isFileSupported(item, collection)) continue;
566
- const fullPath = path5.join(dir, item);
640
+ const fullPath = path7.join(dir, item);
567
641
  files.set(fullPath, {
568
642
  path: item,
569
643
  fullPath
@@ -574,22 +648,22 @@ async function getCollectionFiles(collection) {
574
648
  return Array.from(files.values());
575
649
  }
576
650
  function parseMetaEntry(file, content) {
577
- const extname2 = path5.extname(file);
651
+ const extname4 = path7.extname(file);
578
652
  try {
579
- if (extname2 === ".json") return JSON.parse(content);
580
- if (extname2 === ".yaml") return (0, import_js_yaml2.load)(content);
653
+ if (extname4 === ".json") return JSON.parse(content);
654
+ if (extname4 === ".yaml") return (0, import_js_yaml2.load)(content);
581
655
  } catch (e) {
582
656
  throw new Error(`Failed to parse meta file: ${file}.`, {
583
657
  cause: e
584
658
  });
585
659
  }
586
- throw new Error(`Unknown meta file format: ${extname2}, in ${file}.`);
660
+ throw new Error(`Unknown meta file format: ${extname4}, in ${file}.`);
587
661
  }
588
- var path5, import_node_crypto, import_tinyglobby, import_js_yaml2;
589
- var init_generate = __esm({
590
- "src/next/map/generate.ts"() {
662
+ var path7, import_node_crypto, import_tinyglobby, import_js_yaml2;
663
+ var init_next = __esm({
664
+ "src/plugins/next.ts"() {
591
665
  "use strict";
592
- path5 = __toESM(require("path"), 1);
666
+ path7 = __toESM(require("path"), 1);
593
667
  import_node_crypto = require("crypto");
594
668
  import_tinyglobby = require("tinyglobby");
595
669
  init_validation();
@@ -602,19 +676,7 @@ var init_generate = __esm({
602
676
  }
603
677
  });
604
678
 
605
- // src/loaders/config/index.ts
606
- function findConfigFile() {
607
- return import_node_path4.default.resolve("source.config.ts");
608
- }
609
- var import_node_path4;
610
- var init_config = __esm({
611
- "src/loaders/config/index.ts"() {
612
- "use strict";
613
- import_node_path4 = __toESM(require("path"), 1);
614
- }
615
- });
616
-
617
- // src/next/map/watcher.ts
679
+ // src/next/watcher.ts
618
680
  var watcher_exports = {};
619
681
  __export(watcher_exports, {
620
682
  watcher: () => watcher
@@ -638,97 +700,33 @@ function watcher(configPath, config, ignored) {
638
700
  }
639
701
  var import_chokidar;
640
702
  var init_watcher = __esm({
641
- "src/next/map/watcher.ts"() {
703
+ "src/next/watcher.ts"() {
642
704
  "use strict";
643
705
  import_chokidar = require("chokidar");
644
706
  }
645
707
  });
646
708
 
647
- // src/next/map/index.ts
648
- async function start(dev, configPath, outDir) {
649
- let configHash = await getConfigHash(configPath);
650
- let config = await loadConfig(configPath, outDir, configHash, true);
651
- const outPath = path7.resolve(outDir, `index.ts`);
652
- async function updateMapFile() {
653
- const start3 = performance.now();
654
- try {
655
- await fs3.writeFile(
656
- outPath,
657
- await generateJS(
658
- configPath,
659
- config,
660
- { relativeTo: outDir },
661
- configHash
662
- )
663
- );
664
- } catch (err) {
665
- if (err instanceof ValidationError) {
666
- console.error(err.toStringFormatted());
667
- } else {
668
- console.error(err);
669
- }
670
- }
671
- console.log(`[MDX] updated map file in ${performance.now() - start3}ms`);
672
- }
673
- await updateMapFile();
674
- if (dev) {
675
- const { watcher: watcher2 } = await Promise.resolve().then(() => (init_watcher(), watcher_exports));
676
- const instance = watcher2(configPath, config, [outPath]);
677
- instance.on("ready", () => {
678
- console.log("[MDX] started dev server");
679
- });
680
- instance.on("all", (event, file) => {
681
- if (typeof file !== "string") return;
682
- const absolutePath = path7.resolve(file);
683
- const onUpdate = async () => {
684
- const isConfigFile = absolutePath === configPath;
685
- if (isConfigFile) {
686
- configHash = await getConfigHash(configPath);
687
- config = await loadConfig(configPath, outDir, configHash, true);
688
- }
689
- if (event === "change") removeFileCache(absolutePath);
690
- await updateMapFile();
691
- };
692
- void onUpdate();
693
- });
694
- process.on("exit", () => {
695
- console.log("[MDX] closing dev server");
696
- void instance.close();
697
- });
698
- }
699
- }
700
- var path7, fs3;
701
- var init_map = __esm({
702
- "src/next/map/index.ts"() {
703
- "use strict";
704
- path7 = __toESM(require("path"), 1);
705
- fs3 = __toESM(require("fs/promises"), 1);
706
- init_load();
707
- init_generate();
708
- init_file_cache();
709
- init_validation();
710
- }
709
+ // src/next/index.ts
710
+ var next_exports = {};
711
+ __export(next_exports, {
712
+ createMDX: () => createMDX,
713
+ postInstall: () => postInstall
711
714
  });
712
-
713
- // src/next/create.ts
714
- function createMDX({
715
- configPath = findConfigFile(),
716
- outDir = ".source"
717
- } = {}) {
715
+ function createMDX(createOptions = {}) {
716
+ const options = applyDefaults(createOptions);
717
+ const isDev = process.env.NODE_ENV === "development";
718
718
  if (process.env._FUMADOCS_MDX !== "1") {
719
719
  process.env._FUMADOCS_MDX = "1";
720
- void start(process.env.NODE_ENV === "development", configPath, outDir);
720
+ void init(isDev, options);
721
721
  }
722
722
  return (nextConfig = {}) => {
723
723
  const mdxLoaderOptions = {
724
- configPath,
725
- outDir
724
+ ...options,
725
+ isDev
726
726
  };
727
- const turbo = {
728
- ...nextConfig.experimental?.turbo,
727
+ const turbopack = {
729
728
  ...nextConfig.turbopack,
730
729
  rules: {
731
- ...nextConfig.experimental?.turbo?.rules,
732
730
  ...nextConfig.turbopack?.rules,
733
731
  "*.{md,mdx}": {
734
732
  loaders: [
@@ -741,17 +739,18 @@ function createMDX({
741
739
  }
742
740
  }
743
741
  };
744
- const updated = {
742
+ return {
745
743
  ...nextConfig,
744
+ turbopack,
746
745
  pageExtensions: nextConfig.pageExtensions ?? defaultPageExtensions,
747
- webpack: (config, options) => {
746
+ webpack: (config, options2) => {
748
747
  config.resolve ||= {};
749
748
  config.module ||= {};
750
749
  config.module.rules ||= [];
751
750
  config.module.rules.push({
752
751
  test: /\.mdx?$/,
753
752
  use: [
754
- options.defaultLoaders.babel,
753
+ options2.defaultLoaders.babel,
755
754
  {
756
755
  loader: "fumadocs-mdx/loader-mdx",
757
756
  options: mdxLoaderOptions
@@ -759,150 +758,753 @@ function createMDX({
759
758
  ]
760
759
  });
761
760
  config.plugins ||= [];
762
- return nextConfig.webpack?.(config, options) ?? config;
761
+ return nextConfig.webpack?.(config, options2) ?? config;
763
762
  }
764
763
  };
765
- if (isTurboExperimental) {
766
- updated.experimental = { ...updated.experimental, turbo };
767
- } else {
768
- updated.turbopack = turbo;
769
- }
770
- return updated;
771
764
  };
772
765
  }
773
- var import_node_fs, defaultPageExtensions, isTurboExperimental;
774
- var init_create = __esm({
775
- "src/next/create.ts"() {
776
- "use strict";
777
- init_config();
778
- init_map();
779
- import_node_fs = require("fs");
780
- defaultPageExtensions = ["mdx", "md", "jsx", "js", "tsx", "ts"];
766
+ async function init(dev, options) {
767
+ const pluginHandler = createNextPluginHandler(options);
768
+ let config;
769
+ async function updateConfig() {
770
+ config = await pluginHandler.init(
771
+ await loadConfig(options.configPath, options.outDir, true)
772
+ );
773
+ }
774
+ async function emitFiles() {
775
+ const start2 = performance.now();
781
776
  try {
782
- const content = (0, import_node_fs.readFileSync)("./node_modules/next/package.json").toString();
783
- const version = JSON.parse(content).version;
784
- isTurboExperimental = version.startsWith("15.0.") || version.startsWith("15.1.") || version.startsWith("15.2.");
785
- } catch {
786
- isTurboExperimental = false;
777
+ await pluginHandler.emitAndWrite();
778
+ } catch (err) {
779
+ if (err instanceof ValidationError) {
780
+ console.error(err.toStringFormatted());
781
+ } else {
782
+ console.error(err);
783
+ }
787
784
  }
785
+ console.log(`[MDX] updated map file in ${performance.now() - start2}ms`);
788
786
  }
789
- });
790
-
791
- // src/next/index.ts
792
- var next_exports = {};
793
- __export(next_exports, {
794
- createMDX: () => createMDX,
795
- postInstall: () => postInstall,
796
- start: () => start
797
- });
787
+ async function devServer() {
788
+ const { watcher: watcher2 } = await Promise.resolve().then(() => (init_watcher(), watcher_exports));
789
+ const instance = watcher2(options.configPath, config, [options.outDir]);
790
+ async function onUpdate(event, file) {
791
+ const absolutePath = path8.resolve(file);
792
+ if (event === "change") removeFileCache(absolutePath);
793
+ if (absolutePath === path8.resolve(options.configPath)) {
794
+ await updateConfig();
795
+ console.log("[MDX] restarting dev server");
796
+ await instance.close();
797
+ void devServer();
798
+ }
799
+ await emitFiles();
800
+ }
801
+ instance.on("ready", () => {
802
+ console.log("[MDX] started dev server");
803
+ });
804
+ instance.on("all", (event, file) => {
805
+ void onUpdate(event, file);
806
+ });
807
+ process.on("exit", () => {
808
+ console.log("[MDX] closing dev server");
809
+ void instance.close();
810
+ });
811
+ }
812
+ await updateConfig();
813
+ await emitFiles();
814
+ if (dev) void devServer();
815
+ }
798
816
  async function postInstall(configPath = findConfigFile(), outDir = ".source") {
799
- const config = await loadConfig(configPath, outDir, void 0, true);
800
- const outPath = import_node_path5.default.join(outDir, "index.ts");
801
- await import_promises2.default.rm(outDir, { recursive: true });
802
- await import_promises2.default.mkdir(outDir, { recursive: true });
803
- const hash = await getConfigHash(configPath);
804
- await import_promises2.default.writeFile(
805
- outPath,
806
- await generateJS(configPath, config, { relativeTo: outDir }, hash)
807
- );
817
+ const pluginHandler = createNextPluginHandler({
818
+ outDir,
819
+ configPath
820
+ });
821
+ await pluginHandler.init(await loadConfig(configPath, outDir, true));
822
+ await pluginHandler.emitAndWrite();
808
823
  console.log("[MDX] types generated");
809
824
  }
810
- var import_node_path5, import_promises2;
811
- var init_next = __esm({
825
+ function applyDefaults(options) {
826
+ return {
827
+ outDir: options.outDir ?? ".source",
828
+ configPath: options.configPath ?? findConfigFile()
829
+ };
830
+ }
831
+ function createNextPluginHandler({
832
+ outDir,
833
+ configPath
834
+ }) {
835
+ return createPluginHandler(
836
+ {
837
+ environment: "next",
838
+ outDir,
839
+ configPath
840
+ },
841
+ [next()]
842
+ );
843
+ }
844
+ var path8, defaultPageExtensions;
845
+ var init_next2 = __esm({
812
846
  "src/next/index.ts"() {
813
847
  "use strict";
814
- init_load();
815
- import_node_path5 = __toESM(require("path"), 1);
816
- import_promises2 = __toESM(require("fs/promises"), 1);
817
- init_generate();
818
848
  init_config();
819
- init_create();
849
+ init_plugins();
850
+ path8 = __toESM(require("path"), 1);
851
+ init_load();
852
+ init_file_cache();
853
+ init_validation();
854
+ init_next();
855
+ defaultPageExtensions = ["mdx", "md", "jsx", "js", "tsx", "ts"];
820
856
  }
821
857
  });
822
858
 
823
- // src/vite/generate-glob.ts
824
- function generateGlob(name, patterns, globOptions) {
825
- const options = {
826
- ...globOptions,
827
- query: {
828
- ...globOptions?.query,
829
- collection: name
830
- }
859
+ // src/loaders/mdx/remark-unravel.ts
860
+ function remarkMarkAndUnravel() {
861
+ return (tree) => {
862
+ (0, import_unist_util_visit.visit)(tree, function(node, index, parent) {
863
+ let offset = -1;
864
+ let all = true;
865
+ let oneOrMore = false;
866
+ if (parent && typeof index === "number" && node.type === "paragraph") {
867
+ const children = node.children;
868
+ while (++offset < children.length) {
869
+ const child = children[offset];
870
+ if (child.type === "mdxJsxTextElement" || child.type === "mdxTextExpression") {
871
+ oneOrMore = true;
872
+ } else if (child.type === "text" && child.value.trim().length === 0) {
873
+ } else {
874
+ all = false;
875
+ break;
876
+ }
877
+ }
878
+ if (all && oneOrMore) {
879
+ offset = -1;
880
+ const newChildren = [];
881
+ while (++offset < children.length) {
882
+ const child = children[offset];
883
+ if (child.type === "mdxJsxTextElement") {
884
+ child.type = "mdxJsxFlowElement";
885
+ }
886
+ if (child.type === "mdxTextExpression") {
887
+ child.type = "mdxFlowExpression";
888
+ }
889
+ if (child.type === "text" && /^[\t\r\n ]+$/.test(String(child.value))) {
890
+ } else {
891
+ newChildren.push(child);
892
+ }
893
+ }
894
+ parent.children.splice(index, 1, ...newChildren);
895
+ return index;
896
+ }
897
+ }
898
+ });
831
899
  };
832
- return `import.meta.glob(${JSON.stringify(mapGlobPatterns(patterns))}, ${JSON.stringify(options, null, 2)})`;
833
900
  }
834
- function mapGlobPatterns(patterns) {
835
- return patterns.map(enforceRelative);
901
+ var import_unist_util_visit;
902
+ var init_remark_unravel = __esm({
903
+ "src/loaders/mdx/remark-unravel.ts"() {
904
+ "use strict";
905
+ import_unist_util_visit = require("unist-util-visit");
906
+ }
907
+ });
908
+
909
+ // src/loaders/mdx/remark-include.ts
910
+ function isElementLike(node) {
911
+ return ElementLikeTypes.includes(node.type);
836
912
  }
837
- function enforceRelative(file) {
838
- if (file.startsWith("./")) return file;
839
- if (file.startsWith("/")) return `.${file}`;
840
- return `./${file}`;
913
+ function parseElementAttributes(element) {
914
+ if (Array.isArray(element.attributes)) {
915
+ const attributes = {};
916
+ for (const attr of element.attributes) {
917
+ if (attr.type === "mdxJsxAttribute" && (typeof attr.value === "string" || attr.value === null)) {
918
+ attributes[attr.name] = attr.value;
919
+ }
920
+ }
921
+ return attributes;
922
+ }
923
+ return element.attributes ?? {};
841
924
  }
842
- function getGlobBase(collection) {
843
- let dir = collection.dir;
844
- if (Array.isArray(dir)) {
845
- if (dir.length !== 1)
925
+ function flattenNode(node) {
926
+ if ("children" in node)
927
+ return node.children.map((child) => flattenNode(child)).join("");
928
+ if ("value" in node) return node.value;
929
+ return "";
930
+ }
931
+ function parseSpecifier(specifier) {
932
+ const idx = specifier.lastIndexOf("#");
933
+ if (idx === -1) return { file: specifier };
934
+ return {
935
+ file: specifier.slice(0, idx),
936
+ section: specifier.slice(idx + 1)
937
+ };
938
+ }
939
+ function extractSection(root, section) {
940
+ let nodes;
941
+ let capturingHeadingContent = false;
942
+ (0, import_unist_util_visit2.visit)(root, (node) => {
943
+ if (node.type === "heading") {
944
+ if (capturingHeadingContent) {
945
+ return false;
946
+ }
947
+ if (node.data?.hProperties?.id === section) {
948
+ capturingHeadingContent = true;
949
+ nodes = [node];
950
+ return "skip";
951
+ }
952
+ return;
953
+ }
954
+ if (capturingHeadingContent) {
955
+ nodes?.push(node);
956
+ return "skip";
957
+ }
958
+ if (isElementLike(node) && node.name === "section") {
959
+ const attributes = parseElementAttributes(node);
960
+ if (attributes.id === section) {
961
+ nodes = node.children;
962
+ return false;
963
+ }
964
+ }
965
+ });
966
+ if (nodes)
967
+ return {
968
+ type: "root",
969
+ children: nodes
970
+ };
971
+ }
972
+ function remarkInclude() {
973
+ const TagName = "include";
974
+ const embedContent = async (file, heading, params, data) => {
975
+ let content;
976
+ try {
977
+ content = (await fs4.readFile(file)).toString();
978
+ } catch (e) {
846
979
  throw new Error(
847
- `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
980
+ `failed to read file ${file}
981
+ ${e instanceof Error ? e.message : String(e)}`,
982
+ { cause: e }
848
983
  );
849
- dir = dir[0];
984
+ }
985
+ const ext = path9.extname(file);
986
+ data._compiler?.addDependency(file);
987
+ if (params.lang || ext !== ".md" && ext !== ".mdx") {
988
+ const lang = params.lang ?? ext.slice(1);
989
+ return {
990
+ type: "code",
991
+ lang,
992
+ meta: params.meta,
993
+ value: content,
994
+ data: {}
995
+ };
996
+ }
997
+ const parser = data._getProcessor ? data._getProcessor(ext === ".mdx" ? "mdx" : "md") : this;
998
+ const parsed = fumaMatter(content);
999
+ let mdast = parser.parse({
1000
+ path: file,
1001
+ value: parsed.content,
1002
+ data: { frontmatter: parsed.data }
1003
+ });
1004
+ const baseProcessor = (0, import_unified.unified)().use(remarkMarkAndUnravel);
1005
+ if (heading) {
1006
+ const extracted = extractSection(
1007
+ await baseProcessor.use(import_mdx_plugins.remarkHeading).run(mdast),
1008
+ heading
1009
+ );
1010
+ if (!extracted)
1011
+ throw new Error(
1012
+ `Cannot find section ${heading} in ${file}, make sure you have encapsulated the section in a <section id="${heading}"> tag, or a :::section directive with remark-directive configured.`
1013
+ );
1014
+ mdast = extracted;
1015
+ } else {
1016
+ mdast = await baseProcessor.run(mdast);
1017
+ }
1018
+ await update(mdast, path9.dirname(file), data);
1019
+ return mdast;
1020
+ };
1021
+ async function update(tree, directory, data) {
1022
+ const queue = [];
1023
+ (0, import_unist_util_visit2.visit)(tree, ElementLikeTypes, (_node, _, parent) => {
1024
+ const node = _node;
1025
+ if (node.name !== TagName) return;
1026
+ const specifier = flattenNode(node);
1027
+ if (specifier.length === 0) return "skip";
1028
+ const attributes = parseElementAttributes(node);
1029
+ const { file: relativePath, section } = parseSpecifier(specifier);
1030
+ const file = path9.resolve(
1031
+ "cwd" in attributes ? process.cwd() : directory,
1032
+ relativePath
1033
+ );
1034
+ queue.push(
1035
+ embedContent(file, section, attributes, data).then((replace) => {
1036
+ Object.assign(
1037
+ parent && parent.type === "paragraph" ? parent : node,
1038
+ replace
1039
+ );
1040
+ })
1041
+ );
1042
+ return "skip";
1043
+ });
1044
+ await Promise.all(queue);
850
1045
  }
851
- return enforceRelative(dir);
1046
+ return async (tree, file) => {
1047
+ await update(tree, path9.dirname(file.path), file.data);
1048
+ };
852
1049
  }
853
- var init_generate_glob = __esm({
854
- "src/vite/generate-glob.ts"() {
1050
+ var import_unified, import_unist_util_visit2, path9, fs4, import_mdx_plugins, ElementLikeTypes;
1051
+ var init_remark_include = __esm({
1052
+ "src/loaders/mdx/remark-include.ts"() {
855
1053
  "use strict";
1054
+ import_unified = require("unified");
1055
+ import_unist_util_visit2 = require("unist-util-visit");
1056
+ path9 = __toESM(require("path"), 1);
1057
+ fs4 = __toESM(require("fs/promises"), 1);
1058
+ init_fuma_matter();
1059
+ import_mdx_plugins = require("fumadocs-core/mdx-plugins");
1060
+ init_remark_unravel();
1061
+ ElementLikeTypes = [
1062
+ "mdxJsxFlowElement",
1063
+ "mdxJsxTextElement",
1064
+ "containerDirective",
1065
+ "textDirective",
1066
+ "leafDirective"
1067
+ ];
856
1068
  }
857
1069
  });
858
1070
 
859
- // src/vite/generate.ts
860
- function docs(name, collection) {
861
- const obj = [
862
- ident(`doc: ${doc(name, collection.docs)}`),
863
- ident(`meta: ${meta(name, collection.meta)}`)
864
- ].join(",\n");
865
- return `{
866
- ${obj}
867
- }`;
1071
+ // src/loaders/mdx/remark-postprocess.ts
1072
+ function remarkPostprocess({
1073
+ _format,
1074
+ includeProcessedMarkdown = false,
1075
+ includeMDAST = false,
1076
+ valueToExport = []
1077
+ }) {
1078
+ let _stringifyProcessor;
1079
+ const getStringifyProcessor = () => {
1080
+ if (_format === "mdx") return this;
1081
+ return _stringifyProcessor ??= this().use(import_remark_mdx.default).freeze();
1082
+ };
1083
+ return (tree, file) => {
1084
+ let title;
1085
+ const urls = [];
1086
+ (0, import_unist_util_visit3.visit)(tree, ["heading", "link"], (node) => {
1087
+ if (node.type === "heading" && node.depth === 1) {
1088
+ title = flattenNode2(node);
1089
+ }
1090
+ if (node.type !== "link") return;
1091
+ urls.push({
1092
+ href: node.url
1093
+ });
1094
+ return "skip";
1095
+ });
1096
+ if (title) {
1097
+ file.data.frontmatter ??= {};
1098
+ if (!file.data.frontmatter.title) file.data.frontmatter.title = title;
1099
+ }
1100
+ file.data.extractedReferences = urls;
1101
+ if (includeProcessedMarkdown) {
1102
+ const processor = getStringifyProcessor();
1103
+ file.data._markdown = (0, import_mdast_util_to_markdown.toMarkdown)(tree, {
1104
+ ...processor.data("settings"),
1105
+ // from https://github.com/remarkjs/remark/blob/main/packages/remark-stringify/lib/index.js
1106
+ extensions: processor.data("toMarkdownExtensions") || []
1107
+ });
1108
+ }
1109
+ if (includeMDAST) {
1110
+ const options = includeMDAST === true ? {} : includeMDAST;
1111
+ file.data._mdast = JSON.stringify(
1112
+ options.removePosition ? (0, import_unist_util_remove_position.removePosition)(structuredClone(tree)) : tree
1113
+ );
1114
+ }
1115
+ for (const { name, value } of file.data["mdx-export"] ?? []) {
1116
+ tree.children.unshift(getMdastExport(name, value));
1117
+ }
1118
+ for (const name of valueToExport) {
1119
+ if (!(name in file.data)) continue;
1120
+ tree.children.unshift(getMdastExport(name, file.data[name]));
1121
+ }
1122
+ };
868
1123
  }
869
- function doc(name, collection) {
870
- const patterns = getGlobPatterns(collection);
871
- const base = getGlobBase(collection);
872
- const docGlob = generateGlob(name, patterns, {
873
- base
1124
+ function getMdastExport(name, value) {
1125
+ return {
1126
+ type: "mdxjsEsm",
1127
+ value: "",
1128
+ data: {
1129
+ estree: {
1130
+ type: "Program",
1131
+ sourceType: "module",
1132
+ body: [
1133
+ {
1134
+ type: "ExportNamedDeclaration",
1135
+ attributes: [],
1136
+ specifiers: [],
1137
+ source: null,
1138
+ declaration: {
1139
+ type: "VariableDeclaration",
1140
+ kind: "let",
1141
+ declarations: [
1142
+ {
1143
+ type: "VariableDeclarator",
1144
+ id: {
1145
+ type: "Identifier",
1146
+ name
1147
+ },
1148
+ init: (0, import_estree_util_value_to_estree.valueToEstree)(value)
1149
+ }
1150
+ ]
1151
+ }
1152
+ }
1153
+ ]
1154
+ }
1155
+ }
1156
+ };
1157
+ }
1158
+ function flattenNode2(node) {
1159
+ if ("children" in node)
1160
+ return node.children.map((child) => flattenNode2(child)).join("");
1161
+ if ("value" in node) return node.value;
1162
+ return "";
1163
+ }
1164
+ var import_unist_util_visit3, import_mdast_util_to_markdown, import_estree_util_value_to_estree, import_unist_util_remove_position, import_remark_mdx;
1165
+ var init_remark_postprocess = __esm({
1166
+ "src/loaders/mdx/remark-postprocess.ts"() {
1167
+ "use strict";
1168
+ import_unist_util_visit3 = require("unist-util-visit");
1169
+ import_mdast_util_to_markdown = require("mdast-util-to-markdown");
1170
+ import_estree_util_value_to_estree = require("estree-util-value-to-estree");
1171
+ import_unist_util_remove_position = require("unist-util-remove-position");
1172
+ import_remark_mdx = __toESM(require("remark-mdx"), 1);
1173
+ }
1174
+ });
1175
+
1176
+ // src/loaders/mdx/build-mdx.ts
1177
+ async function buildMDX(cacheKey, source, options) {
1178
+ const { filePath, frontmatter, data, _compiler, ...rest } = options;
1179
+ function getProcessor(format) {
1180
+ const key = `${cacheKey}:${format}`;
1181
+ let processor = cache2.get(key);
1182
+ if (!processor) {
1183
+ processor = (0, import_mdx.createProcessor)({
1184
+ outputFormat: "program",
1185
+ ...rest,
1186
+ remarkPlugins: [
1187
+ remarkInclude,
1188
+ ...rest.remarkPlugins ?? [],
1189
+ [
1190
+ remarkPostprocess,
1191
+ {
1192
+ _format: format,
1193
+ ...options.postprocess,
1194
+ valueToExport: [
1195
+ ...options.postprocess?.valueToExport ?? [],
1196
+ "structuredData",
1197
+ "extractedReferences",
1198
+ "frontmatter",
1199
+ "lastModified",
1200
+ "_markdown",
1201
+ "_mdast"
1202
+ ]
1203
+ }
1204
+ ]
1205
+ ],
1206
+ format
1207
+ });
1208
+ cache2.set(key, processor);
1209
+ }
1210
+ return processor;
1211
+ }
1212
+ return getProcessor(
1213
+ options.format ?? (filePath.endsWith(".mdx") ? "mdx" : "md")
1214
+ ).process({
1215
+ value: source,
1216
+ path: filePath,
1217
+ data: {
1218
+ ...data,
1219
+ frontmatter,
1220
+ _compiler,
1221
+ _getProcessor: getProcessor
1222
+ }
874
1223
  });
875
- if (collection.async) {
876
- const headBlob = generateGlob(name, patterns, {
877
- query: {
878
- only: "frontmatter"
879
- },
880
- import: "frontmatter",
881
- base
1224
+ }
1225
+ var import_mdx, cache2;
1226
+ var init_build_mdx = __esm({
1227
+ "src/loaders/mdx/build-mdx.ts"() {
1228
+ "use strict";
1229
+ import_mdx = require("@mdx-js/mdx");
1230
+ init_remark_include();
1231
+ init_remark_postprocess();
1232
+ cache2 = /* @__PURE__ */ new Map();
1233
+ }
1234
+ });
1235
+
1236
+ // src/loaders/mdx/index.ts
1237
+ function getConfigHash(config) {
1238
+ let hash = hashes.get(config);
1239
+ if (hash) return hash;
1240
+ hash = Date.now().toString();
1241
+ hashes.set(config, hash);
1242
+ return hash;
1243
+ }
1244
+ function createMdxLoader(configLoader) {
1245
+ return async ({
1246
+ source: value,
1247
+ development: isDevelopment,
1248
+ query,
1249
+ compiler,
1250
+ filePath
1251
+ }) => {
1252
+ const matter = fumaMatter(value);
1253
+ const parsed = querySchema.parse(query);
1254
+ const loaded = await configLoader.getConfig();
1255
+ const cacheDir = isDevelopment ? void 0 : loaded.global.experimentalBuildCache;
1256
+ const cacheKey = `${parsed.hash}_${parsed.collection ?? "global"}_${generateCacheHash(filePath)}`;
1257
+ if (cacheDir) {
1258
+ const cached = await import_promises4.default.readFile(import_node_path6.default.join(cacheDir, cacheKey)).then((content) => cacheEntry.parse(JSON.parse(content.toString()))).catch(() => null);
1259
+ if (cached && cached.hash === generateCacheHash(value)) return cached;
1260
+ }
1261
+ const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
1262
+ let docCollection;
1263
+ switch (collection?.type) {
1264
+ case "doc":
1265
+ docCollection = collection;
1266
+ break;
1267
+ case "docs":
1268
+ docCollection = collection.docs;
1269
+ break;
1270
+ }
1271
+ if (docCollection?.schema) {
1272
+ matter.data = await validate(
1273
+ docCollection.schema,
1274
+ matter.data,
1275
+ {
1276
+ source: value,
1277
+ path: filePath
1278
+ },
1279
+ `invalid frontmatter in ${filePath}`
1280
+ );
1281
+ }
1282
+ if (parsed.only === "frontmatter") {
1283
+ return {
1284
+ code: `export const frontmatter = ${JSON.stringify(matter.data)}`,
1285
+ map: null
1286
+ };
1287
+ }
1288
+ const data = {};
1289
+ if (loaded.global.lastModifiedTime === "git") {
1290
+ data.lastModified = (await getGitTimestamp(filePath))?.getTime();
1291
+ }
1292
+ const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
1293
+ const compiled = await buildMDX(
1294
+ `${getConfigHash(loaded)}:${parsed.collection ?? "global"}`,
1295
+ "\n".repeat(lineOffset) + matter.content,
1296
+ {
1297
+ development: isDevelopment,
1298
+ ...docCollection?.mdxOptions ?? await loaded.getDefaultMDXOptions(),
1299
+ postprocess: docCollection?.postprocess,
1300
+ data,
1301
+ filePath,
1302
+ frontmatter: matter.data,
1303
+ _compiler: compiler
1304
+ }
1305
+ );
1306
+ const out = {
1307
+ code: String(compiled.value),
1308
+ map: compiled.map
1309
+ };
1310
+ if (cacheDir) {
1311
+ await import_promises4.default.mkdir(cacheDir, { recursive: true });
1312
+ await import_promises4.default.writeFile(
1313
+ import_node_path6.default.join(cacheDir, cacheKey),
1314
+ JSON.stringify({
1315
+ ...out,
1316
+ hash: generateCacheHash(value)
1317
+ })
1318
+ );
1319
+ }
1320
+ return out;
1321
+ };
1322
+ }
1323
+ function generateCacheHash(input) {
1324
+ return (0, import_node_crypto2.createHash)("md5").update(input).digest("hex");
1325
+ }
1326
+ function countLines(s) {
1327
+ let num = 0;
1328
+ for (const c of s) {
1329
+ if (c === "\n") num++;
1330
+ }
1331
+ return num;
1332
+ }
1333
+ var import_zod, import_promises4, import_node_path6, import_node_crypto2, querySchema, cacheEntry, hashes;
1334
+ var init_mdx = __esm({
1335
+ "src/loaders/mdx/index.ts"() {
1336
+ "use strict";
1337
+ init_fuma_matter();
1338
+ init_validation();
1339
+ init_git_timestamp();
1340
+ init_build_mdx();
1341
+ import_zod = require("zod");
1342
+ import_promises4 = __toESM(require("fs/promises"), 1);
1343
+ import_node_path6 = __toESM(require("path"), 1);
1344
+ import_node_crypto2 = require("crypto");
1345
+ querySchema = import_zod.z.object({
1346
+ only: import_zod.z.literal(["frontmatter", "all"]).default("all"),
1347
+ collection: import_zod.z.string().optional()
1348
+ }).loose();
1349
+ cacheEntry = import_zod.z.object({
1350
+ code: import_zod.z.string(),
1351
+ map: import_zod.z.any().optional(),
1352
+ hash: import_zod.z.string().optional()
882
1353
  });
883
- return `create.docLazy("${name}", "${base}", ${headBlob}, ${docGlob})`;
1354
+ hashes = /* @__PURE__ */ new WeakMap();
884
1355
  }
885
- return `create.doc("${name}", "${base}", ${docGlob})`;
1356
+ });
1357
+
1358
+ // src/loaders/adapter.ts
1359
+ function toVite(loader) {
1360
+ return async function(file, query, value) {
1361
+ const result = await loader({
1362
+ filePath: file,
1363
+ query: (0, import_node_querystring.parse)(query),
1364
+ source: value,
1365
+ development: this.environment.mode === "dev",
1366
+ compiler: {
1367
+ addDependency: (file2) => {
1368
+ this.addWatchFile(file2);
1369
+ }
1370
+ }
1371
+ });
1372
+ return {
1373
+ code: result.code,
1374
+ map: result.map
1375
+ };
1376
+ };
886
1377
  }
887
- function meta(name, collection) {
888
- const patterns = getGlobPatterns(collection);
889
- const base = getGlobBase(collection);
890
- return `create.meta("${name}", "${base}", ${generateGlob(name, patterns, {
891
- import: "default",
892
- base
893
- })})`;
1378
+ var import_node_url2, import_promises5, import_node_querystring, import_node_path7;
1379
+ var init_adapter = __esm({
1380
+ "src/loaders/adapter.ts"() {
1381
+ "use strict";
1382
+ import_node_url2 = require("url");
1383
+ import_promises5 = __toESM(require("fs/promises"), 1);
1384
+ import_node_querystring = require("querystring");
1385
+ init_validation();
1386
+ import_node_path7 = __toESM(require("path"), 1);
1387
+ }
1388
+ });
1389
+
1390
+ // src/utils/glob-import.ts
1391
+ function generateGlobImport(patterns, options) {
1392
+ let code = "{";
1393
+ const result = (0, import_tinyglobby2.globSync)(patterns, {
1394
+ cwd: options.base
1395
+ });
1396
+ for (const item of result) {
1397
+ const fullPath = import_node_path8.default.join(options.base, item);
1398
+ const url = (0, import_node_url3.pathToFileURL)(fullPath);
1399
+ for (const [k, v] of Object.entries(options.query ?? {})) {
1400
+ url.searchParams.set(k, v);
1401
+ }
1402
+ let line = `${JSON.stringify(item)}: () => import(${JSON.stringify(url.href)})`;
1403
+ if (options.import) {
1404
+ line += `.then(mod => mod[${JSON.stringify(options.import)}])`;
1405
+ }
1406
+ code += `${line}, `;
1407
+ }
1408
+ code += "}";
1409
+ return code;
1410
+ }
1411
+ var import_tinyglobby2, import_node_path8, import_node_url3;
1412
+ var init_glob_import = __esm({
1413
+ "src/utils/glob-import.ts"() {
1414
+ "use strict";
1415
+ import_tinyglobby2 = require("tinyglobby");
1416
+ import_node_path8 = __toESM(require("path"), 1);
1417
+ import_node_url3 = require("url");
1418
+ }
1419
+ });
1420
+
1421
+ // src/plugins/vite.ts
1422
+ function vite(options) {
1423
+ let config;
1424
+ return {
1425
+ config(v) {
1426
+ config = v;
1427
+ },
1428
+ emit() {
1429
+ console.log("[Fumadocs MDX] Generating index files");
1430
+ return [
1431
+ {
1432
+ path: "index.ts",
1433
+ content: indexFile2(this.configPath, this.outDir, config, options)
1434
+ }
1435
+ ];
1436
+ }
1437
+ };
894
1438
  }
895
- function entry(configPath, config, outDir, jsExtension) {
1439
+ function indexFile2(configPath, outDir, config, options) {
1440
+ const { addJsExtension = false, runtime } = options;
896
1441
  const lines = [
897
1442
  '/// <reference types="vite/client" />',
898
1443
  `import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
899
1444
  `import type * as Config from '${toImportPath(configPath, {
900
1445
  relativeTo: outDir,
901
- jsExtension
1446
+ jsExtension: addJsExtension
902
1447
  })}';`,
903
1448
  "",
904
1449
  `export const create = fromConfig<typeof Config>();`
905
1450
  ];
1451
+ function docs(name, collection) {
1452
+ const obj = [
1453
+ ident(`doc: ${doc(name, collection.docs)}`),
1454
+ ident(`meta: ${meta(name, collection.meta)}`)
1455
+ ].join(",\n");
1456
+ return `{
1457
+ ${obj}
1458
+ }`;
1459
+ }
1460
+ function doc(name, collection) {
1461
+ const patterns = getGlobPatterns(collection);
1462
+ const base = getGlobBase(collection);
1463
+ const docGlob = generateGlob(patterns, {
1464
+ query: {
1465
+ collection: name
1466
+ },
1467
+ base
1468
+ });
1469
+ if (collection.async) {
1470
+ const headBlob = generateGlob(patterns, {
1471
+ query: {
1472
+ only: "frontmatter",
1473
+ collection: name
1474
+ },
1475
+ import: "frontmatter",
1476
+ base
1477
+ });
1478
+ return `create.docLazy("${name}", "${base}", ${headBlob}, ${docGlob})`;
1479
+ }
1480
+ return `create.doc("${name}", "${base}", ${docGlob})`;
1481
+ }
1482
+ function meta(name, collection) {
1483
+ const patterns = getGlobPatterns(collection);
1484
+ const base = getGlobBase(collection);
1485
+ return `create.meta("${name}", "${base}", ${generateGlob(patterns, {
1486
+ import: "default",
1487
+ base,
1488
+ query: {
1489
+ collection: name
1490
+ }
1491
+ })})`;
1492
+ }
1493
+ function generateGlob(patterns, options2) {
1494
+ patterns = mapGlobPatterns(patterns);
1495
+ if (runtime === "node" || runtime === "bun") {
1496
+ return generateGlobImport(patterns, options2);
1497
+ } else {
1498
+ return `import.meta.glob(${JSON.stringify(patterns)}, ${JSON.stringify(
1499
+ {
1500
+ ...options2,
1501
+ base: import_node_path9.default.relative(outDir, options2.base)
1502
+ },
1503
+ null,
1504
+ 2
1505
+ )})`;
1506
+ }
1507
+ }
906
1508
  for (const [name, collection] of config.collections.entries()) {
907
1509
  let body;
908
1510
  if (collection.type === "docs") {
@@ -917,55 +1519,178 @@ function entry(configPath, config, outDir, jsExtension) {
917
1519
  }
918
1520
  return lines.join("\n");
919
1521
  }
920
- var init_generate2 = __esm({
921
- "src/vite/generate.ts"() {
1522
+ function mapGlobPatterns(patterns) {
1523
+ return patterns.map(enforceRelative);
1524
+ }
1525
+ function enforceRelative(file) {
1526
+ if (file.startsWith("./")) return file;
1527
+ if (file.startsWith("/")) return `.${file}`;
1528
+ return `./${file}`;
1529
+ }
1530
+ function getGlobBase(collection) {
1531
+ let dir = collection.dir;
1532
+ if (Array.isArray(dir)) {
1533
+ if (dir.length !== 1)
1534
+ throw new Error(
1535
+ `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
1536
+ );
1537
+ dir = dir[0];
1538
+ }
1539
+ return enforceRelative(dir);
1540
+ }
1541
+ var import_node_path9;
1542
+ var init_vite = __esm({
1543
+ "src/plugins/vite.ts"() {
922
1544
  "use strict";
923
1545
  init_import_formatter();
924
- init_generate_glob();
925
1546
  init_collections();
1547
+ init_glob_import();
1548
+ import_node_path9 = __toESM(require("path"), 1);
926
1549
  }
927
1550
  });
928
1551
 
929
- // src/vite/postinstall.ts
930
- var postinstall_exports = {};
931
- __export(postinstall_exports, {
1552
+ // src/vite/index.ts
1553
+ var vite_exports = {};
1554
+ __export(vite_exports, {
1555
+ default: () => mdx,
932
1556
  postInstall: () => postInstall2
933
1557
  });
934
- async function postInstall2(configPath = findConfigFile(), outDir, addJsExtension = false) {
935
- const config = await loadConfig(configPath, "node_modules", void 0, true);
936
- const outFile = "source.generated.ts";
937
- if (outDir) {
938
- await import_promises3.default.mkdir(outDir, { recursive: true });
939
- }
940
- await import_promises3.default.writeFile(
941
- outDir ? import_node_path6.default.join(outDir, outFile) : outFile,
942
- entry(configPath, config, outDir ?? process.cwd(), addJsExtension)
943
- );
1558
+ async function mdx(config, pluginOptions = {}) {
1559
+ const options = applyDefaults2(pluginOptions);
1560
+ const { updateViteConfig } = options;
1561
+ const pluginHandler = createVitePluginHandler(options);
1562
+ const loaded = await pluginHandler.init(buildConfig(config));
1563
+ const mdxLoader = toVite(createMdxLoader(resolvedConfig(loaded)));
1564
+ async function transformMeta(path15, query, value) {
1565
+ const isJson = path15.endsWith(".json");
1566
+ const parsed = (0, import_node_querystring2.parse)(query);
1567
+ const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
1568
+ if (!collection) return null;
1569
+ let schema;
1570
+ switch (collection.type) {
1571
+ case "meta":
1572
+ schema = collection.schema;
1573
+ break;
1574
+ case "docs":
1575
+ schema = collection.meta.schema;
1576
+ break;
1577
+ }
1578
+ if (!schema) return null;
1579
+ let data;
1580
+ try {
1581
+ data = isJson ? JSON.parse(value) : (0, import_js_yaml3.load)(value);
1582
+ } catch {
1583
+ return null;
1584
+ }
1585
+ const out = await validate(
1586
+ schema,
1587
+ data,
1588
+ { path: path15, source: value },
1589
+ `invalid data in ${path15}`
1590
+ );
1591
+ return {
1592
+ code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
1593
+ map: null
1594
+ };
1595
+ }
1596
+ return {
1597
+ name: "fumadocs-mdx",
1598
+ // needed, otherwise other plugins will be executed before our `transform`.
1599
+ enforce: "pre",
1600
+ config(config2) {
1601
+ if (!updateViteConfig) return config2;
1602
+ return (0, import_vite.mergeConfig)(config2, {
1603
+ optimizeDeps: {
1604
+ exclude: FumadocsDeps
1605
+ },
1606
+ resolve: {
1607
+ noExternal: FumadocsDeps,
1608
+ dedupe: FumadocsDeps
1609
+ }
1610
+ });
1611
+ },
1612
+ async buildStart() {
1613
+ await pluginHandler.emitAndWrite();
1614
+ },
1615
+ async transform(value, id) {
1616
+ const [file, query = ""] = id.split("?");
1617
+ const ext = path14.extname(file);
1618
+ try {
1619
+ if ([".yaml", ".json"].includes(ext))
1620
+ return await transformMeta(file, query, value);
1621
+ if ([".md", ".mdx"].includes(ext))
1622
+ return await mdxLoader.call(this, file, query, value);
1623
+ } catch (e) {
1624
+ if (e instanceof ValidationError) {
1625
+ throw new Error(e.toStringFormatted());
1626
+ }
1627
+ throw e;
1628
+ }
1629
+ }
1630
+ };
1631
+ }
1632
+ async function postInstall2(configPath = findConfigFile(), pluginOptions = {}) {
1633
+ const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_load(), load_exports));
1634
+ const options = applyDefaults2(pluginOptions);
1635
+ const pluginHandler = createVitePluginHandler(options);
1636
+ await pluginHandler.init(await loadConfig2(configPath, options.outDir, true));
1637
+ await pluginHandler.emitAndWrite();
944
1638
  console.log("[MDX] types generated");
945
1639
  }
946
- var import_promises3, import_node_path6;
947
- var init_postinstall = __esm({
948
- "src/vite/postinstall.ts"() {
1640
+ function createVitePluginHandler({
1641
+ configPath,
1642
+ outDir,
1643
+ generateIndexFile
1644
+ }) {
1645
+ return createPluginHandler(
1646
+ {
1647
+ environment: "vite",
1648
+ configPath,
1649
+ outDir
1650
+ },
1651
+ [
1652
+ generateIndexFile !== false && vite(typeof generateIndexFile === "object" ? generateIndexFile : {})
1653
+ ]
1654
+ );
1655
+ }
1656
+ function applyDefaults2(options) {
1657
+ return {
1658
+ updateViteConfig: options.updateViteConfig ?? true,
1659
+ generateIndexFile: options.generateIndexFile ?? true,
1660
+ configPath: options.configPath ?? "source.config.ts",
1661
+ outDir: options.outDir ?? ".source"
1662
+ };
1663
+ }
1664
+ var import_vite, import_node_querystring2, path14, import_js_yaml3, FumadocsDeps;
1665
+ var init_vite2 = __esm({
1666
+ "src/vite/index.ts"() {
949
1667
  "use strict";
950
- init_load();
951
- import_promises3 = __toESM(require("fs/promises"), 1);
952
- import_node_path6 = __toESM(require("path"), 1);
953
- init_generate2();
1668
+ import_vite = require("vite");
1669
+ init_build();
1670
+ import_node_querystring2 = require("querystring");
1671
+ init_validation();
1672
+ path14 = __toESM(require("path"), 1);
1673
+ import_js_yaml3 = require("js-yaml");
1674
+ init_mdx();
954
1675
  init_config();
1676
+ init_adapter();
1677
+ init_vite();
1678
+ init_plugins();
1679
+ FumadocsDeps = ["fumadocs-core", "fumadocs-ui", "fumadocs-openapi"];
955
1680
  }
956
1681
  });
957
1682
 
958
1683
  // src/bin.ts
959
- var import_node_fs2 = require("fs");
960
- async function start2() {
961
- const args = process.argv.slice(2);
962
- 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");
1684
+ var import_node_fs = require("fs");
1685
+ async function start() {
1686
+ const [configPath] = process.argv.slice(2);
1687
+ const isNext = (0, import_node_fs.existsSync)("next.config.js") || (0, import_node_fs.existsSync)("next.config.mjs") || (0, import_node_fs.existsSync)("next.config.ts");
963
1688
  if (isNext) {
964
- const { postInstall: postInstall3 } = await Promise.resolve().then(() => (init_next(), next_exports));
965
- await postInstall3(...args);
1689
+ const { postInstall: postInstall3 } = await Promise.resolve().then(() => (init_next2(), next_exports));
1690
+ await postInstall3(configPath);
966
1691
  } else {
967
- const { postInstall: postInstall3 } = await Promise.resolve().then(() => (init_postinstall(), postinstall_exports));
968
- await postInstall3(...args);
1692
+ const { postInstall: postInstall3 } = await Promise.resolve().then(() => (init_vite2(), vite_exports));
1693
+ await postInstall3(configPath);
969
1694
  }
970
1695
  }
971
- void start2();
1696
+ void start();