fumadocs-mdx 11.9.1 → 11.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/bin.cjs +1063 -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-CyU2Yl7A.d.cts → browser-B2G8uAF2.d.cts} +1 -1
  6. package/dist/{browser-DEsQvNRx.d.ts → browser-DrH7tKRi.d.ts} +1 -1
  7. package/dist/bun/index.cjs +669 -0
  8. package/dist/bun/index.d.cts +8 -0
  9. package/dist/bun/index.d.ts +8 -0
  10. package/dist/bun/index.js +53 -0
  11. package/dist/chunk-6Y5JDZHD.js +65 -0
  12. package/dist/chunk-CNKI574E.js +82 -0
  13. package/dist/{chunk-GX3THK2Q.js → chunk-IQAEAI4P.js} +25 -25
  14. package/dist/chunk-QJCCVMBJ.js +151 -0
  15. package/dist/{chunk-NUDEC6C5.js → chunk-UOOPSLFY.js} +1 -1
  16. package/dist/{chunk-COQ4VMK2.js → chunk-XXSKWWMB.js} +28 -61
  17. package/dist/config/index.d.cts +1 -1
  18. package/dist/config/index.d.ts +1 -1
  19. package/dist/config/zod-3.d.cts +1 -1
  20. package/dist/config/zod-3.d.ts +1 -1
  21. package/dist/{define-DnJzAZrj.d.cts → define-BH4bnHQl.d.cts} +6 -0
  22. package/dist/{define-DnJzAZrj.d.ts → define-BH4bnHQl.d.ts} +6 -0
  23. package/dist/loader-mdx.cjs +345 -265
  24. package/dist/loader-mdx.js +12 -80
  25. package/dist/next/index.cjs +15 -130
  26. package/dist/next/index.js +15 -33
  27. package/dist/node/loader.cjs +748 -0
  28. package/dist/node/loader.d.cts +5 -0
  29. package/dist/node/loader.d.ts +5 -0
  30. package/dist/node/loader.js +24 -0
  31. package/dist/postinstall-XV4WSHZP.js +9 -0
  32. package/dist/runtime/{async.cjs → next/async.cjs} +4 -4
  33. package/dist/runtime/{async.d.cts → next/async.d.cts} +3 -3
  34. package/dist/runtime/{async.d.ts → next/async.d.ts} +3 -3
  35. package/dist/runtime/{async.js → next/async.js} +6 -6
  36. package/dist/{index.cjs → runtime/next/index.cjs} +4 -6
  37. package/dist/{index.d.cts → runtime/next/index.d.cts} +3 -3
  38. package/dist/{index.d.ts → runtime/next/index.d.ts} +3 -3
  39. package/dist/{index.js → runtime/next/index.js} +1 -1
  40. package/dist/runtime/vite/browser.d.cts +2 -2
  41. package/dist/runtime/vite/browser.d.ts +2 -2
  42. package/dist/runtime/vite/server.d.cts +3 -3
  43. package/dist/runtime/vite/server.d.ts +3 -3
  44. package/dist/{types-WSHJKA8L.d.ts → types-DN9KrG7R.d.ts} +1 -1
  45. package/dist/{types-BmVgoqsr.d.cts → types-DT83Ijs6.d.cts} +1 -1
  46. package/dist/vite/index.cjs +440 -276
  47. package/dist/vite/index.d.cts +4 -1
  48. package/dist/vite/index.d.ts +4 -1
  49. package/dist/vite/index.js +19 -81
  50. package/package.json +24 -17
  51. package/bin.js +0 -5
  52. package/dist/chunk-UCY7OBZG.js +0 -12
@@ -200,7 +200,8 @@ var init_mdx_options = __esm({
200
200
  // src/vite/index.ts
201
201
  var vite_exports = {};
202
202
  __export(vite_exports, {
203
- default: () => mdx
203
+ default: () => mdx,
204
+ postInstall: () => postInstall
204
205
  });
205
206
  module.exports = __toCommonJS(vite_exports);
206
207
  var import_vite = require("vite");
@@ -255,14 +256,183 @@ function buildConfig(config) {
255
256
  };
256
257
  }
257
258
 
258
- // src/utils/build-mdx.ts
259
- var import_mdx = require("@mdx-js/mdx");
259
+ // src/vite/index.ts
260
+ var import_node_querystring2 = require("querystring");
260
261
 
261
- // src/mdx-plugins/remark-include.ts
262
- var import_unified = require("unified");
263
- var import_unist_util_visit2 = require("unist-util-visit");
264
- var path = __toESM(require("path"), 1);
265
- var fs = __toESM(require("fs/promises"), 1);
262
+ // src/utils/validation.ts
263
+ var import_picocolors = __toESM(require("picocolors"), 1);
264
+ var ValidationError = class extends Error {
265
+ constructor(message, issues) {
266
+ super(
267
+ `${message}:
268
+ ${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
269
+ );
270
+ this.title = message;
271
+ this.issues = issues;
272
+ }
273
+ toStringFormatted() {
274
+ return [
275
+ import_picocolors.default.bold(`[MDX] ${this.title}:`),
276
+ ...this.issues.map(
277
+ (issue) => import_picocolors.default.redBright(
278
+ `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
279
+ )
280
+ )
281
+ ].join("\n");
282
+ }
283
+ };
284
+ async function validate(schema, data, context, errorMessage) {
285
+ if (typeof schema === "function" && !("~standard" in schema)) {
286
+ schema = schema(context);
287
+ }
288
+ if ("~standard" in schema) {
289
+ const result = await schema["~standard"].validate(
290
+ data
291
+ );
292
+ if (result.issues) {
293
+ throw new ValidationError(errorMessage, result.issues);
294
+ }
295
+ return result.value;
296
+ }
297
+ return data;
298
+ }
299
+
300
+ // src/vite/index.ts
301
+ var fs6 = __toESM(require("fs/promises"), 1);
302
+ var path8 = __toESM(require("path"), 1);
303
+ var import_js_yaml2 = require("js-yaml");
304
+
305
+ // src/utils/import-formatter.ts
306
+ var import_node_path = __toESM(require("path"), 1);
307
+ function toImportPath(file, config) {
308
+ const ext = import_node_path.default.extname(file);
309
+ let filename;
310
+ if (ext === ".ts" && config.jsExtension) {
311
+ filename = file.substring(0, file.length - ext.length) + ".js";
312
+ } else if (ext === ".ts") {
313
+ filename = file.substring(0, file.length - ext.length);
314
+ } else {
315
+ filename = file;
316
+ }
317
+ let importPath;
318
+ if ("relativeTo" in config) {
319
+ importPath = import_node_path.default.relative(config.relativeTo, filename);
320
+ if (!import_node_path.default.isAbsolute(importPath) && !importPath.startsWith(".")) {
321
+ importPath = `./${importPath}`;
322
+ }
323
+ } else {
324
+ importPath = import_node_path.default.resolve(filename);
325
+ }
326
+ return importPath.replaceAll(import_node_path.default.sep, "/");
327
+ }
328
+ function ident(code, tab = 1) {
329
+ return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
330
+ }
331
+
332
+ // src/vite/generate-glob.ts
333
+ function generateGlob(name, patterns, globOptions) {
334
+ const options = {
335
+ ...globOptions,
336
+ query: {
337
+ ...globOptions?.query,
338
+ collection: name
339
+ }
340
+ };
341
+ return `import.meta.glob(${JSON.stringify(mapGlobPatterns(patterns))}, ${JSON.stringify(options, null, 2)})`;
342
+ }
343
+ function mapGlobPatterns(patterns) {
344
+ return patterns.map(enforceRelative);
345
+ }
346
+ function enforceRelative(file) {
347
+ if (file.startsWith("./")) return file;
348
+ if (file.startsWith("/")) return `.${file}`;
349
+ return `./${file}`;
350
+ }
351
+ function getGlobBase(collection) {
352
+ let dir = collection.dir;
353
+ if (Array.isArray(dir)) {
354
+ if (dir.length !== 1)
355
+ throw new Error(
356
+ `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
357
+ );
358
+ dir = dir[0];
359
+ }
360
+ return enforceRelative(dir);
361
+ }
362
+
363
+ // src/utils/collections.ts
364
+ function getSupportedFormats(collection) {
365
+ return {
366
+ doc: ["mdx", "md"],
367
+ meta: ["json", "yaml"]
368
+ }[collection.type];
369
+ }
370
+ function getGlobPatterns(collection) {
371
+ if (collection.files) return collection.files;
372
+ return [`**/*.{${getSupportedFormats(collection).join(",")}}`];
373
+ }
374
+
375
+ // src/vite/generate.ts
376
+ function docs(name, collection) {
377
+ const obj = [
378
+ ident(`doc: ${doc(name, collection.docs)}`),
379
+ ident(`meta: ${meta(name, collection.meta)}`)
380
+ ].join(",\n");
381
+ return `{
382
+ ${obj}
383
+ }`;
384
+ }
385
+ function doc(name, collection) {
386
+ const patterns = getGlobPatterns(collection);
387
+ const base = getGlobBase(collection);
388
+ const docGlob = generateGlob(name, patterns, {
389
+ base
390
+ });
391
+ if (collection.async) {
392
+ const headBlob = generateGlob(name, patterns, {
393
+ query: {
394
+ only: "frontmatter"
395
+ },
396
+ import: "frontmatter",
397
+ base
398
+ });
399
+ return `create.docLazy("${name}", "${base}", ${headBlob}, ${docGlob})`;
400
+ }
401
+ return `create.doc("${name}", "${base}", ${docGlob})`;
402
+ }
403
+ function meta(name, collection) {
404
+ const patterns = getGlobPatterns(collection);
405
+ const base = getGlobBase(collection);
406
+ return `create.meta("${name}", "${base}", ${generateGlob(name, patterns, {
407
+ import: "default",
408
+ base
409
+ })})`;
410
+ }
411
+ function entry(configPath, config, outDir, jsExtension) {
412
+ const lines = [
413
+ '/// <reference types="vite/client" />',
414
+ `import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
415
+ `import type * as Config from '${toImportPath(configPath, {
416
+ relativeTo: outDir,
417
+ jsExtension
418
+ })}';`,
419
+ "",
420
+ `export const create = fromConfig<typeof Config>();`
421
+ ];
422
+ for (const [name, collection] of config.collections.entries()) {
423
+ let body;
424
+ if (collection.type === "docs") {
425
+ body = docs(name, collection);
426
+ } else if (collection.type === "meta") {
427
+ body = meta(name, collection);
428
+ } else {
429
+ body = doc(name, collection);
430
+ }
431
+ lines.push("");
432
+ lines.push(`export const ${name} = ${body};`);
433
+ }
434
+ return lines.join("\n");
435
+ }
266
436
 
267
437
  // src/utils/fuma-matter.ts
268
438
  var import_js_yaml = require("js-yaml");
@@ -280,7 +450,46 @@ function fumaMatter(input) {
280
450
  return output;
281
451
  }
282
452
 
453
+ // src/utils/git-timestamp.ts
454
+ var import_node_path2 = __toESM(require("path"), 1);
455
+ var import_tinyexec = require("tinyexec");
456
+ var cache = /* @__PURE__ */ new Map();
457
+ async function getGitTimestamp(file) {
458
+ const cached = cache.get(file);
459
+ if (cached) return cached;
460
+ try {
461
+ const out = await (0, import_tinyexec.x)(
462
+ "git",
463
+ ["log", "-1", '--pretty="%ai"', import_node_path2.default.relative(process.cwd(), file)],
464
+ {
465
+ throwOnError: true
466
+ }
467
+ );
468
+ const time = new Date(out.stdout);
469
+ cache.set(file, time);
470
+ return time;
471
+ } catch {
472
+ return;
473
+ }
474
+ }
475
+
476
+ // src/utils/count-lines.ts
477
+ function countLines(s) {
478
+ let num = 0;
479
+ for (const c of s) {
480
+ if (c === "\n") num++;
481
+ }
482
+ return num;
483
+ }
484
+
485
+ // src/utils/build-mdx.ts
486
+ var import_mdx = require("@mdx-js/mdx");
487
+
283
488
  // src/mdx-plugins/remark-include.ts
489
+ var import_unified = require("unified");
490
+ var import_unist_util_visit2 = require("unist-util-visit");
491
+ var path3 = __toESM(require("path"), 1);
492
+ var fs = __toESM(require("fs/promises"), 1);
284
493
  var import_remark_parse = __toESM(require("remark-parse"), 1);
285
494
  var import_remark_mdx = __toESM(require("remark-mdx"), 1);
286
495
  var import_mdx_plugins = require("fumadocs-core/mdx-plugins");
@@ -335,7 +544,7 @@ ${e instanceof Error ? e.message : String(e)}`,
335
544
  { cause: e }
336
545
  );
337
546
  }
338
- const ext = path.extname(file);
547
+ const ext = path3.extname(file);
339
548
  data._compiler?.addDependency(file);
340
549
  if (params.lang || ext !== ".md" && ext !== ".mdx") {
341
550
  const lang = params.lang ?? ext.slice(1);
@@ -361,7 +570,7 @@ ${e instanceof Error ? e.message : String(e)}`,
361
570
  );
362
571
  parsed = extracted;
363
572
  }
364
- await update(parsed, path.dirname(file), data);
573
+ await update(parsed, path3.dirname(file), data);
365
574
  return parsed;
366
575
  }
367
576
  async function update(tree, directory, data) {
@@ -381,7 +590,7 @@ ${e instanceof Error ? e.message : String(e)}`,
381
590
  }
382
591
  }
383
592
  const { file: relativePath, section } = parseSpecifier(specifier);
384
- const file = path.resolve(
593
+ const file = path3.resolve(
385
594
  "cwd" in params ? process.cwd() : directory,
386
595
  relativePath
387
596
  );
@@ -399,7 +608,7 @@ ${e instanceof Error ? e.message : String(e)}`,
399
608
  await Promise.all(queue);
400
609
  }
401
610
  return async (tree, file) => {
402
- await update(tree, path.dirname(file.path), file.data);
611
+ await update(tree, path3.dirname(file.path), file.data);
403
612
  };
404
613
  }
405
614
  function getDefaultProcessor(format) {
@@ -409,12 +618,12 @@ function getDefaultProcessor(format) {
409
618
  }
410
619
 
411
620
  // src/utils/build-mdx.ts
412
- var cache = /* @__PURE__ */ new Map();
621
+ var cache2 = /* @__PURE__ */ new Map();
413
622
  async function buildMDX(cacheKey, source, options) {
414
623
  const { filePath, frontmatter, data, _compiler, ...rest } = options;
415
624
  function getProcessor(format) {
416
625
  const key = `${cacheKey}:${format}`;
417
- let processor = cache.get(key);
626
+ let processor = cache2.get(key);
418
627
  if (!processor) {
419
628
  processor = (0, import_mdx.createProcessor)({
420
629
  outputFormat: "program",
@@ -422,7 +631,7 @@ async function buildMDX(cacheKey, source, options) {
422
631
  remarkPlugins: [remarkInclude, ...rest.remarkPlugins ?? []],
423
632
  format
424
633
  });
425
- cache.set(key, processor);
634
+ cache2.set(key, processor);
426
635
  }
427
636
  return processor;
428
637
  }
@@ -440,229 +649,241 @@ async function buildMDX(cacheKey, source, options) {
440
649
  });
441
650
  }
442
651
 
443
- // src/vite/index.ts
444
- var import_node_querystring = require("querystring");
445
-
446
- // src/utils/count-lines.ts
447
- function countLines(s) {
448
- let num = 0;
449
- for (const c of s) {
450
- if (c === "\n") num++;
451
- }
452
- return num;
453
- }
454
-
455
- // src/utils/validation.ts
456
- var import_picocolors = __toESM(require("picocolors"), 1);
457
- var ValidationError = class extends Error {
458
- constructor(message, issues) {
459
- super(
460
- `${message}:
461
- ${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
462
- );
463
- this.title = message;
464
- this.issues = issues;
465
- }
466
- toStringFormatted() {
467
- return [
468
- import_picocolors.default.bold(`[MDX] ${this.title}:`),
469
- ...this.issues.map(
470
- (issue) => import_picocolors.default.redBright(
471
- `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
472
- )
473
- )
474
- ].join("\n");
475
- }
476
- };
477
- async function validate(schema, data, context, errorMessage) {
478
- if (typeof schema === "function" && !("~standard" in schema)) {
479
- schema = schema(context);
480
- }
481
- if ("~standard" in schema) {
482
- const result = await schema["~standard"].validate(
483
- data
652
+ // src/loaders/mdx.ts
653
+ var import_zod = require("zod");
654
+ var import_promises = __toESM(require("fs/promises"), 1);
655
+ var import_node_path3 = __toESM(require("path"), 1);
656
+ var import_node_crypto = require("crypto");
657
+ var querySchema = import_zod.z.object({
658
+ only: import_zod.z.literal(["frontmatter", "all"]).default("all"),
659
+ collection: import_zod.z.string().optional(),
660
+ hash: import_zod.z.string().describe(
661
+ "the hash of config, used for revalidation on Turbopack/Webpack."
662
+ ).optional()
663
+ }).loose();
664
+ var cacheEntry = import_zod.z.object({
665
+ code: import_zod.z.string(),
666
+ map: import_zod.z.any().optional(),
667
+ hash: import_zod.z.string().optional()
668
+ });
669
+ function createMdxLoader(configLoader) {
670
+ return async ({
671
+ source: value,
672
+ development: isDevelopment,
673
+ query,
674
+ compiler,
675
+ filePath
676
+ }) => {
677
+ const matter = fumaMatter(value);
678
+ const parsed = querySchema.parse(query);
679
+ const loaded = await configLoader.getConfig(parsed.hash);
680
+ const cacheDir = isDevelopment ? void 0 : loaded.global.experimentalBuildCache;
681
+ const cacheKey = `${parsed.hash}_${parsed.collection ?? "global"}_${generateCacheHash(filePath)}`;
682
+ if (cacheDir) {
683
+ const cached = await import_promises.default.readFile(import_node_path3.default.join(cacheDir, cacheKey)).then((content) => cacheEntry.parse(JSON.parse(content.toString()))).catch(() => null);
684
+ if (cached && cached.hash === generateCacheHash(value)) return cached;
685
+ }
686
+ const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
687
+ let schema;
688
+ let mdxOptions;
689
+ switch (collection?.type) {
690
+ case "doc":
691
+ mdxOptions = collection.mdxOptions;
692
+ schema = collection.schema;
693
+ break;
694
+ case "docs":
695
+ mdxOptions = collection.docs.mdxOptions;
696
+ schema = collection.docs.schema;
697
+ break;
698
+ }
699
+ if (schema) {
700
+ matter.data = await validate(
701
+ schema,
702
+ matter.data,
703
+ {
704
+ source: value,
705
+ path: filePath
706
+ },
707
+ `invalid frontmatter in ${filePath}`
708
+ );
709
+ }
710
+ if (parsed.only === "frontmatter") {
711
+ return {
712
+ code: `export const frontmatter = ${JSON.stringify(matter.data)}`,
713
+ map: null
714
+ };
715
+ }
716
+ const data = {};
717
+ if (loaded.global.lastModifiedTime === "git") {
718
+ data.lastModified = (await getGitTimestamp(filePath))?.getTime();
719
+ }
720
+ const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
721
+ const compiled = await buildMDX(
722
+ `${parsed.hash ?? ""}:${parsed.collection ?? "global"}`,
723
+ "\n".repeat(lineOffset) + matter.content,
724
+ {
725
+ development: isDevelopment,
726
+ ...mdxOptions ?? await loaded.getDefaultMDXOptions(),
727
+ data,
728
+ filePath,
729
+ frontmatter: matter.data,
730
+ _compiler: compiler
731
+ }
484
732
  );
485
- if (result.issues) {
486
- throw new ValidationError(errorMessage, result.issues);
733
+ const out = {
734
+ code: String(compiled.value),
735
+ map: compiled.map
736
+ };
737
+ if (cacheDir) {
738
+ await import_promises.default.mkdir(cacheDir, { recursive: true });
739
+ await import_promises.default.writeFile(
740
+ import_node_path3.default.join(cacheDir, cacheKey),
741
+ JSON.stringify({
742
+ ...out,
743
+ hash: generateCacheHash(value)
744
+ })
745
+ );
487
746
  }
488
- return result.value;
489
- }
490
- return data;
747
+ return out;
748
+ };
749
+ }
750
+ function generateCacheHash(input) {
751
+ return (0, import_node_crypto.createHash)("md5").update(input).digest("hex");
491
752
  }
492
753
 
493
- // src/vite/index.ts
494
- var import_zod = require("zod");
495
- var fs2 = __toESM(require("fs/promises"), 1);
496
- var path4 = __toESM(require("path"), 1);
497
- var import_js_yaml2 = require("js-yaml");
498
-
499
- // src/utils/git-timestamp.ts
500
- var import_node_path = __toESM(require("path"), 1);
501
- var import_tinyexec = require("tinyexec");
502
- var cache2 = /* @__PURE__ */ new Map();
503
- async function getGitTimestamp(file) {
504
- const cached = cache2.get(file);
505
- if (cached) return cached;
754
+ // src/utils/config.ts
755
+ var fs3 = __toESM(require("fs/promises"), 1);
756
+ var path5 = __toESM(require("path"), 1);
757
+ var import_node_url = require("url");
758
+ function findConfigFile() {
759
+ return path5.resolve("source.config.ts");
760
+ }
761
+ var cache3 = null;
762
+ async function isZod3() {
506
763
  try {
507
- const out = await (0, import_tinyexec.x)(
508
- "git",
509
- ["log", "-1", '--pretty="%ai"', import_node_path.default.relative(process.cwd(), file)],
510
- {
511
- throwOnError: true
512
- }
764
+ const content = JSON.parse(
765
+ (await fs3.readFile("node_modules/zod/package.json")).toString()
513
766
  );
514
- const time = new Date(out.stdout);
515
- cache2.set(file, time);
516
- return time;
767
+ const version = content.version;
768
+ return typeof version === "string" && version.startsWith("3.");
517
769
  } catch {
518
- return;
519
- }
520
- }
521
-
522
- // src/utils/import-formatter.ts
523
- var import_node_path2 = __toESM(require("path"), 1);
524
- function toImportPath(file, config) {
525
- const ext = import_node_path2.default.extname(file);
526
- let filename;
527
- if (ext === ".ts" && config.jsExtension) {
528
- filename = file.substring(0, file.length - ext.length) + ".js";
529
- } else if (ext === ".ts") {
530
- filename = file.substring(0, file.length - ext.length);
531
- } else {
532
- filename = file;
533
- }
534
- let importPath;
535
- if ("relativeTo" in config) {
536
- importPath = import_node_path2.default.relative(config.relativeTo, filename);
537
- if (!import_node_path2.default.isAbsolute(importPath) && !importPath.startsWith(".")) {
538
- importPath = `./${importPath}`;
539
- }
540
- } else {
541
- importPath = import_node_path2.default.resolve(filename);
770
+ return false;
542
771
  }
543
- return importPath.replaceAll(import_node_path2.default.sep, "/");
544
- }
545
- function ident(code, tab = 1) {
546
- return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
547
772
  }
548
-
549
- // src/vite/generate-glob.ts
550
- function generateGlob(name, patterns, globOptions) {
551
- const options = {
552
- ...globOptions,
553
- query: {
554
- ...globOptions?.query,
555
- collection: name
773
+ function createCompatZodPlugin() {
774
+ return {
775
+ name: "replace-zod-import",
776
+ async setup(build) {
777
+ const usingZod3 = await isZod3();
778
+ if (!usingZod3) return;
779
+ console.warn(
780
+ "[Fumadocs MDX] Noticed Zod v3 in your node_modules, we recommend upgrading to Zod v4 for better compatibility."
781
+ );
782
+ build.onResolve({ filter: /^fumadocs-mdx\/config$/ }, () => {
783
+ return {
784
+ path: "fumadocs-mdx/config/zod-3",
785
+ external: true
786
+ };
787
+ });
556
788
  }
557
789
  };
558
- return `import.meta.glob(${JSON.stringify(mapGlobPatterns(patterns))}, ${JSON.stringify(options, null, 2)})`;
559
- }
560
- function mapGlobPatterns(patterns) {
561
- return patterns.map(enforceRelative);
562
790
  }
563
- function enforceRelative(file) {
564
- if (file.startsWith("./")) return file;
565
- if (file.startsWith("/")) return `.${file}`;
566
- return `./${file}`;
791
+ async function compileConfig(configPath, outDir) {
792
+ const { build } = await import("esbuild");
793
+ const transformed = await build({
794
+ entryPoints: [{ in: configPath, out: "source.config" }],
795
+ bundle: true,
796
+ outdir: outDir,
797
+ target: "node20",
798
+ write: true,
799
+ platform: "node",
800
+ format: "esm",
801
+ packages: "external",
802
+ plugins: [createCompatZodPlugin()],
803
+ outExtension: {
804
+ ".js": ".mjs"
805
+ },
806
+ allowOverwrite: true
807
+ });
808
+ if (transformed.errors.length > 0) {
809
+ throw new Error("failed to compile configuration file");
810
+ }
567
811
  }
568
- function getGlobBase(collection) {
569
- let dir = collection.dir;
570
- if (Array.isArray(dir)) {
571
- if (dir.length !== 1)
572
- throw new Error(
573
- `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
574
- );
575
- dir = dir[0];
812
+ async function loadConfig(configPath, outDir, hash, build = false) {
813
+ if (cache3 && cache3.hash === hash) {
814
+ return await cache3.config;
576
815
  }
577
- return enforceRelative(dir);
816
+ if (build) await compileConfig(configPath, outDir);
817
+ const url = (0, import_node_url.pathToFileURL)(path5.resolve(outDir, "source.config.mjs"));
818
+ const config = import(`${url.href}?hash=${hash}`).then((loaded) => {
819
+ return buildConfig(
820
+ // every call to `loadConfig` will cause the previous cache to be ignored
821
+ loaded
822
+ );
823
+ });
824
+ if (hash) cache3 = { config, hash };
825
+ return await config;
578
826
  }
579
827
 
580
- // src/utils/collections.ts
581
- function getSupportedFormats(collection) {
828
+ // src/loaders/config-loader.ts
829
+ function resolvedConfig(loaded) {
582
830
  return {
583
- doc: ["mdx", "md"],
584
- meta: ["json", "yaml"]
585
- }[collection.type];
586
- }
587
- function getGlobPatterns(collection) {
588
- if (collection.files) return collection.files;
589
- return [`**/*.{${getSupportedFormats(collection).join(",")}}`];
831
+ getConfig() {
832
+ return loaded;
833
+ }
834
+ };
590
835
  }
591
836
 
592
- // src/vite/generate.ts
593
- function docs(name, collection) {
594
- const obj = [
595
- ident(`doc: ${doc(name, collection.docs)}`),
596
- ident(`meta: ${meta(name, collection.meta)}`)
597
- ].join(",\n");
598
- return `{
599
- ${obj}
600
- }`;
601
- }
602
- function doc(name, collection) {
603
- const patterns = getGlobPatterns(collection);
604
- const base = getGlobBase(collection);
605
- const docGlob = generateGlob(name, patterns, {
606
- base
607
- });
608
- if (collection.async) {
609
- const headBlob = generateGlob(name, patterns, {
610
- query: {
611
- only: "frontmatter"
612
- },
613
- import: "frontmatter",
614
- base
837
+ // src/loaders/adapter.ts
838
+ var import_node_url2 = require("url");
839
+ var import_promises2 = __toESM(require("fs/promises"), 1);
840
+ var import_node_querystring = require("querystring");
841
+ var import_node_path4 = __toESM(require("path"), 1);
842
+ function toVite(loader) {
843
+ return async function(file, query, value) {
844
+ const result = await loader({
845
+ filePath: file,
846
+ query: (0, import_node_querystring.parse)(query),
847
+ source: value,
848
+ development: this.environment.mode === "dev",
849
+ compiler: {
850
+ addDependency: (file2) => {
851
+ this.addWatchFile(file2);
852
+ }
853
+ }
615
854
  });
616
- return `create.docLazy("${name}", "${base}", ${headBlob}, ${docGlob})`;
617
- }
618
- return `create.doc("${name}", "${base}", ${docGlob})`;
619
- }
620
- function meta(name, collection) {
621
- const patterns = getGlobPatterns(collection);
622
- const base = getGlobBase(collection);
623
- return `create.meta("${name}", "${base}", ${generateGlob(name, patterns, {
624
- import: "default",
625
- base
626
- })})`;
855
+ return {
856
+ code: result.code,
857
+ map: result.map
858
+ };
859
+ };
627
860
  }
628
- function entry(configPath, config, outDir, jsExtension) {
629
- const lines = [
630
- '/// <reference types="vite/client" />',
631
- `import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
632
- `import type * as Config from '${toImportPath(configPath, {
633
- relativeTo: outDir,
634
- jsExtension
635
- })}';`,
636
- "",
637
- `export const create = fromConfig<typeof Config>();`
638
- ];
639
- for (const [name, collection] of config.collections.entries()) {
640
- let body;
641
- if (collection.type === "docs") {
642
- body = docs(name, collection);
643
- } else if (collection.type === "meta") {
644
- body = meta(name, collection);
645
- } else {
646
- body = doc(name, collection);
647
- }
648
- lines.push("");
649
- lines.push(`export const ${name} = ${body};`);
861
+
862
+ // src/vite/postinstall.ts
863
+ var import_promises3 = __toESM(require("fs/promises"), 1);
864
+ var import_node_path5 = __toESM(require("path"), 1);
865
+ async function postInstall(configPath = findConfigFile(), outDir, addJsExtension = false) {
866
+ const config = await loadConfig(configPath, "node_modules", void 0, true);
867
+ const outFile = "source.generated.ts";
868
+ if (outDir) {
869
+ await import_promises3.default.mkdir(outDir, { recursive: true });
650
870
  }
651
- return lines.join("\n");
871
+ await import_promises3.default.writeFile(
872
+ outDir ? import_node_path5.default.join(outDir, outFile) : outFile,
873
+ entry(configPath, config, outDir ?? process.cwd(), addJsExtension)
874
+ );
875
+ console.log("[MDX] types generated");
652
876
  }
653
877
 
654
878
  // src/vite/index.ts
655
879
  var FumadocsDeps = ["fumadocs-core", "fumadocs-ui", "fumadocs-openapi"];
656
- var querySchema = import_zod.z.object({
657
- only: import_zod.z.literal(["frontmatter", "all"]).default("all"),
658
- collection: import_zod.z.string().optional()
659
- }).loose();
660
880
  function mdx(config, options = {}) {
661
881
  const { generateIndexFile = true, configPath = "source.config.ts" } = options;
662
882
  const loaded = buildConfig(config);
663
- async function transformMeta(path5, query, value) {
664
- const isJson = path5.endsWith(".json");
665
- const parsed = (0, import_node_querystring.parse)(query);
883
+ const mdxLoader = toVite(createMdxLoader(resolvedConfig(loaded)));
884
+ async function transformMeta(path9, query, value) {
885
+ const isJson = path9.endsWith(".json");
886
+ const parsed = (0, import_node_querystring2.parse)(query);
666
887
  const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
667
888
  if (!collection) return null;
668
889
  let schema;
@@ -684,75 +905,14 @@ function mdx(config, options = {}) {
684
905
  const out = await validate(
685
906
  schema,
686
907
  data,
687
- { path: path5, source: value },
688
- `invalid data in ${path5}`
908
+ { path: path9, source: value },
909
+ `invalid data in ${path9}`
689
910
  );
690
911
  return {
691
912
  code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
692
913
  map: null
693
914
  };
694
915
  }
695
- async function transformContent(file, query, value) {
696
- const matter = fumaMatter(value);
697
- const isDevelopment = this.environment.mode === "dev";
698
- const parsed = querySchema.parse((0, import_node_querystring.parse)(query));
699
- const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
700
- let schema;
701
- let mdxOptions;
702
- switch (collection?.type) {
703
- case "doc":
704
- mdxOptions = collection.mdxOptions;
705
- schema = collection.schema;
706
- break;
707
- case "docs":
708
- mdxOptions = collection.docs.mdxOptions;
709
- schema = collection.docs.schema;
710
- break;
711
- }
712
- if (schema) {
713
- matter.data = await validate(
714
- schema,
715
- matter.data,
716
- {
717
- source: value,
718
- path: file
719
- },
720
- `invalid frontmatter in ${file}`
721
- );
722
- }
723
- if (parsed.only === "frontmatter") {
724
- return {
725
- code: `export const frontmatter = ${JSON.stringify(matter.data)}`,
726
- map: null
727
- };
728
- }
729
- const data = {};
730
- if (loaded.global.lastModifiedTime === "git") {
731
- data.lastModified = (await getGitTimestamp(file))?.getTime();
732
- }
733
- mdxOptions ??= await loaded.getDefaultMDXOptions();
734
- const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
735
- const compiled = await buildMDX(
736
- parsed.collection ?? "global",
737
- "\n".repeat(lineOffset) + matter.content,
738
- {
739
- development: isDevelopment,
740
- ...mdxOptions,
741
- data,
742
- filePath: file,
743
- frontmatter: matter.data,
744
- _compiler: {
745
- addDependency: (file2) => {
746
- this.addWatchFile(file2);
747
- }
748
- }
749
- }
750
- );
751
- return {
752
- code: String(compiled.value),
753
- map: compiled.map
754
- };
755
- }
756
916
  return {
757
917
  name: "fumadocs-mdx",
758
918
  // needed, otherwise other plugins will be executed before our `transform`.
@@ -773,8 +933,8 @@ function mdx(config, options = {}) {
773
933
  console.log("[Fumadocs MDX] Generating index files");
774
934
  const outDir = process.cwd();
775
935
  const outFile = "source.generated.ts";
776
- await fs2.writeFile(
777
- path4.join(outDir, outFile),
936
+ await fs6.writeFile(
937
+ path8.join(outDir, outFile),
778
938
  entry(
779
939
  configPath,
780
940
  loaded,
@@ -785,12 +945,12 @@ function mdx(config, options = {}) {
785
945
  },
786
946
  async transform(value, id) {
787
947
  const [file, query = ""] = id.split("?");
788
- const ext = path4.extname(file);
948
+ const ext = path8.extname(file);
789
949
  try {
790
950
  if ([".yaml", ".json"].includes(ext))
791
951
  return await transformMeta(file, query, value);
792
952
  if ([".md", ".mdx"].includes(ext))
793
- return await transformContent.call(this, file, query, value);
953
+ return await mdxLoader.call(this, file, query, value);
794
954
  } catch (e) {
795
955
  if (e instanceof ValidationError) {
796
956
  throw new Error(e.toStringFormatted());
@@ -800,3 +960,7 @@ function mdx(config, options = {}) {
800
960
  }
801
961
  };
802
962
  }
963
+ // Annotate the CommonJS export names for ESM import in node:
964
+ 0 && (module.exports = {
965
+ postInstall
966
+ });