fumadocs-mdx 11.9.1 → 11.10.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 (37) hide show
  1. package/dist/{browser-CyU2Yl7A.d.cts → browser-B2G8uAF2.d.cts} +1 -1
  2. package/dist/{browser-DEsQvNRx.d.ts → browser-DrH7tKRi.d.ts} +1 -1
  3. package/dist/bun/index.cjs +667 -0
  4. package/dist/bun/index.d.cts +8 -0
  5. package/dist/bun/index.d.ts +8 -0
  6. package/dist/bun/index.js +50 -0
  7. package/dist/{chunk-766EAFX6.js → chunk-2HKRTQYP.js} +64 -0
  8. package/dist/chunk-5XJM5RPV.js +149 -0
  9. package/dist/chunk-NVX3U5YE.js +82 -0
  10. package/dist/config/index.d.cts +1 -1
  11. package/dist/config/index.d.ts +1 -1
  12. package/dist/config/zod-3.d.cts +1 -1
  13. package/dist/config/zod-3.d.ts +1 -1
  14. package/dist/{define-DnJzAZrj.d.cts → define-BH4bnHQl.d.cts} +6 -0
  15. package/dist/{define-DnJzAZrj.d.ts → define-BH4bnHQl.d.ts} +6 -0
  16. package/dist/index.d.cts +2 -2
  17. package/dist/index.d.ts +2 -2
  18. package/dist/loader-mdx.cjs +345 -265
  19. package/dist/loader-mdx.js +11 -80
  20. package/dist/next/index.js +4 -6
  21. package/dist/node/loader.cjs +748 -0
  22. package/dist/node/loader.d.cts +5 -0
  23. package/dist/node/loader.d.ts +5 -0
  24. package/dist/node/loader.js +23 -0
  25. package/dist/runtime/async.d.cts +2 -2
  26. package/dist/runtime/async.d.ts +2 -2
  27. package/dist/runtime/vite/browser.d.cts +2 -2
  28. package/dist/runtime/vite/browser.d.ts +2 -2
  29. package/dist/runtime/vite/server.d.cts +3 -3
  30. package/dist/runtime/vite/server.d.ts +3 -3
  31. package/dist/{types-WSHJKA8L.d.ts → types-DN9KrG7R.d.ts} +1 -1
  32. package/dist/{types-BmVgoqsr.d.cts → types-DT83Ijs6.d.cts} +1 -1
  33. package/dist/vite/index.cjs +356 -282
  34. package/dist/vite/index.js +12 -78
  35. package/package.json +17 -8
  36. package/dist/chunk-GX3THK2Q.js +0 -66
  37. package/dist/chunk-UCY7OBZG.js +0 -12
@@ -255,14 +255,183 @@ function buildConfig(config) {
255
255
  };
256
256
  }
257
257
 
258
- // src/utils/build-mdx.ts
259
- var import_mdx = require("@mdx-js/mdx");
258
+ // src/vite/index.ts
259
+ var import_node_querystring2 = require("querystring");
260
260
 
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);
261
+ // src/utils/validation.ts
262
+ var import_picocolors = __toESM(require("picocolors"), 1);
263
+ var ValidationError = class extends Error {
264
+ constructor(message, issues) {
265
+ super(
266
+ `${message}:
267
+ ${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
268
+ );
269
+ this.title = message;
270
+ this.issues = issues;
271
+ }
272
+ toStringFormatted() {
273
+ return [
274
+ import_picocolors.default.bold(`[MDX] ${this.title}:`),
275
+ ...this.issues.map(
276
+ (issue) => import_picocolors.default.redBright(
277
+ `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
278
+ )
279
+ )
280
+ ].join("\n");
281
+ }
282
+ };
283
+ async function validate(schema, data, context, errorMessage) {
284
+ if (typeof schema === "function" && !("~standard" in schema)) {
285
+ schema = schema(context);
286
+ }
287
+ if ("~standard" in schema) {
288
+ const result = await schema["~standard"].validate(
289
+ data
290
+ );
291
+ if (result.issues) {
292
+ throw new ValidationError(errorMessage, result.issues);
293
+ }
294
+ return result.value;
295
+ }
296
+ return data;
297
+ }
298
+
299
+ // src/vite/index.ts
300
+ var fs5 = __toESM(require("fs/promises"), 1);
301
+ var path7 = __toESM(require("path"), 1);
302
+ var import_js_yaml2 = require("js-yaml");
303
+
304
+ // src/utils/import-formatter.ts
305
+ var import_node_path = __toESM(require("path"), 1);
306
+ function toImportPath(file, config) {
307
+ const ext = import_node_path.default.extname(file);
308
+ let filename;
309
+ if (ext === ".ts" && config.jsExtension) {
310
+ filename = file.substring(0, file.length - ext.length) + ".js";
311
+ } else if (ext === ".ts") {
312
+ filename = file.substring(0, file.length - ext.length);
313
+ } else {
314
+ filename = file;
315
+ }
316
+ let importPath;
317
+ if ("relativeTo" in config) {
318
+ importPath = import_node_path.default.relative(config.relativeTo, filename);
319
+ if (!import_node_path.default.isAbsolute(importPath) && !importPath.startsWith(".")) {
320
+ importPath = `./${importPath}`;
321
+ }
322
+ } else {
323
+ importPath = import_node_path.default.resolve(filename);
324
+ }
325
+ return importPath.replaceAll(import_node_path.default.sep, "/");
326
+ }
327
+ function ident(code, tab = 1) {
328
+ return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
329
+ }
330
+
331
+ // src/vite/generate-glob.ts
332
+ function generateGlob(name, patterns, globOptions) {
333
+ const options = {
334
+ ...globOptions,
335
+ query: {
336
+ ...globOptions?.query,
337
+ collection: name
338
+ }
339
+ };
340
+ return `import.meta.glob(${JSON.stringify(mapGlobPatterns(patterns))}, ${JSON.stringify(options, null, 2)})`;
341
+ }
342
+ function mapGlobPatterns(patterns) {
343
+ return patterns.map(enforceRelative);
344
+ }
345
+ function enforceRelative(file) {
346
+ if (file.startsWith("./")) return file;
347
+ if (file.startsWith("/")) return `.${file}`;
348
+ return `./${file}`;
349
+ }
350
+ function getGlobBase(collection) {
351
+ let dir = collection.dir;
352
+ if (Array.isArray(dir)) {
353
+ if (dir.length !== 1)
354
+ throw new Error(
355
+ `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
356
+ );
357
+ dir = dir[0];
358
+ }
359
+ return enforceRelative(dir);
360
+ }
361
+
362
+ // src/utils/collections.ts
363
+ function getSupportedFormats(collection) {
364
+ return {
365
+ doc: ["mdx", "md"],
366
+ meta: ["json", "yaml"]
367
+ }[collection.type];
368
+ }
369
+ function getGlobPatterns(collection) {
370
+ if (collection.files) return collection.files;
371
+ return [`**/*.{${getSupportedFormats(collection).join(",")}}`];
372
+ }
373
+
374
+ // src/vite/generate.ts
375
+ function docs(name, collection) {
376
+ const obj = [
377
+ ident(`doc: ${doc(name, collection.docs)}`),
378
+ ident(`meta: ${meta(name, collection.meta)}`)
379
+ ].join(",\n");
380
+ return `{
381
+ ${obj}
382
+ }`;
383
+ }
384
+ function doc(name, collection) {
385
+ const patterns = getGlobPatterns(collection);
386
+ const base = getGlobBase(collection);
387
+ const docGlob = generateGlob(name, patterns, {
388
+ base
389
+ });
390
+ if (collection.async) {
391
+ const headBlob = generateGlob(name, patterns, {
392
+ query: {
393
+ only: "frontmatter"
394
+ },
395
+ import: "frontmatter",
396
+ base
397
+ });
398
+ return `create.docLazy("${name}", "${base}", ${headBlob}, ${docGlob})`;
399
+ }
400
+ return `create.doc("${name}", "${base}", ${docGlob})`;
401
+ }
402
+ function meta(name, collection) {
403
+ const patterns = getGlobPatterns(collection);
404
+ const base = getGlobBase(collection);
405
+ return `create.meta("${name}", "${base}", ${generateGlob(name, patterns, {
406
+ import: "default",
407
+ base
408
+ })})`;
409
+ }
410
+ function entry(configPath, config, outDir, jsExtension) {
411
+ const lines = [
412
+ '/// <reference types="vite/client" />',
413
+ `import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
414
+ `import type * as Config from '${toImportPath(configPath, {
415
+ relativeTo: outDir,
416
+ jsExtension
417
+ })}';`,
418
+ "",
419
+ `export const create = fromConfig<typeof Config>();`
420
+ ];
421
+ for (const [name, collection] of config.collections.entries()) {
422
+ let body;
423
+ if (collection.type === "docs") {
424
+ body = docs(name, collection);
425
+ } else if (collection.type === "meta") {
426
+ body = meta(name, collection);
427
+ } else {
428
+ body = doc(name, collection);
429
+ }
430
+ lines.push("");
431
+ lines.push(`export const ${name} = ${body};`);
432
+ }
433
+ return lines.join("\n");
434
+ }
266
435
 
267
436
  // src/utils/fuma-matter.ts
268
437
  var import_js_yaml = require("js-yaml");
@@ -280,7 +449,46 @@ function fumaMatter(input) {
280
449
  return output;
281
450
  }
282
451
 
452
+ // src/utils/git-timestamp.ts
453
+ var import_node_path2 = __toESM(require("path"), 1);
454
+ var import_tinyexec = require("tinyexec");
455
+ var cache = /* @__PURE__ */ new Map();
456
+ async function getGitTimestamp(file) {
457
+ const cached = cache.get(file);
458
+ if (cached) return cached;
459
+ try {
460
+ const out = await (0, import_tinyexec.x)(
461
+ "git",
462
+ ["log", "-1", '--pretty="%ai"', import_node_path2.default.relative(process.cwd(), file)],
463
+ {
464
+ throwOnError: true
465
+ }
466
+ );
467
+ const time = new Date(out.stdout);
468
+ cache.set(file, time);
469
+ return time;
470
+ } catch {
471
+ return;
472
+ }
473
+ }
474
+
475
+ // src/utils/count-lines.ts
476
+ function countLines(s) {
477
+ let num = 0;
478
+ for (const c of s) {
479
+ if (c === "\n") num++;
480
+ }
481
+ return num;
482
+ }
483
+
484
+ // src/utils/build-mdx.ts
485
+ var import_mdx = require("@mdx-js/mdx");
486
+
283
487
  // src/mdx-plugins/remark-include.ts
488
+ var import_unified = require("unified");
489
+ var import_unist_util_visit2 = require("unist-util-visit");
490
+ var path3 = __toESM(require("path"), 1);
491
+ var fs = __toESM(require("fs/promises"), 1);
284
492
  var import_remark_parse = __toESM(require("remark-parse"), 1);
285
493
  var import_remark_mdx = __toESM(require("remark-mdx"), 1);
286
494
  var import_mdx_plugins = require("fumadocs-core/mdx-plugins");
@@ -335,7 +543,7 @@ ${e instanceof Error ? e.message : String(e)}`,
335
543
  { cause: e }
336
544
  );
337
545
  }
338
- const ext = path.extname(file);
546
+ const ext = path3.extname(file);
339
547
  data._compiler?.addDependency(file);
340
548
  if (params.lang || ext !== ".md" && ext !== ".mdx") {
341
549
  const lang = params.lang ?? ext.slice(1);
@@ -361,7 +569,7 @@ ${e instanceof Error ? e.message : String(e)}`,
361
569
  );
362
570
  parsed = extracted;
363
571
  }
364
- await update(parsed, path.dirname(file), data);
572
+ await update(parsed, path3.dirname(file), data);
365
573
  return parsed;
366
574
  }
367
575
  async function update(tree, directory, data) {
@@ -381,7 +589,7 @@ ${e instanceof Error ? e.message : String(e)}`,
381
589
  }
382
590
  }
383
591
  const { file: relativePath, section } = parseSpecifier(specifier);
384
- const file = path.resolve(
592
+ const file = path3.resolve(
385
593
  "cwd" in params ? process.cwd() : directory,
386
594
  relativePath
387
595
  );
@@ -399,7 +607,7 @@ ${e instanceof Error ? e.message : String(e)}`,
399
607
  await Promise.all(queue);
400
608
  }
401
609
  return async (tree, file) => {
402
- await update(tree, path.dirname(file.path), file.data);
610
+ await update(tree, path3.dirname(file.path), file.data);
403
611
  };
404
612
  }
405
613
  function getDefaultProcessor(format) {
@@ -409,12 +617,12 @@ function getDefaultProcessor(format) {
409
617
  }
410
618
 
411
619
  // src/utils/build-mdx.ts
412
- var cache = /* @__PURE__ */ new Map();
620
+ var cache2 = /* @__PURE__ */ new Map();
413
621
  async function buildMDX(cacheKey, source, options) {
414
622
  const { filePath, frontmatter, data, _compiler, ...rest } = options;
415
623
  function getProcessor(format) {
416
624
  const key = `${cacheKey}:${format}`;
417
- let processor = cache.get(key);
625
+ let processor = cache2.get(key);
418
626
  if (!processor) {
419
627
  processor = (0, import_mdx.createProcessor)({
420
628
  outputFormat: "program",
@@ -422,7 +630,7 @@ async function buildMDX(cacheKey, source, options) {
422
630
  remarkPlugins: [remarkInclude, ...rest.remarkPlugins ?? []],
423
631
  format
424
632
  });
425
- cache.set(key, processor);
633
+ cache2.set(key, processor);
426
634
  }
427
635
  return processor;
428
636
  }
@@ -440,262 +648,40 @@ async function buildMDX(cacheKey, source, options) {
440
648
  });
441
649
  }
442
650
 
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
484
- );
485
- if (result.issues) {
486
- throw new ValidationError(errorMessage, result.issues);
487
- }
488
- return result.value;
489
- }
490
- return data;
491
- }
492
-
493
- // src/vite/index.ts
651
+ // src/loaders/mdx.ts
494
652
  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;
506
- 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
- }
513
- );
514
- const time = new Date(out.stdout);
515
- cache2.set(file, time);
516
- return time;
517
- } 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);
542
- }
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
- }
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
556
- }
557
- };
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
- }
563
- function enforceRelative(file) {
564
- if (file.startsWith("./")) return file;
565
- if (file.startsWith("/")) return `.${file}`;
566
- return `./${file}`;
567
- }
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];
576
- }
577
- return enforceRelative(dir);
578
- }
579
-
580
- // src/utils/collections.ts
581
- function getSupportedFormats(collection) {
582
- 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(",")}}`];
590
- }
591
-
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
615
- });
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
- })})`;
627
- }
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};`);
650
- }
651
- return lines.join("\n");
652
- }
653
-
654
- // src/vite/index.ts
655
- var FumadocsDeps = ["fumadocs-core", "fumadocs-ui", "fumadocs-openapi"];
653
+ var import_promises = __toESM(require("fs/promises"), 1);
654
+ var import_node_path3 = __toESM(require("path"), 1);
655
+ var import_node_crypto = require("crypto");
656
656
  var querySchema = import_zod.z.object({
657
657
  only: import_zod.z.literal(["frontmatter", "all"]).default("all"),
658
- collection: import_zod.z.string().optional()
658
+ collection: import_zod.z.string().optional(),
659
+ hash: import_zod.z.string().describe(
660
+ "the hash of config, used for revalidation on Turbopack/Webpack."
661
+ ).optional()
659
662
  }).loose();
660
- function mdx(config, options = {}) {
661
- const { generateIndexFile = true, configPath = "source.config.ts" } = options;
662
- 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);
666
- const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
667
- if (!collection) return null;
668
- let schema;
669
- switch (collection.type) {
670
- case "meta":
671
- schema = collection.schema;
672
- break;
673
- case "docs":
674
- schema = collection.meta.schema;
675
- break;
676
- }
677
- if (!schema) return null;
678
- let data;
679
- try {
680
- data = isJson ? JSON.parse(value) : (0, import_js_yaml2.load)(value);
681
- } catch {
682
- return null;
683
- }
684
- const out = await validate(
685
- schema,
686
- data,
687
- { path: path5, source: value },
688
- `invalid data in ${path5}`
689
- );
690
- return {
691
- code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
692
- map: null
693
- };
694
- }
695
- async function transformContent(file, query, value) {
663
+ var cacheEntry = import_zod.z.object({
664
+ code: import_zod.z.string(),
665
+ map: import_zod.z.any().optional(),
666
+ hash: import_zod.z.string().optional()
667
+ });
668
+ function createMdxLoader(configLoader) {
669
+ return async ({
670
+ source: value,
671
+ development: isDevelopment,
672
+ query,
673
+ compiler,
674
+ filePath
675
+ }) => {
696
676
  const matter = fumaMatter(value);
697
- const isDevelopment = this.environment.mode === "dev";
698
- const parsed = querySchema.parse((0, import_node_querystring.parse)(query));
677
+ const parsed = querySchema.parse(query);
678
+ const loaded = await configLoader.getConfig(parsed.hash);
679
+ const cacheDir = isDevelopment ? void 0 : loaded.global.experimentalBuildCache;
680
+ const cacheKey = `${parsed.hash}_${parsed.collection ?? "global"}_${generateCacheHash(filePath)}`;
681
+ if (cacheDir) {
682
+ const cached = await import_promises.default.readFile(import_node_path3.default.join(cacheDir, cacheKey)).then((content) => cacheEntry.parse(JSON.parse(content.toString()))).catch(() => null);
683
+ if (cached && cached.hash === generateCacheHash(value)) return cached;
684
+ }
699
685
  const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
700
686
  let schema;
701
687
  let mdxOptions;
@@ -715,9 +701,9 @@ function mdx(config, options = {}) {
715
701
  matter.data,
716
702
  {
717
703
  source: value,
718
- path: file
704
+ path: filePath
719
705
  },
720
- `invalid frontmatter in ${file}`
706
+ `invalid frontmatter in ${filePath}`
721
707
  );
722
708
  }
723
709
  if (parsed.only === "frontmatter") {
@@ -728,30 +714,118 @@ function mdx(config, options = {}) {
728
714
  }
729
715
  const data = {};
730
716
  if (loaded.global.lastModifiedTime === "git") {
731
- data.lastModified = (await getGitTimestamp(file))?.getTime();
717
+ data.lastModified = (await getGitTimestamp(filePath))?.getTime();
732
718
  }
733
- mdxOptions ??= await loaded.getDefaultMDXOptions();
734
719
  const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
735
720
  const compiled = await buildMDX(
736
- parsed.collection ?? "global",
721
+ `${parsed.hash ?? ""}:${parsed.collection ?? "global"}`,
737
722
  "\n".repeat(lineOffset) + matter.content,
738
723
  {
739
724
  development: isDevelopment,
740
- ...mdxOptions,
725
+ ...mdxOptions ?? await loaded.getDefaultMDXOptions(),
741
726
  data,
742
- filePath: file,
727
+ filePath,
743
728
  frontmatter: matter.data,
744
- _compiler: {
745
- addDependency: (file2) => {
746
- this.addWatchFile(file2);
747
- }
748
- }
729
+ _compiler: compiler
749
730
  }
750
731
  );
751
- return {
732
+ const out = {
752
733
  code: String(compiled.value),
753
734
  map: compiled.map
754
735
  };
736
+ if (cacheDir) {
737
+ await import_promises.default.mkdir(cacheDir, { recursive: true });
738
+ await import_promises.default.writeFile(
739
+ import_node_path3.default.join(cacheDir, cacheKey),
740
+ JSON.stringify({
741
+ ...out,
742
+ hash: generateCacheHash(value)
743
+ })
744
+ );
745
+ }
746
+ return out;
747
+ };
748
+ }
749
+ function generateCacheHash(input) {
750
+ return (0, import_node_crypto.createHash)("md5").update(input).digest("hex");
751
+ }
752
+
753
+ // src/utils/config.ts
754
+ var fs3 = __toESM(require("fs/promises"), 1);
755
+ var path5 = __toESM(require("path"), 1);
756
+ var import_node_url = require("url");
757
+
758
+ // src/loaders/config-loader.ts
759
+ function resolvedConfig(loaded) {
760
+ return {
761
+ getConfig() {
762
+ return loaded;
763
+ }
764
+ };
765
+ }
766
+
767
+ // src/loaders/adapter.ts
768
+ var import_node_url2 = require("url");
769
+ var import_promises2 = __toESM(require("fs/promises"), 1);
770
+ var import_node_querystring = require("querystring");
771
+ var import_node_path4 = __toESM(require("path"), 1);
772
+ function toVite(loader) {
773
+ return async function(file, query, value) {
774
+ const result = await loader({
775
+ filePath: file,
776
+ query: (0, import_node_querystring.parse)(query),
777
+ source: value,
778
+ development: this.environment.mode === "dev",
779
+ compiler: {
780
+ addDependency: (file2) => {
781
+ this.addWatchFile(file2);
782
+ }
783
+ }
784
+ });
785
+ return {
786
+ code: result.code,
787
+ map: result.map
788
+ };
789
+ };
790
+ }
791
+
792
+ // src/vite/index.ts
793
+ var FumadocsDeps = ["fumadocs-core", "fumadocs-ui", "fumadocs-openapi"];
794
+ function mdx(config, options = {}) {
795
+ const { generateIndexFile = true, configPath = "source.config.ts" } = options;
796
+ const loaded = buildConfig(config);
797
+ const mdxLoader = toVite(createMdxLoader(resolvedConfig(loaded)));
798
+ async function transformMeta(path8, query, value) {
799
+ const isJson = path8.endsWith(".json");
800
+ const parsed = (0, import_node_querystring2.parse)(query);
801
+ const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
802
+ if (!collection) return null;
803
+ let schema;
804
+ switch (collection.type) {
805
+ case "meta":
806
+ schema = collection.schema;
807
+ break;
808
+ case "docs":
809
+ schema = collection.meta.schema;
810
+ break;
811
+ }
812
+ if (!schema) return null;
813
+ let data;
814
+ try {
815
+ data = isJson ? JSON.parse(value) : (0, import_js_yaml2.load)(value);
816
+ } catch {
817
+ return null;
818
+ }
819
+ const out = await validate(
820
+ schema,
821
+ data,
822
+ { path: path8, source: value },
823
+ `invalid data in ${path8}`
824
+ );
825
+ return {
826
+ code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
827
+ map: null
828
+ };
755
829
  }
756
830
  return {
757
831
  name: "fumadocs-mdx",
@@ -773,8 +847,8 @@ function mdx(config, options = {}) {
773
847
  console.log("[Fumadocs MDX] Generating index files");
774
848
  const outDir = process.cwd();
775
849
  const outFile = "source.generated.ts";
776
- await fs2.writeFile(
777
- path4.join(outDir, outFile),
850
+ await fs5.writeFile(
851
+ path7.join(outDir, outFile),
778
852
  entry(
779
853
  configPath,
780
854
  loaded,
@@ -785,12 +859,12 @@ function mdx(config, options = {}) {
785
859
  },
786
860
  async transform(value, id) {
787
861
  const [file, query = ""] = id.split("?");
788
- const ext = path4.extname(file);
862
+ const ext = path7.extname(file);
789
863
  try {
790
864
  if ([".yaml", ".json"].includes(ext))
791
865
  return await transformMeta(file, query, value);
792
866
  if ([".md", ".mdx"].includes(ext))
793
- return await transformContent.call(this, file, query, value);
867
+ return await mdxLoader.call(this, file, query, value);
794
868
  } catch (e) {
795
869
  if (e instanceof ValidationError) {
796
870
  throw new Error(e.toStringFormatted());