fumadocs-mdx 11.10.1 → 12.0.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 (68) hide show
  1. package/dist/bin.cjs +126 -218
  2. package/dist/bin.js +1 -1
  3. package/dist/{browser-B2G8uAF2.d.cts → browser-D5lvL8vv.d.ts} +51 -4
  4. package/dist/{browser-DrH7tKRi.d.ts → browser-DjWADqp8.d.cts} +51 -4
  5. package/dist/bun/index.cjs +274 -230
  6. package/dist/bun/index.js +8 -8
  7. package/dist/chunk-ADR6R7HM.js +29 -0
  8. package/dist/{chunk-UOOPSLFY.js → chunk-AUOOMFAI.js} +27 -21
  9. package/dist/chunk-FSZMKRVH.js +80 -0
  10. package/dist/{chunk-766EAFX6.js → chunk-LGYVNESJ.js} +2 -36
  11. package/dist/chunk-LMG6UWCL.js +167 -0
  12. package/dist/chunk-QAUWMR5D.js +142 -0
  13. package/dist/{chunk-QJCCVMBJ.js → chunk-SP7CHRTS.js} +17 -47
  14. package/dist/{chunk-QVZ7JH4H.js → chunk-U4MQ44TS.js} +1 -1
  15. package/dist/{chunk-CNKI574E.js → chunk-VXEBLM4X.js} +1 -1
  16. package/dist/chunk-XMFLD5J6.js +30 -0
  17. package/dist/chunk-ZLCSVXCD.js +10 -0
  18. package/dist/{chunk-XXSKWWMB.js → chunk-ZX7TM4AR.js} +4 -2
  19. package/dist/config/index.cjs +97 -148
  20. package/dist/config/index.d.cts +1 -1
  21. package/dist/config/index.d.ts +1 -1
  22. package/dist/config/index.js +48 -9
  23. package/dist/{define-BH4bnHQl.d.ts → define--6HQ1ehX.d.cts} +18 -3
  24. package/dist/{define-BH4bnHQl.d.cts → define--6HQ1ehX.d.ts} +18 -3
  25. package/dist/load-UUXLUBHL.js +9 -0
  26. package/dist/loader-mdx.cjs +336 -305
  27. package/dist/loader-mdx.js +8 -8
  28. package/dist/next/index.cjs +152 -242
  29. package/dist/next/index.js +52 -66
  30. package/dist/node/loader.cjs +274 -243
  31. package/dist/node/loader.js +7 -8
  32. package/dist/postinstall-SCSXM4IM.js +10 -0
  33. package/dist/{mdx-options-T73E4LQB.js → preset-ZMP6U62C.js} +1 -1
  34. package/dist/runtime/next/async.cjs +304 -204
  35. package/dist/runtime/next/async.d.cts +3 -3
  36. package/dist/runtime/next/async.d.ts +3 -3
  37. package/dist/runtime/next/async.js +59 -32
  38. package/dist/runtime/next/index.cjs +32 -21
  39. package/dist/runtime/next/index.d.cts +11 -7
  40. package/dist/runtime/next/index.d.ts +11 -7
  41. package/dist/runtime/next/index.js +2 -1
  42. package/dist/runtime/vite/browser.d.cts +2 -3
  43. package/dist/runtime/vite/browser.d.ts +2 -3
  44. package/dist/runtime/vite/server.cjs +67 -21
  45. package/dist/runtime/vite/server.d.cts +14 -28
  46. package/dist/runtime/vite/server.d.ts +14 -28
  47. package/dist/runtime/vite/server.js +61 -21
  48. package/dist/shared-0QIuV0XZ.d.ts +70 -0
  49. package/dist/shared-CqgMnt9h.d.cts +70 -0
  50. package/dist/{types-DN9KrG7R.d.ts → types-CFlQxTN8.d.ts} +10 -37
  51. package/dist/{types-DT83Ijs6.d.cts → types-DkGjw-Uo.d.cts} +10 -37
  52. package/dist/vite/index.cjs +299 -279
  53. package/dist/vite/index.d.cts +1 -0
  54. package/dist/vite/index.d.ts +1 -0
  55. package/dist/vite/index.js +15 -20
  56. package/dist/{watcher-4NDMOH4R.js → watcher-HGOH3APP.js} +1 -1
  57. package/package.json +16 -16
  58. package/dist/build-mdx-DnC1jKvn.d.cts +0 -46
  59. package/dist/build-mdx-DnC1jKvn.d.ts +0 -46
  60. package/dist/chunk-GBMFGEC7.js +0 -57
  61. package/dist/chunk-QQWCBFFE.js +0 -40
  62. package/dist/chunk-SMSNZ6N5.js +0 -155
  63. package/dist/chunk-SVTXMVLQ.js +0 -139
  64. package/dist/config/zod-3.cjs +0 -422
  65. package/dist/config/zod-3.d.cts +0 -53
  66. package/dist/config/zod-3.d.ts +0 -53
  67. package/dist/config/zod-3.js +0 -40
  68. package/dist/postinstall-XV4WSHZP.js +0 -9
@@ -30,86 +30,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
- // src/mdx-plugins/remark-postprocess.ts
34
- function remarkPostprocess({
35
- injectExports
36
- }) {
37
- return (tree, file) => {
38
- let title;
39
- const urls = [];
40
- (0, import_unist_util_visit2.visit)(tree, ["heading", "link"], (node) => {
41
- if (node.type === "heading" && node.depth === 1) {
42
- title = flattenNode2(node);
43
- }
44
- if (node.type !== "link") return;
45
- urls.push({
46
- href: node.url
47
- });
48
- return "skip";
49
- });
50
- if (title) {
51
- file.data.frontmatter ??= {};
52
- if (!file.data.frontmatter.title) file.data.frontmatter.title = title;
53
- }
54
- file.data.extractedReferences = urls;
55
- for (const name of injectExports) {
56
- if (!(name in file.data)) continue;
57
- tree.children.unshift(getMdastExport(name, file.data[name]));
58
- }
59
- };
60
- }
61
- function flattenNode2(node) {
62
- if ("children" in node)
63
- return node.children.map((child) => flattenNode2(child)).join("");
64
- if ("value" in node) return node.value;
65
- return "";
66
- }
67
- function getMdastExport(name, value) {
68
- return {
69
- type: "mdxjsEsm",
70
- value: "",
71
- data: {
72
- estree: {
73
- type: "Program",
74
- sourceType: "module",
75
- body: [
76
- {
77
- type: "ExportNamedDeclaration",
78
- attributes: [],
79
- specifiers: [],
80
- source: null,
81
- declaration: {
82
- type: "VariableDeclaration",
83
- kind: "let",
84
- declarations: [
85
- {
86
- type: "VariableDeclarator",
87
- id: {
88
- type: "Identifier",
89
- name
90
- },
91
- init: (0, import_estree_util_value_to_estree.valueToEstree)(value)
92
- }
93
- ]
94
- }
95
- }
96
- ]
97
- }
98
- }
99
- };
100
- }
101
- var import_unist_util_visit2, import_estree_util_value_to_estree;
102
- var init_remark_postprocess = __esm({
103
- "src/mdx-plugins/remark-postprocess.ts"() {
104
- "use strict";
105
- import_unist_util_visit2 = require("unist-util-visit");
106
- import_estree_util_value_to_estree = require("estree-util-value-to-estree");
107
- }
108
- });
109
-
110
- // src/utils/mdx-options.ts
111
- var mdx_options_exports = {};
112
- __export(mdx_options_exports, {
33
+ // src/loaders/mdx/preset.ts
34
+ var preset_exports = {};
35
+ __export(preset_exports, {
113
36
  getDefaultMDXOptions: () => getDefaultMDXOptions
114
37
  });
115
38
  function pluginOption(def, options = []) {
@@ -132,13 +55,6 @@ function getDefaultMDXOptions({
132
55
  _withoutBundler = false,
133
56
  ...mdxOptions
134
57
  }) {
135
- const mdxExports = [
136
- "structuredData",
137
- "extractedReferences",
138
- "frontmatter",
139
- "lastModified",
140
- ...valueToExport
141
- ];
142
58
  const remarkPlugins = pluginOption(
143
59
  (v) => [
144
60
  plugins.remarkGfm,
@@ -166,10 +82,15 @@ function getDefaultMDXOptions({
166
82
  plugins.remarkStructure,
167
83
  remarkStructureOptions
168
84
  ],
169
- [
170
- remarkPostprocess,
171
- { injectExports: mdxExports }
172
- ]
85
+ () => {
86
+ return (_, file) => {
87
+ file.data["mdx-export"] ??= [];
88
+ for (const name of valueToExport) {
89
+ if (name in file.data)
90
+ file.data["mdx-export"].push({ name, value: file.data[name] });
91
+ }
92
+ };
93
+ }
173
94
  ],
174
95
  mdxOptions.remarkPlugins
175
96
  );
@@ -189,11 +110,125 @@ function getDefaultMDXOptions({
189
110
  };
190
111
  }
191
112
  var plugins;
192
- var init_mdx_options = __esm({
193
- "src/utils/mdx-options.ts"() {
113
+ var init_preset = __esm({
114
+ "src/loaders/mdx/preset.ts"() {
194
115
  "use strict";
195
116
  plugins = __toESM(require("fumadocs-core/mdx-plugins"), 1);
196
- init_remark_postprocess();
117
+ }
118
+ });
119
+
120
+ // src/config/build.ts
121
+ function buildConfig(config) {
122
+ const collections = /* @__PURE__ */ new Map();
123
+ let globalConfig = {};
124
+ for (const [k, v] of Object.entries(config)) {
125
+ if (!v) {
126
+ continue;
127
+ }
128
+ if (typeof v === "object" && "type" in v) {
129
+ if (v.type === "docs") {
130
+ collections.set(k, v);
131
+ continue;
132
+ }
133
+ if (v.type === "doc" || v.type === "meta") {
134
+ collections.set(k, v);
135
+ continue;
136
+ }
137
+ }
138
+ if (k === "default" && v) {
139
+ globalConfig = v;
140
+ continue;
141
+ }
142
+ throw new Error(
143
+ `Unknown export "${k}", you can only export collections from source configuration file.`
144
+ );
145
+ }
146
+ const mdxOptionsCache = /* @__PURE__ */ new Map();
147
+ return {
148
+ global: globalConfig,
149
+ collections,
150
+ async getDefaultMDXOptions(mode = "default") {
151
+ const cached = mdxOptionsCache.get(mode);
152
+ if (cached) return cached;
153
+ const input = this.global.mdxOptions;
154
+ async function uncached() {
155
+ const options = typeof input === "function" ? await input() : input;
156
+ const { getDefaultMDXOptions: getDefaultMDXOptions2 } = await Promise.resolve().then(() => (init_preset(), preset_exports));
157
+ if (options?.preset === "minimal") return options;
158
+ return getDefaultMDXOptions2({
159
+ ...options,
160
+ _withoutBundler: mode === "remote"
161
+ });
162
+ }
163
+ const result = uncached();
164
+ mdxOptionsCache.set(mode, result);
165
+ return result;
166
+ }
167
+ };
168
+ }
169
+ var init_build = __esm({
170
+ "src/config/build.ts"() {
171
+ "use strict";
172
+ }
173
+ });
174
+
175
+ // src/loaders/config/load.ts
176
+ var load_exports = {};
177
+ __export(load_exports, {
178
+ getConfigHash: () => getConfigHash,
179
+ loadConfig: () => loadConfig
180
+ });
181
+ async function compileConfig(configPath, outDir) {
182
+ const { build } = await import("esbuild");
183
+ const transformed = await build({
184
+ entryPoints: [{ in: configPath, out: "source.config" }],
185
+ bundle: true,
186
+ outdir: outDir,
187
+ target: "node20",
188
+ write: true,
189
+ platform: "node",
190
+ format: "esm",
191
+ packages: "external",
192
+ outExtension: {
193
+ ".js": ".mjs"
194
+ },
195
+ allowOverwrite: true
196
+ });
197
+ if (transformed.errors.length > 0) {
198
+ throw new Error("failed to compile configuration file");
199
+ }
200
+ }
201
+ async function loadConfig(configPath, outDir, hash, build = false) {
202
+ if (cache3 && cache3.hash === hash) {
203
+ return await cache3.config;
204
+ }
205
+ if (build) await compileConfig(configPath, outDir);
206
+ const url = (0, import_node_url.pathToFileURL)(path4.resolve(outDir, "source.config.mjs"));
207
+ const config = import(`${url.href}?hash=${hash}`).then((loaded) => {
208
+ return buildConfig(
209
+ // every call to `loadConfig` will cause the previous cache to be ignored
210
+ loaded
211
+ );
212
+ });
213
+ if (hash) cache3 = { config, hash };
214
+ return await config;
215
+ }
216
+ async function getConfigHash(configPath) {
217
+ const stats = await fs3.stat(configPath).catch(() => void 0);
218
+ if (stats) {
219
+ return stats.mtime.getTime().toString();
220
+ }
221
+ throw new Error("Cannot find config file");
222
+ }
223
+ var fs3, path4, import_node_url, cache3;
224
+ var init_load = __esm({
225
+ "src/loaders/config/load.ts"() {
226
+ "use strict";
227
+ fs3 = __toESM(require("fs/promises"), 1);
228
+ path4 = __toESM(require("path"), 1);
229
+ import_node_url = require("url");
230
+ init_build();
231
+ cache3 = null;
197
232
  }
198
233
  });
199
234
 
@@ -281,19 +316,10 @@ async function getGitTimestamp(file) {
281
316
  }
282
317
  }
283
318
 
284
- // src/utils/count-lines.ts
285
- function countLines(s) {
286
- let num = 0;
287
- for (const c of s) {
288
- if (c === "\n") num++;
289
- }
290
- return num;
291
- }
292
-
293
- // src/utils/build-mdx.ts
319
+ // src/loaders/mdx/build-mdx.ts
294
320
  var import_mdx = require("@mdx-js/mdx");
295
321
 
296
- // src/mdx-plugins/remark-include.ts
322
+ // src/loaders/mdx/remark-include.ts
297
323
  var import_unified = require("unified");
298
324
  var import_unist_util_visit = require("unist-util-visit");
299
325
  var path2 = __toESM(require("path"), 1);
@@ -301,7 +327,28 @@ var fs = __toESM(require("fs/promises"), 1);
301
327
  var import_remark_parse = __toESM(require("remark-parse"), 1);
302
328
  var import_remark_mdx = __toESM(require("remark-mdx"), 1);
303
329
  var import_mdx_plugins = require("fumadocs-core/mdx-plugins");
304
- var baseProcessor = (0, import_unified.unified)().use(import_mdx_plugins.remarkHeading);
330
+ var ElementLikeTypes = [
331
+ "mdxJsxFlowElement",
332
+ "mdxJsxTextElement",
333
+ "containerDirective",
334
+ "textDirective",
335
+ "leafDirective"
336
+ ];
337
+ function isElementLike(node) {
338
+ return ElementLikeTypes.includes(node.type);
339
+ }
340
+ function parseElementAttributes(element) {
341
+ if (Array.isArray(element.attributes)) {
342
+ const attributes = {};
343
+ for (const attr of element.attributes) {
344
+ if (attr.type === "mdxJsxAttribute" && (typeof attr.value === "string" || attr.value === null)) {
345
+ attributes[attr.name] = attr.value;
346
+ }
347
+ }
348
+ return attributes;
349
+ }
350
+ return element.attributes ?? {};
351
+ }
305
352
  function flattenNode(node) {
306
353
  if ("children" in node)
307
354
  return node.children.map((child) => flattenNode(child)).join("");
@@ -318,21 +365,31 @@ function parseSpecifier(specifier) {
318
365
  }
319
366
  function extractSection(root, section) {
320
367
  let nodes;
321
- for (const node of root.children) {
322
- if (node.type === "mdxJsxFlowElement" && node.name === "section" && node.attributes.some(
323
- (attr) => attr.type === "mdxJsxAttribute" && attr.name === "id" && attr.value === section
324
- )) {
325
- nodes = node.children;
326
- break;
368
+ let capturingHeadingContent = false;
369
+ (0, import_unist_util_visit.visit)(root, (node) => {
370
+ if (node.type === "heading") {
371
+ if (capturingHeadingContent) {
372
+ return false;
373
+ }
374
+ if (node.data?.hProperties?.id === section) {
375
+ capturingHeadingContent = true;
376
+ nodes = [node];
377
+ return "skip";
378
+ }
379
+ return;
327
380
  }
328
- if (node.type === "heading" && node.data?.hProperties?.id === section) {
329
- nodes = [node];
330
- continue;
381
+ if (capturingHeadingContent) {
382
+ nodes?.push(node);
383
+ return "skip";
331
384
  }
332
- if (!nodes) continue;
333
- if (node.type === "heading") break;
334
- nodes.push(node);
335
- }
385
+ if (isElementLike(node) && node.name === "section") {
386
+ const attributes = parseElementAttributes(node);
387
+ if (attributes.id === section) {
388
+ nodes = node.children;
389
+ return false;
390
+ }
391
+ }
392
+ });
336
393
  if (nodes)
337
394
  return {
338
395
  type: "root",
@@ -364,55 +421,52 @@ ${e instanceof Error ? e.message : String(e)}`,
364
421
  data: {}
365
422
  };
366
423
  }
367
- const processor = (data._getProcessor ?? getDefaultProcessor)(
424
+ const parser = (data._getProcessor ?? getDefaultProcessor)(
368
425
  ext === ".mdx" ? "mdx" : "md"
369
426
  );
370
- let parsed = await baseProcessor.run(
371
- processor.parse(fumaMatter(content).content)
372
- );
427
+ const parsed = fumaMatter(content);
428
+ let mdast = parser.parse({
429
+ path: file,
430
+ value: parsed.content,
431
+ data: { frontmatter: parsed.data }
432
+ });
373
433
  if (heading) {
374
- const extracted = extractSection(parsed, heading);
434
+ const extracted = extractSection(
435
+ await (0, import_unified.unified)().use(import_mdx_plugins.remarkHeading).run(mdast),
436
+ heading
437
+ );
375
438
  if (!extracted)
376
439
  throw new Error(
377
- `Cannot find section ${heading} in ${file}, make sure you have encapsulated the section in a <section id="${heading}"> tag.`
440
+ `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.`
378
441
  );
379
- parsed = extracted;
442
+ mdast = extracted;
380
443
  }
381
- await update(parsed, path2.dirname(file), data);
382
- return parsed;
444
+ await update(mdast, path2.dirname(file), data);
445
+ return mdast;
383
446
  }
384
447
  async function update(tree, directory, data) {
385
448
  const queue = [];
386
- (0, import_unist_util_visit.visit)(
387
- tree,
388
- ["mdxJsxFlowElement", "mdxJsxTextElement"],
389
- (_node, _, parent) => {
390
- const node = _node;
391
- if (node.name !== TagName) return;
392
- const params = {};
393
- const specifier = flattenNode(node);
394
- if (specifier.length === 0) return "skip";
395
- for (const attr of node.attributes) {
396
- if (attr.type === "mdxJsxAttribute" && (typeof attr.value === "string" || attr.value === null)) {
397
- params[attr.name] = attr.value;
398
- }
399
- }
400
- const { file: relativePath, section } = parseSpecifier(specifier);
401
- const file = path2.resolve(
402
- "cwd" in params ? process.cwd() : directory,
403
- relativePath
404
- );
405
- queue.push(
406
- embedContent(file, section, params, data).then((replace) => {
407
- Object.assign(
408
- parent && parent.type === "paragraph" ? parent : node,
409
- replace
410
- );
411
- })
412
- );
413
- return "skip";
414
- }
415
- );
449
+ (0, import_unist_util_visit.visit)(tree, ElementLikeTypes, (_node, _, parent) => {
450
+ const node = _node;
451
+ if (node.name !== TagName) return;
452
+ const specifier = flattenNode(node);
453
+ if (specifier.length === 0) return "skip";
454
+ const attributes = parseElementAttributes(node);
455
+ const { file: relativePath, section } = parseSpecifier(specifier);
456
+ const file = path2.resolve(
457
+ "cwd" in attributes ? process.cwd() : directory,
458
+ relativePath
459
+ );
460
+ queue.push(
461
+ embedContent(file, section, attributes, data).then((replace) => {
462
+ Object.assign(
463
+ parent && parent.type === "paragraph" ? parent : node,
464
+ replace
465
+ );
466
+ })
467
+ );
468
+ return "skip";
469
+ });
416
470
  await Promise.all(queue);
417
471
  }
418
472
  return async (tree, file) => {
@@ -425,7 +479,90 @@ function getDefaultProcessor(format) {
425
479
  return mdProcessor.use(import_remark_mdx.default);
426
480
  }
427
481
 
428
- // src/utils/build-mdx.ts
482
+ // src/loaders/mdx/remark-postprocess.ts
483
+ var import_unist_util_visit2 = require("unist-util-visit");
484
+ var import_mdast_util_to_markdown = require("mdast-util-to-markdown");
485
+ var import_estree_util_value_to_estree = require("estree-util-value-to-estree");
486
+ function remarkPostprocess({
487
+ includeProcessedMarkdown = false,
488
+ valueToExport = []
489
+ } = {}) {
490
+ return (tree, file) => {
491
+ let title;
492
+ const urls = [];
493
+ (0, import_unist_util_visit2.visit)(tree, ["heading", "link"], (node) => {
494
+ if (node.type === "heading" && node.depth === 1) {
495
+ title = flattenNode2(node);
496
+ }
497
+ if (node.type !== "link") return;
498
+ urls.push({
499
+ href: node.url
500
+ });
501
+ return "skip";
502
+ });
503
+ if (title) {
504
+ file.data.frontmatter ??= {};
505
+ if (!file.data.frontmatter.title) file.data.frontmatter.title = title;
506
+ }
507
+ file.data.extractedReferences = urls;
508
+ if (includeProcessedMarkdown) {
509
+ file.data._markdown = (0, import_mdast_util_to_markdown.toMarkdown)(tree, {
510
+ ...this.data("settings"),
511
+ // from https://github.com/remarkjs/remark/blob/main/packages/remark-stringify/lib/index.js
512
+ extensions: this.data("toMarkdownExtensions") || []
513
+ });
514
+ }
515
+ for (const { name, value } of file.data["mdx-export"] ?? []) {
516
+ tree.children.unshift(getMdastExport(name, value));
517
+ }
518
+ for (const name of valueToExport) {
519
+ if (!(name in file.data)) continue;
520
+ tree.children.unshift(getMdastExport(name, file.data[name]));
521
+ }
522
+ };
523
+ }
524
+ function getMdastExport(name, value) {
525
+ return {
526
+ type: "mdxjsEsm",
527
+ value: "",
528
+ data: {
529
+ estree: {
530
+ type: "Program",
531
+ sourceType: "module",
532
+ body: [
533
+ {
534
+ type: "ExportNamedDeclaration",
535
+ attributes: [],
536
+ specifiers: [],
537
+ source: null,
538
+ declaration: {
539
+ type: "VariableDeclaration",
540
+ kind: "let",
541
+ declarations: [
542
+ {
543
+ type: "VariableDeclarator",
544
+ id: {
545
+ type: "Identifier",
546
+ name
547
+ },
548
+ init: (0, import_estree_util_value_to_estree.valueToEstree)(value)
549
+ }
550
+ ]
551
+ }
552
+ }
553
+ ]
554
+ }
555
+ }
556
+ };
557
+ }
558
+ function flattenNode2(node) {
559
+ if ("children" in node)
560
+ return node.children.map((child) => flattenNode2(child)).join("");
561
+ if ("value" in node) return node.value;
562
+ return "";
563
+ }
564
+
565
+ // src/loaders/mdx/build-mdx.ts
429
566
  var cache2 = /* @__PURE__ */ new Map();
430
567
  async function buildMDX(cacheKey, source, options) {
431
568
  const { filePath, frontmatter, data, _compiler, ...rest } = options;
@@ -436,7 +573,24 @@ async function buildMDX(cacheKey, source, options) {
436
573
  processor = (0, import_mdx.createProcessor)({
437
574
  outputFormat: "program",
438
575
  ...rest,
439
- remarkPlugins: [remarkInclude, ...rest.remarkPlugins ?? []],
576
+ remarkPlugins: [
577
+ remarkInclude,
578
+ ...rest.remarkPlugins ?? [],
579
+ [
580
+ remarkPostprocess,
581
+ {
582
+ ...options.postprocess,
583
+ valueToExport: [
584
+ ...options.postprocess?.valueToExport ?? [],
585
+ "structuredData",
586
+ "extractedReferences",
587
+ "frontmatter",
588
+ "lastModified",
589
+ "_markdown"
590
+ ]
591
+ }
592
+ ]
593
+ ],
440
594
  format
441
595
  });
442
596
  cache2.set(key, processor);
@@ -444,7 +598,7 @@ async function buildMDX(cacheKey, source, options) {
444
598
  return processor;
445
599
  }
446
600
  return getProcessor(
447
- options.format ?? filePath.endsWith(".mdx") ? "mdx" : "md"
601
+ options.format ?? (filePath.endsWith(".mdx") ? "mdx" : "md")
448
602
  ).process({
449
603
  value: source,
450
604
  path: filePath,
@@ -457,7 +611,7 @@ async function buildMDX(cacheKey, source, options) {
457
611
  });
458
612
  }
459
613
 
460
- // src/loaders/mdx.ts
614
+ // src/loaders/mdx/index.ts
461
615
  var import_zod = require("zod");
462
616
  var import_promises = __toESM(require("fs/promises"), 1);
463
617
  var import_node_path2 = __toESM(require("path"), 1);
@@ -492,21 +646,18 @@ function createMdxLoader(configLoader) {
492
646
  if (cached && cached.hash === generateCacheHash(value)) return cached;
493
647
  }
494
648
  const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
495
- let schema;
496
- let mdxOptions;
649
+ let docCollection;
497
650
  switch (collection?.type) {
498
651
  case "doc":
499
- mdxOptions = collection.mdxOptions;
500
- schema = collection.schema;
652
+ docCollection = collection;
501
653
  break;
502
654
  case "docs":
503
- mdxOptions = collection.docs.mdxOptions;
504
- schema = collection.docs.schema;
655
+ docCollection = collection.docs;
505
656
  break;
506
657
  }
507
- if (schema) {
658
+ if (docCollection?.schema) {
508
659
  matter.data = await validate(
509
- schema,
660
+ docCollection.schema,
510
661
  matter.data,
511
662
  {
512
663
  source: value,
@@ -531,7 +682,8 @@ function createMdxLoader(configLoader) {
531
682
  "\n".repeat(lineOffset) + matter.content,
532
683
  {
533
684
  development: isDevelopment,
534
- ...mdxOptions ?? await loaded.getDefaultMDXOptions(),
685
+ ...docCollection?.mdxOptions ?? await loaded.getDefaultMDXOptions(),
686
+ postprocess: docCollection?.postprocess,
535
687
  data,
536
688
  filePath,
537
689
  frontmatter: matter.data,
@@ -558,145 +710,24 @@ function createMdxLoader(configLoader) {
558
710
  function generateCacheHash(input) {
559
711
  return (0, import_node_crypto.createHash)("md5").update(input).digest("hex");
560
712
  }
561
-
562
- // src/utils/config.ts
563
- var fs3 = __toESM(require("fs/promises"), 1);
564
- var path4 = __toESM(require("path"), 1);
565
- var import_node_url = require("url");
566
-
567
- // src/config/build.ts
568
- function buildConfig(config) {
569
- const collections = /* @__PURE__ */ new Map();
570
- let globalConfig = {};
571
- for (const [k, v] of Object.entries(config)) {
572
- if (!v) {
573
- continue;
574
- }
575
- if (typeof v === "object" && "type" in v) {
576
- if (v.type === "docs") {
577
- collections.set(k, v);
578
- continue;
579
- }
580
- if (v.type === "doc" || v.type === "meta") {
581
- collections.set(k, v);
582
- continue;
583
- }
584
- }
585
- if (k === "default" && v) {
586
- globalConfig = v;
587
- continue;
588
- }
589
- throw new Error(
590
- `Unknown export "${k}", you can only export collections from source configuration file.`
591
- );
592
- }
593
- const mdxOptionsCache = /* @__PURE__ */ new Map();
594
- return {
595
- global: globalConfig,
596
- collections,
597
- async getDefaultMDXOptions(mode = "default") {
598
- const cached = mdxOptionsCache.get(mode);
599
- if (cached) return cached;
600
- const input = this.global.mdxOptions;
601
- async function uncached() {
602
- const options = typeof input === "function" ? await input() : input;
603
- const { getDefaultMDXOptions: getDefaultMDXOptions2 } = await Promise.resolve().then(() => (init_mdx_options(), mdx_options_exports));
604
- if (options?.preset === "minimal") return options;
605
- return getDefaultMDXOptions2({
606
- ...options,
607
- _withoutBundler: mode === "remote"
608
- });
609
- }
610
- const result = uncached();
611
- mdxOptionsCache.set(mode, result);
612
- return result;
613
- }
614
- };
615
- }
616
-
617
- // src/utils/config.ts
618
- var cache3 = null;
619
- async function isZod3() {
620
- try {
621
- const content = JSON.parse(
622
- (await fs3.readFile("node_modules/zod/package.json")).toString()
623
- );
624
- const version = content.version;
625
- return typeof version === "string" && version.startsWith("3.");
626
- } catch {
627
- return false;
628
- }
629
- }
630
- function createCompatZodPlugin() {
631
- return {
632
- name: "replace-zod-import",
633
- async setup(build) {
634
- const usingZod3 = await isZod3();
635
- if (!usingZod3) return;
636
- console.warn(
637
- "[Fumadocs MDX] Noticed Zod v3 in your node_modules, we recommend upgrading to Zod v4 for better compatibility."
638
- );
639
- build.onResolve({ filter: /^fumadocs-mdx\/config$/ }, () => {
640
- return {
641
- path: "fumadocs-mdx/config/zod-3",
642
- external: true
643
- };
644
- });
645
- }
646
- };
647
- }
648
- async function compileConfig(configPath, outDir) {
649
- const { build } = await import("esbuild");
650
- const transformed = await build({
651
- entryPoints: [{ in: configPath, out: "source.config" }],
652
- bundle: true,
653
- outdir: outDir,
654
- target: "node20",
655
- write: true,
656
- platform: "node",
657
- format: "esm",
658
- packages: "external",
659
- plugins: [createCompatZodPlugin()],
660
- outExtension: {
661
- ".js": ".mjs"
662
- },
663
- allowOverwrite: true
664
- });
665
- if (transformed.errors.length > 0) {
666
- throw new Error("failed to compile configuration file");
667
- }
668
- }
669
- async function loadConfig(configPath, outDir, hash, build = false) {
670
- if (cache3 && cache3.hash === hash) {
671
- return await cache3.config;
672
- }
673
- if (build) await compileConfig(configPath, outDir);
674
- const url = (0, import_node_url.pathToFileURL)(path4.resolve(outDir, "source.config.mjs"));
675
- const config = import(`${url.href}?hash=${hash}`).then((loaded) => {
676
- return buildConfig(
677
- // every call to `loadConfig` will cause the previous cache to be ignored
678
- loaded
679
- );
680
- });
681
- if (hash) cache3 = { config, hash };
682
- return await config;
683
- }
684
- async function getConfigHash(configPath) {
685
- const stats = await fs3.stat(configPath).catch(() => void 0);
686
- if (stats) {
687
- return stats.mtime.getTime().toString();
713
+ function countLines(s) {
714
+ let num = 0;
715
+ for (const c of s) {
716
+ if (c === "\n") num++;
688
717
  }
689
- throw new Error("Cannot find config file");
718
+ return num;
690
719
  }
691
720
 
692
- // src/loaders/config-loader.ts
721
+ // src/loaders/config/index.ts
722
+ var import_node_path3 = __toESM(require("path"), 1);
693
723
  function dynamicConfig(configPath, outDir) {
694
724
  return {
695
725
  async getConfig(hash) {
696
- return loadConfig(
726
+ const { loadConfig: loadConfig2, getConfigHash: getConfigHash2 } = await Promise.resolve().then(() => (init_load(), load_exports));
727
+ return loadConfig2(
697
728
  configPath,
698
729
  outDir,
699
- hash ?? await getConfigHash(configPath)
730
+ hash ?? await getConfigHash2(configPath)
700
731
  );
701
732
  }
702
733
  };
@@ -706,13 +737,13 @@ function dynamicConfig(configPath, outDir) {
706
737
  var import_node_url2 = require("url");
707
738
  var import_promises2 = __toESM(require("fs/promises"), 1);
708
739
  var import_node_querystring = require("querystring");
709
- var import_node_path3 = __toESM(require("path"), 1);
740
+ var import_node_path4 = __toESM(require("path"), 1);
710
741
  function toWebpack(loader2) {
711
742
  return async function(source, callback) {
712
743
  try {
713
744
  const result = await loader2({
714
745
  filePath: this.resourcePath,
715
- query: (0, import_node_querystring.parse)(this.resourceQuery),
746
+ query: (0, import_node_querystring.parse)(this.resourceQuery.slice(1)),
716
747
  source,
717
748
  development: this.mode === "development",
718
749
  compiler: this
@@ -723,7 +754,7 @@ function toWebpack(loader2) {
723
754
  return callback(new Error(error.toStringFormatted()));
724
755
  }
725
756
  if (!(error instanceof Error)) throw error;
726
- const fpath = import_node_path3.default.relative(this.context, this.resourcePath);
757
+ const fpath = import_node_path4.default.relative(this.context, this.resourcePath);
727
758
  error.message = `${fpath}:${error.name}: ${error.message}`;
728
759
  callback(error);
729
760
  }