fumadocs-mdx 13.0.8 → 14.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 (104) hide show
  1. package/dist/bin.cjs +924 -901
  2. package/dist/bin.js +3 -3
  3. package/dist/build-mdx-6UAK5FF5.js +8 -0
  4. package/dist/bun/index.cjs +578 -471
  5. package/dist/bun/index.d.cts +3 -2
  6. package/dist/bun/index.d.ts +3 -2
  7. package/dist/bun/index.js +12 -12
  8. package/dist/chunk-4JSFLXXT.js +8 -0
  9. package/dist/chunk-5UMZCWKV.js +17 -0
  10. package/dist/chunk-5YXP7JLN.js +138 -0
  11. package/dist/{chunk-2E2JCOSO.js → chunk-6NISOLQ6.js} +16 -44
  12. package/dist/chunk-7L2KNF6B.js +180 -0
  13. package/dist/chunk-E5DJTSIM.js +86 -0
  14. package/dist/{chunk-K5ZLPEIQ.js → chunk-FBLMK4RS.js} +9 -6
  15. package/dist/{chunk-QXHN25N3.js → chunk-OXSRIWQW.js} +7 -8
  16. package/dist/chunk-PKI7ZDA5.js +29 -0
  17. package/dist/{chunk-3J3WL7WN.js → chunk-SLY7WXTX.js} +71 -58
  18. package/dist/{chunk-5FTSWCB4.js → chunk-SRSRFOVI.js} +8 -10
  19. package/dist/chunk-TYJDYTKH.js +85 -0
  20. package/dist/chunk-XHJCLBZ4.js +406 -0
  21. package/dist/{chunk-2HXTGJBI.js → chunk-ZY6UZ7NH.js} +22 -19
  22. package/dist/config/index.cjs +79 -71
  23. package/dist/config/index.d.cts +2 -1
  24. package/dist/config/index.d.ts +2 -1
  25. package/dist/config/index.js +5 -5
  26. package/dist/index-BlVBvy-z.d.ts +8 -0
  27. package/dist/{core-DB7TdlyC.d.cts → index-D7JdSMpp.d.cts} +99 -61
  28. package/dist/{core-DB7TdlyC.d.ts → index-D7JdSMpp.d.ts} +99 -61
  29. package/dist/index-P2NNUkHn.d.cts +8 -0
  30. package/dist/index.d.cts +3 -74
  31. package/dist/index.d.ts +3 -74
  32. package/dist/load-from-file-I3ALLIVB.js +8 -0
  33. package/dist/next/index.cjs +698 -476
  34. package/dist/next/index.d.cts +11 -1
  35. package/dist/next/index.d.ts +11 -1
  36. package/dist/next/index.js +78 -281
  37. package/dist/node/loader.cjs +704 -602
  38. package/dist/node/loader.js +10 -11
  39. package/dist/plugins/index-file.cjs +471 -0
  40. package/dist/plugins/index-file.d.cts +29 -0
  41. package/dist/plugins/index-file.d.ts +29 -0
  42. package/dist/plugins/index-file.js +8 -0
  43. package/dist/plugins/json-schema.d.cts +3 -2
  44. package/dist/plugins/json-schema.d.ts +3 -2
  45. package/dist/plugins/last-modified.cjs +75 -0
  46. package/dist/plugins/last-modified.d.cts +27 -0
  47. package/dist/plugins/last-modified.d.ts +27 -0
  48. package/dist/plugins/last-modified.js +44 -0
  49. package/dist/runtime/{vite/browser.cjs → browser.cjs} +40 -53
  50. package/dist/runtime/browser.d.cts +50 -0
  51. package/dist/runtime/browser.d.ts +50 -0
  52. package/dist/runtime/browser.js +68 -0
  53. package/dist/runtime/dynamic.cjs +985 -0
  54. package/dist/runtime/dynamic.d.cts +27 -0
  55. package/dist/runtime/dynamic.d.ts +27 -0
  56. package/dist/runtime/dynamic.js +78 -0
  57. package/dist/runtime/server.cjs +173 -0
  58. package/dist/runtime/server.d.cts +161 -0
  59. package/dist/runtime/server.d.ts +161 -0
  60. package/dist/runtime/server.js +8 -0
  61. package/dist/vite/index.cjs +934 -638
  62. package/dist/vite/index.d.cts +12 -22
  63. package/dist/vite/index.d.ts +12 -22
  64. package/dist/vite/index.js +30 -221
  65. package/dist/webpack/mdx.cjs +613 -515
  66. package/dist/webpack/mdx.d.cts +9 -1
  67. package/dist/webpack/mdx.d.ts +9 -1
  68. package/dist/webpack/mdx.js +12 -17
  69. package/dist/webpack/meta.cjs +327 -233
  70. package/dist/webpack/meta.d.cts +9 -1
  71. package/dist/webpack/meta.d.ts +9 -1
  72. package/dist/webpack/meta.js +13 -15
  73. package/package.json +15 -32
  74. package/dist/build-mdx-BjXOmv0b.d.cts +0 -53
  75. package/dist/build-mdx-CY5UldCO.d.ts +0 -53
  76. package/dist/chunk-2AQRQXSO.js +0 -119
  77. package/dist/chunk-CXA4JO4Z.js +0 -45
  78. package/dist/chunk-DMJ6I4C3.js +0 -76
  79. package/dist/chunk-FSZMKRVH.js +0 -80
  80. package/dist/chunk-II3H5ZVZ.js +0 -77
  81. package/dist/chunk-KILFIBVW.js +0 -75
  82. package/dist/chunk-NVRDCY6Z.js +0 -30
  83. package/dist/chunk-VUEZTR2H.js +0 -26
  84. package/dist/index-D7s7kCc2.d.cts +0 -7
  85. package/dist/index-D7s7kCc2.d.ts +0 -7
  86. package/dist/load-from-file-AVYOFOI7.js +0 -7
  87. package/dist/preset-ZMP6U62C.js +0 -6
  88. package/dist/runtime/next/async.cjs +0 -760
  89. package/dist/runtime/next/async.d.cts +0 -19
  90. package/dist/runtime/next/async.d.ts +0 -19
  91. package/dist/runtime/next/async.js +0 -86
  92. package/dist/runtime/next/index.cjs +0 -136
  93. package/dist/runtime/next/index.d.cts +0 -33
  94. package/dist/runtime/next/index.d.ts +0 -33
  95. package/dist/runtime/next/index.js +0 -11
  96. package/dist/runtime/vite/browser.d.cts +0 -59
  97. package/dist/runtime/vite/browser.d.ts +0 -59
  98. package/dist/runtime/vite/browser.js +0 -11
  99. package/dist/runtime/vite/server.cjs +0 -243
  100. package/dist/runtime/vite/server.d.cts +0 -30
  101. package/dist/runtime/vite/server.d.ts +0 -30
  102. package/dist/runtime/vite/server.js +0 -111
  103. package/dist/types-Bnh9n7mj.d.cts +0 -45
  104. package/dist/types-ey1AZqrg.d.ts +0 -45
@@ -30,11 +30,7 @@ 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/loaders/mdx/preset.ts
34
- var preset_exports = {};
35
- __export(preset_exports, {
36
- getDefaultMDXOptions: () => getDefaultMDXOptions
37
- });
33
+ // src/config/preset.ts
38
34
  function pluginOption(def, options = []) {
39
35
  const list = def(Array.isArray(options) ? options : []).filter(
40
36
  Boolean
@@ -44,76 +40,81 @@ function pluginOption(def, options = []) {
44
40
  }
45
41
  return list;
46
42
  }
47
- function getDefaultMDXOptions({
48
- valueToExport = [],
49
- rehypeCodeOptions,
50
- remarkImageOptions,
51
- remarkHeadingOptions,
52
- remarkStructureOptions,
53
- remarkCodeTabOptions,
54
- remarkNpmOptions,
55
- _withoutBundler = false,
56
- ...mdxOptions
57
- }) {
58
- const remarkPlugins = pluginOption(
59
- (v) => [
60
- plugins.remarkGfm,
61
- [
62
- plugins.remarkHeading,
63
- {
64
- generateToc: false,
65
- ...remarkHeadingOptions
66
- }
67
- ],
68
- remarkImageOptions !== false && [
69
- plugins.remarkImage,
70
- {
71
- ...remarkImageOptions,
72
- useImport: _withoutBundler ? false : remarkImageOptions?.useImport
73
- }
74
- ],
75
- "remarkCodeTab" in plugins && remarkCodeTabOptions !== false && [
76
- plugins.remarkCodeTab,
77
- remarkCodeTabOptions
43
+ function applyMdxPreset(options = {}) {
44
+ return async (environment = "bundler") => {
45
+ if (options.preset === "minimal") return options;
46
+ const plugins = await import("fumadocs-core/mdx-plugins");
47
+ const {
48
+ valueToExport = [],
49
+ rehypeCodeOptions,
50
+ remarkImageOptions,
51
+ remarkHeadingOptions,
52
+ remarkStructureOptions,
53
+ remarkCodeTabOptions,
54
+ remarkNpmOptions,
55
+ ...mdxOptions
56
+ } = options;
57
+ const remarkPlugins = pluginOption(
58
+ (v) => [
59
+ plugins.remarkGfm,
60
+ [
61
+ plugins.remarkHeading,
62
+ {
63
+ generateToc: false,
64
+ ...remarkHeadingOptions
65
+ }
66
+ ],
67
+ remarkImageOptions !== false && [
68
+ plugins.remarkImage,
69
+ {
70
+ ...remarkImageOptions,
71
+ useImport: remarkImageOptions?.useImport ?? environment === "bundler"
72
+ }
73
+ ],
74
+ "remarkCodeTab" in plugins && remarkCodeTabOptions !== false && [
75
+ plugins.remarkCodeTab,
76
+ remarkCodeTabOptions
77
+ ],
78
+ "remarkNpm" in plugins && remarkNpmOptions !== false && [plugins.remarkNpm, remarkNpmOptions],
79
+ ...v,
80
+ remarkStructureOptions !== false && [
81
+ plugins.remarkStructure,
82
+ remarkStructureOptions
83
+ ],
84
+ valueToExport.length > 0 && (() => {
85
+ return (_, file) => {
86
+ file.data["mdx-export"] ??= [];
87
+ for (const name of valueToExport) {
88
+ if (!(name in file.data)) continue;
89
+ file.data["mdx-export"].push({
90
+ name,
91
+ value: file.data[name]
92
+ });
93
+ }
94
+ };
95
+ })
78
96
  ],
79
- "remarkNpm" in plugins && remarkNpmOptions !== false && [plugins.remarkNpm, remarkNpmOptions],
80
- ...v,
81
- remarkStructureOptions !== false && [
82
- plugins.remarkStructure,
83
- remarkStructureOptions
97
+ mdxOptions.remarkPlugins
98
+ );
99
+ const rehypePlugins = pluginOption(
100
+ (v) => [
101
+ rehypeCodeOptions !== false && [plugins.rehypeCode, rehypeCodeOptions],
102
+ ...v,
103
+ plugins.rehypeToc
84
104
  ],
85
- () => {
86
- return (_, file) => {
87
- file.data["mdx-export"] ??= [];
88
- for (const name of valueToExport) {
89
- if (name in file.data)
90
- file.data["mdx-export"].push({ name, value: file.data[name] });
91
- }
92
- };
93
- }
94
- ],
95
- mdxOptions.remarkPlugins
96
- );
97
- const rehypePlugins = pluginOption(
98
- (v) => [
99
- rehypeCodeOptions !== false && [plugins.rehypeCode, rehypeCodeOptions],
100
- ...v,
101
- plugins.rehypeToc
102
- ],
103
- mdxOptions.rehypePlugins
104
- );
105
- return {
106
- ...mdxOptions,
107
- outputFormat: _withoutBundler ? "function-body" : mdxOptions.outputFormat,
108
- remarkPlugins,
109
- rehypePlugins
105
+ mdxOptions.rehypePlugins
106
+ );
107
+ return {
108
+ ...mdxOptions,
109
+ outputFormat: environment === "runtime" ? "function-body" : mdxOptions.outputFormat,
110
+ remarkPlugins,
111
+ rehypePlugins
112
+ };
110
113
  };
111
114
  }
112
- var plugins;
113
115
  var init_preset = __esm({
114
- "src/loaders/mdx/preset.ts"() {
116
+ "src/config/preset.ts"() {
115
117
  "use strict";
116
- plugins = __toESM(require("fumadocs-core/mdx-plugins"), 1);
117
118
  }
118
119
  });
119
120
 
@@ -124,7 +125,10 @@ function buildCollection(name, config) {
124
125
  ...config,
125
126
  name,
126
127
  meta: buildPrimitiveCollection(name, config.meta),
127
- docs: buildPrimitiveCollection(name, config.docs)
128
+ docs: buildPrimitiveCollection(name, config.docs),
129
+ hasFile(filePath) {
130
+ return this.docs.hasFile(filePath) || this.meta.hasFile(filePath);
131
+ }
128
132
  };
129
133
  }
130
134
  return buildPrimitiveCollection(name, config);
@@ -178,11 +182,6 @@ function buildConfig(config) {
178
182
  `Unknown export "${k}", you can only export collections from source configuration file.`
179
183
  );
180
184
  }
181
- if (loaded.collections) {
182
- for (const [k, v] of Object.entries(loaded.collections)) {
183
- collections.set(k, buildCollection(k, v));
184
- }
185
- }
186
185
  const mdxOptionsCache = /* @__PURE__ */ new Map();
187
186
  return {
188
187
  global: loaded,
@@ -190,21 +189,22 @@ function buildConfig(config) {
190
189
  getCollection(name) {
191
190
  return collections.get(name);
192
191
  },
193
- async getDefaultMDXOptions(mode = "default") {
194
- const cached = mdxOptionsCache.get(mode);
192
+ getMDXOptions(collection, environment = "bundler") {
193
+ const key = collection ? `${environment}:${collection.name}` : environment;
194
+ const cached = mdxOptionsCache.get(key);
195
195
  if (cached) return cached;
196
- const input = this.global.mdxOptions;
197
- async function uncached() {
198
- const options = typeof input === "function" ? await input() : input;
199
- const { getDefaultMDXOptions: getDefaultMDXOptions2 } = await Promise.resolve().then(() => (init_preset(), preset_exports));
200
- if (options?.preset === "minimal") return options;
201
- return getDefaultMDXOptions2({
202
- ...options,
203
- _withoutBundler: mode === "remote"
204
- });
196
+ let result;
197
+ if (collection?.mdxOptions) {
198
+ const optionsFn = collection.mdxOptions;
199
+ result = typeof optionsFn === "function" ? optionsFn(environment) : optionsFn;
200
+ } else {
201
+ result = (async () => {
202
+ const optionsFn = this.global.mdxOptions;
203
+ const options = typeof optionsFn === "function" ? await optionsFn() : optionsFn;
204
+ return applyMdxPreset(options)(environment);
205
+ })();
205
206
  }
206
- const result = uncached();
207
- mdxOptionsCache.set(mode, result);
207
+ mdxOptionsCache.set(key, result);
208
208
  return result;
209
209
  }
210
210
  };
@@ -214,6 +214,7 @@ var init_build = __esm({
214
214
  "src/config/build.ts"() {
215
215
  "use strict";
216
216
  import_picomatch = __toESM(require("picomatch"), 1);
217
+ init_preset();
217
218
  SupportedFormats = {
218
219
  doc: ["mdx", "md"],
219
220
  meta: ["json", "yaml"]
@@ -221,101 +222,7 @@ var init_build = __esm({
221
222
  }
222
223
  });
223
224
 
224
- // src/config/load-from-file.ts
225
- var load_from_file_exports = {};
226
- __export(load_from_file_exports, {
227
- loadConfig: () => loadConfig
228
- });
229
- async function compileConfig(configPath, outDir) {
230
- const { build } = await import("esbuild");
231
- const transformed = await build({
232
- entryPoints: [{ in: configPath, out: "source.config" }],
233
- bundle: true,
234
- outdir: outDir,
235
- target: "node20",
236
- write: true,
237
- platform: "node",
238
- format: "esm",
239
- packages: "external",
240
- outExtension: {
241
- ".js": ".mjs"
242
- },
243
- allowOverwrite: true
244
- });
245
- if (transformed.errors.length > 0) {
246
- throw new Error("failed to compile configuration file");
247
- }
248
- }
249
- async function loadConfig(configPath, outDir, build = false) {
250
- if (build) await compileConfig(configPath, outDir);
251
- const url = (0, import_node_url3.pathToFileURL)(path9.resolve(outDir, "source.config.mjs"));
252
- url.searchParams.set("hash", Date.now().toString());
253
- const config = import(url.href).then(
254
- (loaded) => buildConfig(loaded)
255
- );
256
- return await config;
257
- }
258
- var path9, import_node_url3;
259
- var init_load_from_file = __esm({
260
- "src/config/load-from-file.ts"() {
261
- "use strict";
262
- path9 = __toESM(require("path"), 1);
263
- import_node_url3 = require("url");
264
- init_build();
265
- }
266
- });
267
-
268
- // src/vite/index.ts
269
- var vite_exports = {};
270
- __export(vite_exports, {
271
- default: () => mdx,
272
- postInstall: () => postInstall
273
- });
274
- module.exports = __toCommonJS(vite_exports);
275
- var import_vite = require("vite");
276
- init_build();
277
-
278
- // src/utils/validation.ts
279
- var import_picocolors = __toESM(require("picocolors"), 1);
280
- var ValidationError = class extends Error {
281
- constructor(message, issues) {
282
- super(
283
- `${message}:
284
- ${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
285
- );
286
- this.title = message;
287
- this.issues = issues;
288
- }
289
- toStringFormatted() {
290
- return [
291
- import_picocolors.default.bold(`[MDX] ${this.title}:`),
292
- ...this.issues.map(
293
- (issue) => import_picocolors.default.redBright(
294
- `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
295
- )
296
- )
297
- ].join("\n");
298
- }
299
- };
300
- async function validate(schema, data, context, errorMessage) {
301
- if (typeof schema === "function" && !("~standard" in schema)) {
302
- schema = schema(context);
303
- }
304
- if ("~standard" in schema) {
305
- const result = await schema["~standard"].validate(
306
- data
307
- );
308
- if (result.issues) {
309
- throw new ValidationError(errorMessage, result.issues);
310
- }
311
- return result.value;
312
- }
313
- return data;
314
- }
315
-
316
225
  // src/utils/fuma-matter.ts
317
- var import_js_yaml = require("js-yaml");
318
- var regex = /^---\r?\n(.+?)\r?\n---\r?\n/s;
319
226
  function fumaMatter(input) {
320
227
  const output = { matter: "", data: {}, content: input };
321
228
  const match = regex.exec(input);
@@ -328,42 +235,16 @@ function fumaMatter(input) {
328
235
  output.data = loaded ?? {};
329
236
  return output;
330
237
  }
331
-
332
- // src/utils/git-timestamp.ts
333
- var import_node_path = __toESM(require("path"), 1);
334
- var import_tinyexec = require("tinyexec");
335
- var cache = /* @__PURE__ */ new Map();
336
- async function getGitTimestamp(file) {
337
- const cached = cache.get(file);
338
- if (cached) return cached;
339
- try {
340
- const out = await (0, import_tinyexec.x)(
341
- "git",
342
- ["log", "-1", '--pretty="%ai"', import_node_path.default.relative(process.cwd(), file)],
343
- {
344
- throwOnError: true
345
- }
346
- );
347
- const time = new Date(out.stdout);
348
- cache.set(file, time);
349
- return time;
350
- } catch {
351
- return;
238
+ var import_js_yaml, regex;
239
+ var init_fuma_matter = __esm({
240
+ "src/utils/fuma-matter.ts"() {
241
+ "use strict";
242
+ import_js_yaml = require("js-yaml");
243
+ regex = /^---\r?\n(.+?)\r?\n---\r?\n/s;
352
244
  }
353
- }
354
-
355
- // src/loaders/mdx/build-mdx.ts
356
- var import_mdx = require("@mdx-js/mdx");
357
-
358
- // src/loaders/mdx/remark-include.ts
359
- var import_unified = require("unified");
360
- var import_unist_util_visit2 = require("unist-util-visit");
361
- var path2 = __toESM(require("path"), 1);
362
- var fs = __toESM(require("fs/promises"), 1);
363
- var import_mdx_plugins = require("fumadocs-core/mdx-plugins");
245
+ });
364
246
 
365
247
  // src/loaders/mdx/remark-unravel.ts
366
- var import_unist_util_visit = require("unist-util-visit");
367
248
  function remarkMarkAndUnravel() {
368
249
  return (tree) => {
369
250
  (0, import_unist_util_visit.visit)(tree, function(node, index, parent) {
@@ -405,15 +286,28 @@ function remarkMarkAndUnravel() {
405
286
  });
406
287
  };
407
288
  }
289
+ var import_unist_util_visit;
290
+ var init_remark_unravel = __esm({
291
+ "src/loaders/mdx/remark-unravel.ts"() {
292
+ "use strict";
293
+ import_unist_util_visit = require("unist-util-visit");
294
+ }
295
+ });
296
+
297
+ // src/loaders/mdx/mdast-utils.ts
298
+ function flattenNode(node) {
299
+ if ("children" in node)
300
+ return node.children.map((child) => flattenNode(child)).join("");
301
+ if ("value" in node) return node.value;
302
+ return "";
303
+ }
304
+ var init_mdast_utils = __esm({
305
+ "src/loaders/mdx/mdast-utils.ts"() {
306
+ "use strict";
307
+ }
308
+ });
408
309
 
409
310
  // src/loaders/mdx/remark-include.ts
410
- var ElementLikeTypes = [
411
- "mdxJsxFlowElement",
412
- "mdxJsxTextElement",
413
- "containerDirective",
414
- "textDirective",
415
- "leafDirective"
416
- ];
417
311
  function isElementLike(node) {
418
312
  return ElementLikeTypes.includes(node.type);
419
313
  }
@@ -429,12 +323,6 @@ function parseElementAttributes(element) {
429
323
  }
430
324
  return element.attributes ?? {};
431
325
  }
432
- function flattenNode(node) {
433
- if ("children" in node)
434
- return node.children.map((child) => flattenNode(child)).join("");
435
- if ("value" in node) return node.value;
436
- return "";
437
- }
438
326
  function parseSpecifier(specifier) {
439
327
  const idx = specifier.lastIndexOf("#");
440
328
  if (idx === -1) return { file: specifier };
@@ -489,7 +377,7 @@ ${e instanceof Error ? e.message : String(e)}`,
489
377
  { cause: e }
490
378
  );
491
379
  }
492
- const ext = path2.extname(file);
380
+ const ext = path.extname(file);
493
381
  data._compiler?.addDependency(file);
494
382
  if (params.lang || ext !== ".md" && ext !== ".mdx") {
495
383
  const lang = params.lang ?? ext.slice(1);
@@ -522,7 +410,7 @@ ${e instanceof Error ? e.message : String(e)}`,
522
410
  } else {
523
411
  mdast = await baseProcessor.run(mdast);
524
412
  }
525
- await update(mdast, path2.dirname(file), data);
413
+ await update(mdast, path.dirname(file), data);
526
414
  return mdast;
527
415
  };
528
416
  async function update(tree, directory, data) {
@@ -534,7 +422,7 @@ ${e instanceof Error ? e.message : String(e)}`,
534
422
  if (specifier.length === 0) return "skip";
535
423
  const attributes = parseElementAttributes(node);
536
424
  const { file: relativePath, section } = parseSpecifier(specifier);
537
- const file = path2.resolve(
425
+ const file = path.resolve(
538
426
  "cwd" in attributes ? process.cwd() : directory,
539
427
  relativePath
540
428
  );
@@ -551,62 +439,96 @@ ${e instanceof Error ? e.message : String(e)}`,
551
439
  await Promise.all(queue);
552
440
  }
553
441
  return async (tree, file) => {
554
- await update(tree, path2.dirname(file.path), file.data);
442
+ await update(tree, path.dirname(file.path), file.data);
555
443
  };
556
444
  }
445
+ var import_unified, import_unist_util_visit2, path, fs, import_mdx_plugins, ElementLikeTypes;
446
+ var init_remark_include = __esm({
447
+ "src/loaders/mdx/remark-include.ts"() {
448
+ "use strict";
449
+ import_unified = require("unified");
450
+ import_unist_util_visit2 = require("unist-util-visit");
451
+ path = __toESM(require("path"), 1);
452
+ fs = __toESM(require("fs/promises"), 1);
453
+ init_fuma_matter();
454
+ import_mdx_plugins = require("fumadocs-core/mdx-plugins");
455
+ init_remark_unravel();
456
+ init_mdast_utils();
457
+ ElementLikeTypes = [
458
+ "mdxJsxFlowElement",
459
+ "mdxJsxTextElement",
460
+ "containerDirective",
461
+ "textDirective",
462
+ "leafDirective"
463
+ ];
464
+ }
465
+ });
557
466
 
558
467
  // src/loaders/mdx/remark-postprocess.ts
559
- var import_unist_util_visit3 = require("unist-util-visit");
560
- var import_mdast_util_to_markdown = require("mdast-util-to-markdown");
561
- var import_estree_util_value_to_estree = require("estree-util-value-to-estree");
562
- var import_unist_util_remove_position = require("unist-util-remove-position");
563
- var import_remark_mdx = __toESM(require("remark-mdx"), 1);
564
468
  function remarkPostprocess({
565
469
  _format,
566
470
  includeProcessedMarkdown = false,
567
471
  includeMDAST = false,
472
+ extractLinkReferences = false,
568
473
  valueToExport = []
569
474
  }) {
570
475
  let _stringifyProcessor;
571
476
  const getStringifyProcessor = () => {
572
- if (_format === "mdx") return this;
573
- return _stringifyProcessor ??= this().use(import_remark_mdx.default).freeze();
477
+ return _stringifyProcessor ??= _format === "mdx" ? this : (
478
+ // force Markdown processor to stringify MDX nodes
479
+ this().use(import_remark_mdx.default).freeze()
480
+ );
574
481
  };
575
482
  return (tree, file) => {
576
- let title;
577
- const urls = [];
578
- (0, import_unist_util_visit3.visit)(tree, ["heading", "link"], (node) => {
579
- if (node.type === "heading" && node.depth === 1) {
580
- title = flattenNode2(node);
581
- }
582
- if (node.type !== "link") return;
583
- urls.push({
584
- href: node.url
483
+ const frontmatter = file.data.frontmatter ??= {};
484
+ if (!frontmatter.title) {
485
+ (0, import_unist_util_visit3.visit)(tree, "heading", (node) => {
486
+ if (node.depth === 1) {
487
+ frontmatter.title = flattenNode(node);
488
+ return false;
489
+ }
490
+ });
491
+ }
492
+ file.data["mdx-export"] ??= [];
493
+ if (extractLinkReferences) {
494
+ const urls = [];
495
+ (0, import_unist_util_visit3.visit)(tree, "link", (node) => {
496
+ urls.push({
497
+ href: node.url
498
+ });
499
+ return "skip";
500
+ });
501
+ file.data["mdx-export"].push({
502
+ name: "extractedReferences",
503
+ value: urls
585
504
  });
586
- return "skip";
587
- });
588
- if (title) {
589
- file.data.frontmatter ??= {};
590
- if (!file.data.frontmatter.title) file.data.frontmatter.title = title;
591
505
  }
592
- file.data.extractedReferences = urls;
593
506
  if (includeProcessedMarkdown) {
594
507
  const processor = getStringifyProcessor();
595
- file.data._markdown = (0, import_mdast_util_to_markdown.toMarkdown)(tree, {
508
+ const markdown = (0, import_mdast_util_to_markdown.toMarkdown)(tree, {
596
509
  ...processor.data("settings"),
597
510
  // from https://github.com/remarkjs/remark/blob/main/packages/remark-stringify/lib/index.js
598
511
  extensions: processor.data("toMarkdownExtensions") || []
599
512
  });
513
+ file.data["mdx-export"].push({
514
+ name: "_markdown",
515
+ value: markdown
516
+ });
600
517
  }
601
518
  if (includeMDAST) {
602
519
  const options = includeMDAST === true ? {} : includeMDAST;
603
- file.data._mdast = JSON.stringify(
520
+ const mdast = JSON.stringify(
604
521
  options.removePosition ? (0, import_unist_util_remove_position.removePosition)(structuredClone(tree)) : tree
605
522
  );
523
+ file.data["mdx-export"].push({
524
+ name: "_mdast",
525
+ value: mdast
526
+ });
606
527
  }
607
- for (const { name, value } of file.data["mdx-export"] ?? []) {
528
+ for (const { name, value } of file.data["mdx-export"]) {
608
529
  tree.children.unshift(getMdastExport(name, value));
609
530
  }
531
+ file.data["mdx-export"] = [];
610
532
  for (const name of valueToExport) {
611
533
  if (!(name in file.data)) continue;
612
534
  tree.children.unshift(getMdastExport(name, file.data[name]));
@@ -647,68 +569,179 @@ function getMdastExport(name, value) {
647
569
  }
648
570
  };
649
571
  }
650
- function flattenNode2(node) {
651
- if ("children" in node)
652
- return node.children.map((child) => flattenNode2(child)).join("");
653
- if ("value" in node) return node.value;
654
- return "";
655
- }
572
+ var import_unist_util_visit3, import_mdast_util_to_markdown, import_estree_util_value_to_estree, import_unist_util_remove_position, import_remark_mdx;
573
+ var init_remark_postprocess = __esm({
574
+ "src/loaders/mdx/remark-postprocess.ts"() {
575
+ "use strict";
576
+ import_unist_util_visit3 = require("unist-util-visit");
577
+ import_mdast_util_to_markdown = require("mdast-util-to-markdown");
578
+ import_estree_util_value_to_estree = require("estree-util-value-to-estree");
579
+ import_unist_util_remove_position = require("unist-util-remove-position");
580
+ import_remark_mdx = __toESM(require("remark-mdx"), 1);
581
+ init_mdast_utils();
582
+ }
583
+ });
656
584
 
657
585
  // src/loaders/mdx/build-mdx.ts
658
- var cache2 = /* @__PURE__ */ new Map();
659
- async function buildMDX(cacheKey, source, options) {
660
- const { filePath, frontmatter, data, _compiler, ...rest } = options;
586
+ var build_mdx_exports = {};
587
+ __export(build_mdx_exports, {
588
+ buildMDX: () => buildMDX
589
+ });
590
+ async function buildMDX(core, collection, {
591
+ filePath,
592
+ frontmatter,
593
+ source,
594
+ _compiler,
595
+ environment,
596
+ isDevelopment
597
+ }) {
598
+ const mdxOptions = await core.getConfig().getMDXOptions(collection, environment);
661
599
  function getProcessor(format) {
662
- const key = `${cacheKey}:${format}`;
663
- let processor = cache2.get(key);
600
+ const cache = core.cache;
601
+ const key = `build-mdx:${collection?.name ?? "global"}:${format}`;
602
+ let processor = cache.get(key);
664
603
  if (!processor) {
604
+ const postprocessOptions = {
605
+ _format: format,
606
+ ...collection?.postprocess,
607
+ valueToExport: [
608
+ ...collection?.postprocess?.valueToExport ?? [],
609
+ "structuredData",
610
+ "frontmatter"
611
+ ]
612
+ };
665
613
  processor = (0, import_mdx.createProcessor)({
666
614
  outputFormat: "program",
667
- ...rest,
615
+ development: isDevelopment,
616
+ ...mdxOptions,
668
617
  remarkPlugins: [
669
618
  remarkInclude,
670
- ...rest.remarkPlugins ?? [],
671
- [
672
- remarkPostprocess,
673
- {
674
- _format: format,
675
- ...options.postprocess,
676
- valueToExport: [
677
- ...options.postprocess?.valueToExport ?? [],
678
- "structuredData",
679
- "extractedReferences",
680
- "frontmatter",
681
- "lastModified",
682
- "_markdown",
683
- "_mdast"
684
- ]
685
- }
686
- ]
619
+ ...mdxOptions.remarkPlugins ?? [],
620
+ [remarkPostprocess, postprocessOptions]
687
621
  ],
688
622
  format
689
623
  });
690
- cache2.set(key, processor);
624
+ cache.set(key, processor);
691
625
  }
692
626
  return processor;
693
627
  }
694
- return getProcessor(
695
- options.format ?? (filePath.endsWith(".mdx") ? "mdx" : "md")
696
- ).process({
628
+ let vfile = new import_vfile.VFile({
697
629
  value: source,
698
630
  path: filePath,
699
- data: {
700
- ...data,
701
- frontmatter,
702
- _compiler,
703
- _getProcessor: getProcessor
704
- }
631
+ data: { frontmatter, _compiler, _getProcessor: getProcessor }
632
+ });
633
+ if (collection) {
634
+ vfile = await core.transformVFile({ collection, filePath, source }, vfile);
635
+ }
636
+ return getProcessor(filePath.endsWith(".mdx") ? "mdx" : "md").process(vfile);
637
+ }
638
+ var import_mdx, import_vfile;
639
+ var init_build_mdx = __esm({
640
+ "src/loaders/mdx/build-mdx.ts"() {
641
+ "use strict";
642
+ import_mdx = require("@mdx-js/mdx");
643
+ import_vfile = require("vfile");
644
+ init_remark_include();
645
+ init_remark_postprocess();
646
+ }
647
+ });
648
+
649
+ // src/config/load-from-file.ts
650
+ var load_from_file_exports = {};
651
+ __export(load_from_file_exports, {
652
+ loadConfig: () => loadConfig
653
+ });
654
+ async function compileConfig(core) {
655
+ const { build } = await import("esbuild");
656
+ const transformed = await build({
657
+ entryPoints: [{ in: core._options.configPath, out: "source.config" }],
658
+ bundle: true,
659
+ outdir: core._options.outDir,
660
+ target: "node20",
661
+ write: true,
662
+ platform: "node",
663
+ format: "esm",
664
+ packages: "external",
665
+ outExtension: {
666
+ ".js": ".mjs"
667
+ },
668
+ allowOverwrite: true
705
669
  });
670
+ if (transformed.errors.length > 0) {
671
+ throw new Error("failed to compile configuration file");
672
+ }
673
+ }
674
+ async function loadConfig(core, build = false) {
675
+ if (build) await compileConfig(core);
676
+ const url = (0, import_node_url2.pathToFileURL)(core.getCompiledConfigPath());
677
+ url.searchParams.set("hash", Date.now().toString());
678
+ const config = import(url.href).then(
679
+ (loaded) => buildConfig(loaded)
680
+ );
681
+ return await config;
682
+ }
683
+ var import_node_url2;
684
+ var init_load_from_file = __esm({
685
+ "src/config/load-from-file.ts"() {
686
+ "use strict";
687
+ import_node_url2 = require("url");
688
+ init_build();
689
+ }
690
+ });
691
+
692
+ // src/vite/index.ts
693
+ var vite_exports = {};
694
+ __export(vite_exports, {
695
+ default: () => mdx,
696
+ postInstall: () => postInstall
697
+ });
698
+ module.exports = __toCommonJS(vite_exports);
699
+ var import_vite = require("vite");
700
+ init_build();
701
+
702
+ // src/utils/validation.ts
703
+ var ValidationError = class extends Error {
704
+ constructor(message, issues) {
705
+ super(
706
+ `${message}:
707
+ ${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
708
+ );
709
+ this.title = message;
710
+ this.issues = issues;
711
+ }
712
+ async toStringFormatted() {
713
+ const picocolors = await import("picocolors");
714
+ return [
715
+ picocolors.bold(`[MDX] ${this.title}:`),
716
+ ...this.issues.map(
717
+ (issue) => picocolors.redBright(
718
+ `- ${picocolors.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
719
+ )
720
+ )
721
+ ].join("\n");
722
+ }
723
+ };
724
+ async function validate(schema, data, context, errorMessage) {
725
+ if (typeof schema === "function" && !("~standard" in schema)) {
726
+ schema = schema(context);
727
+ }
728
+ if ("~standard" in schema) {
729
+ const result = await schema["~standard"].validate(
730
+ data
731
+ );
732
+ if (result.issues) {
733
+ throw new ValidationError(errorMessage, result.issues);
734
+ }
735
+ return result.value;
736
+ }
737
+ return data;
706
738
  }
707
739
 
708
740
  // src/loaders/mdx/index.ts
741
+ init_fuma_matter();
709
742
  var import_zod = require("zod");
710
743
  var import_promises = __toESM(require("fs/promises"), 1);
711
- var import_node_path2 = __toESM(require("path"), 1);
744
+ var import_node_path = __toESM(require("path"), 1);
712
745
  var import_node_crypto = require("crypto");
713
746
 
714
747
  // src/loaders/index.ts
@@ -735,20 +768,20 @@ function createMdxLoader(configLoader) {
735
768
  compiler,
736
769
  filePath
737
770
  }) {
771
+ const config = await configLoader.getConfig();
738
772
  const value = await getSource();
739
773
  const matter = fumaMatter(value);
740
774
  const parsed = querySchema.parse(query);
741
- const config = await configLoader.getConfig();
742
775
  let after;
743
776
  if (!isDevelopment && config.global.experimentalBuildCache) {
744
777
  const cacheDir = config.global.experimentalBuildCache;
745
778
  const cacheKey = `${parsed.hash}_${parsed.collection ?? "global"}_${generateCacheHash(filePath)}`;
746
- const cached = await import_promises.default.readFile(import_node_path2.default.join(cacheDir, cacheKey)).then((content) => cacheEntry.parse(JSON.parse(content.toString()))).catch(() => null);
779
+ const cached = await import_promises.default.readFile(import_node_path.default.join(cacheDir, cacheKey)).then((content) => cacheEntry.parse(JSON.parse(content.toString()))).catch(() => null);
747
780
  if (cached && cached.hash === generateCacheHash(value)) return cached;
748
781
  after = async () => {
749
782
  await import_promises.default.mkdir(cacheDir, { recursive: true });
750
783
  await import_promises.default.writeFile(
751
- import_node_path2.default.join(cacheDir, cacheKey),
784
+ import_node_path.default.join(cacheDir, cacheKey),
752
785
  JSON.stringify({
753
786
  ...out,
754
787
  hash: generateCacheHash(value)
@@ -766,15 +799,10 @@ function createMdxLoader(configLoader) {
766
799
  docCollection = collection.docs;
767
800
  break;
768
801
  }
769
- if (docCollection?.schema) {
770
- matter.data = await validate(
771
- docCollection.schema,
772
- matter.data,
773
- {
774
- source: value,
775
- path: filePath
776
- },
777
- `invalid frontmatter in ${filePath}`
802
+ if (docCollection) {
803
+ matter.data = await configLoader.core.transformFrontmatter(
804
+ { collection: docCollection, filePath, source: value },
805
+ matter.data
778
806
  );
779
807
  }
780
808
  if (parsed.only === "frontmatter") {
@@ -783,24 +811,16 @@ function createMdxLoader(configLoader) {
783
811
  map: null
784
812
  };
785
813
  }
786
- const data = {};
787
- if (config.global.lastModifiedTime === "git") {
788
- data.lastModified = (await getGitTimestamp(filePath))?.getTime();
789
- }
790
814
  const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
791
- const compiled = await buildMDX(
792
- `${getConfigHash(config)}:${parsed.collection ?? "global"}`,
793
- "\n".repeat(lineOffset) + matter.content,
794
- {
795
- development: isDevelopment,
796
- ...docCollection?.mdxOptions ?? await config.getDefaultMDXOptions(),
797
- postprocess: docCollection?.postprocess,
798
- data,
799
- filePath,
800
- frontmatter: matter.data,
801
- _compiler: compiler
802
- }
803
- );
815
+ const { buildMDX: buildMDX2 } = await Promise.resolve().then(() => (init_build_mdx(), build_mdx_exports));
816
+ const compiled = await buildMDX2(configLoader.core, docCollection, {
817
+ isDevelopment,
818
+ source: "\n".repeat(lineOffset) + matter.content,
819
+ filePath,
820
+ frontmatter: matter.data,
821
+ _compiler: compiler,
822
+ environment: "bundler"
823
+ });
804
824
  const out = {
805
825
  code: String(compiled.value),
806
826
  map: compiled.map
@@ -810,14 +830,6 @@ function createMdxLoader(configLoader) {
810
830
  }
811
831
  };
812
832
  }
813
- var hashes = /* @__PURE__ */ new WeakMap();
814
- function getConfigHash(config) {
815
- let hash = hashes.get(config);
816
- if (hash) return hash;
817
- hash = Date.now().toString();
818
- hashes.set(config, hash);
819
- return hash;
820
- }
821
833
  function generateCacheHash(input) {
822
834
  return (0, import_node_crypto.createHash)("md5").update(input).digest("hex");
823
835
  }
@@ -833,7 +845,7 @@ function countLines(s) {
833
845
  var import_node_url = require("url");
834
846
  var import_promises2 = __toESM(require("fs/promises"), 1);
835
847
  var import_node_querystring = require("querystring");
836
- var import_node_path3 = __toESM(require("path"), 1);
848
+ var import_node_path2 = __toESM(require("path"), 1);
837
849
  var import_node_fs = require("fs");
838
850
  function toVite(loader) {
839
851
  return {
@@ -864,240 +876,69 @@ function toVite(loader) {
864
876
  };
865
877
  }
866
878
 
867
- // src/utils/import-formatter.ts
879
+ // src/core.ts
868
880
  var import_node_path4 = __toESM(require("path"), 1);
869
- function toImportPath(file, config) {
870
- const ext = import_node_path4.default.extname(file);
871
- let filename;
872
- if (ext === ".ts" && config.jsExtension) {
873
- filename = file.substring(0, file.length - ext.length) + ".js";
874
- } else if (ext === ".ts") {
875
- filename = file.substring(0, file.length - ext.length);
876
- } else {
877
- filename = file;
878
- }
879
- let importPath;
880
- if ("relativeTo" in config) {
881
- importPath = import_node_path4.default.relative(config.relativeTo, filename);
882
- if (!import_node_path4.default.isAbsolute(importPath) && !importPath.startsWith(".")) {
883
- importPath = `./${importPath}`;
884
- }
885
- } else {
886
- importPath = import_node_path4.default.resolve(filename);
887
- }
888
- return importPath.replaceAll(import_node_path4.default.sep, "/");
889
- }
890
- function ident(code, tab = 1) {
891
- return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
892
- }
893
-
894
- // src/utils/glob-import.ts
895
- var import_tinyglobby = require("tinyglobby");
896
- var import_node_path5 = __toESM(require("path"), 1);
897
- var import_node_url2 = require("url");
898
- function generateGlobImport(patterns, options) {
899
- let code = "{";
900
- const result = (0, import_tinyglobby.globSync)(patterns, {
901
- cwd: options.base
902
- });
903
- for (const item of result) {
904
- const fullPath = import_node_path5.default.join(options.base, item);
905
- const url = (0, import_node_url2.pathToFileURL)(fullPath);
906
- for (const [k, v] of Object.entries(options.query ?? {})) {
907
- url.searchParams.set(k, v);
908
- }
909
- let line = `${JSON.stringify(item)}: () => import(${JSON.stringify(url.href)})`;
910
- if (options.import) {
911
- line += `.then(mod => mod[${JSON.stringify(options.import)}])`;
912
- }
913
- code += `${line}, `;
914
- }
915
- code += "}";
916
- return code;
917
- }
881
+ var import_promises4 = __toESM(require("fs/promises"), 1);
918
882
 
919
- // src/plugins/vite.ts
920
- var import_node_path6 = __toESM(require("path"), 1);
921
- function vite({
922
- index
923
- }) {
924
- let config;
925
- let indexOptions;
926
- if (index === false) indexOptions = false;
927
- else indexOptions = applyDefaults(index === true ? {} : index);
928
- return {
929
- name: "vite",
930
- config(v) {
931
- config = v;
932
- },
933
- configureServer(server) {
934
- if (!server.watcher || indexOptions === false || indexOptions.runtime === false)
935
- return;
936
- server.watcher.on("all", (event, file) => {
937
- if (event === "change") return;
938
- const isUpdated = config.collectionList.some((collection) => {
939
- if (collection.type === "docs")
940
- return collection.docs.hasFile(file) || collection.meta.hasFile(file);
941
- return collection.hasFile(file);
942
- });
943
- if (isUpdated) {
944
- this.core.emitAndWrite({
945
- filterPlugin: (plugin) => plugin.name === "vite"
946
- });
947
- }
948
- });
949
- },
950
- emit() {
951
- const out = [];
952
- if (indexOptions === false) return out;
953
- if (indexOptions.browser) {
954
- out.push({
955
- path: "browser.ts",
956
- content: indexFile(this, config, indexOptions, "browser")
957
- });
958
- }
959
- out.push({
960
- path: "index.ts",
961
- content: indexFile(
962
- this,
963
- config,
964
- indexOptions,
965
- indexOptions.browser ? "server" : "all"
966
- )
967
- });
968
- return out;
969
- }
970
- };
971
- }
972
- function applyDefaults(options) {
973
- return {
974
- addJsExtension: options.addJsExtension ?? false,
975
- browser: options.browser ?? false,
976
- runtime: options.runtime ?? false
977
- };
978
- }
979
- function indexFile({ configPath, outDir }, config, { addJsExtension, runtime }, environment) {
980
- const runtimePath = {
981
- all: "fumadocs-mdx/runtime/vite",
982
- server: "fumadocs-mdx/runtime/vite.server",
983
- browser: "fumadocs-mdx/runtime/vite.browser"
984
- }[environment];
985
- const lines = [
986
- '/// <reference types="vite/client" />',
987
- `import { fromConfig } from '${runtimePath}';`,
988
- `import type * as Config from '${toImportPath(configPath, {
989
- relativeTo: outDir,
990
- jsExtension: addJsExtension
991
- })}';`,
992
- "",
993
- `export const create = fromConfig<typeof Config>();`
994
- ];
995
- function generateCollectionGlob(collection) {
996
- if (collection.type === "docs") {
997
- const obj = [
998
- ident(`doc: ${generateCollectionGlob(collection.docs)}`),
999
- ident(`meta: ${generateCollectionGlob(collection.meta)}`)
1000
- ].join(",\n");
1001
- return `{
1002
- ${obj}
1003
- }`;
1004
- }
1005
- const dir = getCollectionDir(collection);
1006
- if (collection.type === "doc") {
1007
- const docGlob = generateGlob(collection.patterns, {
1008
- query: {
1009
- collection: collection.name
1010
- },
1011
- base: dir
1012
- });
1013
- if (collection.async) {
1014
- const headBlob = generateGlob(collection.patterns, {
1015
- query: {
1016
- only: "frontmatter",
1017
- collection: collection.name
1018
- },
1019
- import: "frontmatter",
1020
- base: dir
1021
- });
1022
- return `create.docLazy("${collection.name}", "${dir}", ${headBlob}, ${docGlob})`;
1023
- }
1024
- return `create.doc("${collection.name}", "${dir}", ${docGlob})`;
1025
- }
1026
- return `create.meta("${collection.name}", "${dir}", ${generateGlob(
1027
- collection.patterns,
1028
- {
1029
- import: "default",
1030
- base: dir,
1031
- query: {
1032
- collection: collection.name
1033
- }
1034
- }
1035
- )})`;
1036
- }
1037
- function generateGlob(patterns, options) {
1038
- patterns = patterns.map(normalizeGlobPath);
1039
- if (runtime === "node" || runtime === "bun") {
1040
- return generateGlobImport(patterns, options);
1041
- } else {
1042
- return `import.meta.glob(${JSON.stringify(patterns)}, ${JSON.stringify(
1043
- {
1044
- ...options,
1045
- base: normalizeGlobPath(import_node_path6.default.relative(outDir, options.base))
1046
- },
1047
- null,
1048
- 2
1049
- )})`;
1050
- }
1051
- }
1052
- for (const collection of config.collectionList) {
1053
- lines.push("");
1054
- lines.push(
1055
- `export const ${collection.name} = ${generateCollectionGlob(collection)};`
1056
- );
883
+ // src/utils/codegen/cache.ts
884
+ var import_lru_cache = require("lru-cache");
885
+ var import_promises3 = __toESM(require("fs/promises"), 1);
886
+ var import_node_path3 = __toESM(require("path"), 1);
887
+ var map = new import_lru_cache.LRUCache({
888
+ max: 100
889
+ });
890
+ function toFullPath(file) {
891
+ if (import_node_path3.default.isAbsolute(file)) {
892
+ return import_node_path3.default.relative(process.cwd(), file);
1057
893
  }
1058
- return lines.join("\n");
1059
- }
1060
- function normalizeGlobPath(file) {
1061
- file = slash(file);
1062
- if (file.startsWith("./")) return file;
1063
- if (file.startsWith("/")) return `.${file}`;
1064
- return `./${file}`;
894
+ return file;
1065
895
  }
1066
- function getCollectionDir({ dir }) {
1067
- if (Array.isArray(dir)) {
1068
- if (dir.length !== 1)
1069
- throw new Error(
1070
- `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
1071
- );
1072
- return dir[0];
1073
- }
1074
- return dir;
896
+ async function readFileWithCache(file) {
897
+ const fullPath = toFullPath(file);
898
+ const cached = map.get(fullPath);
899
+ if (cached) return cached;
900
+ const read = import_promises3.default.readFile(fullPath).then((s) => s.toString());
901
+ map.set(fullPath, read);
902
+ return read;
1075
903
  }
1076
- function slash(path10) {
1077
- const isExtendedLengthPath = path10.startsWith("\\\\?\\");
1078
- if (isExtendedLengthPath) {
1079
- return path10;
1080
- }
1081
- return path10.replaceAll("\\", "/");
904
+ function removeFileCache(file) {
905
+ map.delete(toFullPath(file));
1082
906
  }
1083
907
 
1084
908
  // src/core.ts
1085
- var import_node_path7 = __toESM(require("path"), 1);
1086
- var import_promises3 = __toESM(require("fs/promises"), 1);
1087
- function findConfigFile() {
1088
- return import_node_path7.default.resolve("source.config.ts");
909
+ var _Defaults = {
910
+ configPath: "source.config.ts",
911
+ outDir: ".source"
912
+ };
913
+ async function getPlugins(pluginOptions) {
914
+ const plugins = [];
915
+ for await (const option of pluginOptions) {
916
+ if (!option) continue;
917
+ if (Array.isArray(option)) plugins.push(...await getPlugins(option));
918
+ else plugins.push(option);
919
+ }
920
+ return plugins;
1089
921
  }
1090
922
  function createCore(options, defaultPlugins = []) {
1091
923
  let config;
1092
- let plugins2;
1093
- return {
924
+ let plugins;
925
+ async function transformMetadata({
926
+ collection,
927
+ filePath,
928
+ source
929
+ }, data) {
930
+ if (collection.schema) {
931
+ data = await validate(
932
+ collection.schema,
933
+ data,
934
+ { path: filePath, source },
935
+ collection.type === "doc" ? `invalid frontmatter in ${filePath}` : `invalid data in ${filePath}`
936
+ );
937
+ }
938
+ return data;
939
+ }
940
+ const core = {
1094
941
  _options: options,
1095
- getPluginContext() {
1096
- return {
1097
- core: this,
1098
- ...options
1099
- };
1100
- },
1101
942
  /**
1102
943
  * Convenient cache store, reset when config changes
1103
944
  */
@@ -1105,17 +946,12 @@ function createCore(options, defaultPlugins = []) {
1105
946
  async init({ config: newConfig }) {
1106
947
  config = await newConfig;
1107
948
  this.cache.clear();
1108
- plugins2 = [];
1109
- for await (const option of [
949
+ plugins = await getPlugins([
1110
950
  ...defaultPlugins,
1111
951
  ...config.global.plugins ?? []
1112
- ]) {
1113
- if (!option) continue;
1114
- if (Array.isArray(option)) plugins2.push(...option);
1115
- else plugins2.push(option);
1116
- }
1117
- for (const plugin of plugins2) {
1118
- const out = await plugin.config?.call(this.getPluginContext(), config);
952
+ ]);
953
+ for (const plugin of plugins) {
954
+ const out = await plugin.config?.call(pluginContext, config);
1119
955
  if (out) config = out;
1120
956
  }
1121
957
  return this;
@@ -1123,37 +959,88 @@ function createCore(options, defaultPlugins = []) {
1123
959
  getConfig() {
1124
960
  return config;
1125
961
  },
962
+ /**
963
+ * The file path of compiled config file, the file may not exist (e.g. on Vite, or still compiling)
964
+ */
965
+ getCompiledConfigPath() {
966
+ return import_node_path4.default.join(options.outDir, "source.config.mjs");
967
+ },
1126
968
  async initServer(server) {
1127
- for (const plugin of plugins2) {
1128
- await plugin.configureServer?.call(this.getPluginContext(), server);
969
+ server.watcher?.on("all", async (event, file) => {
970
+ if (event === "change") removeFileCache(file);
971
+ });
972
+ for (const plugin of plugins) {
973
+ await plugin.configureServer?.call(pluginContext, server);
1129
974
  }
1130
975
  },
1131
- async emitAndWrite({
1132
- filterPlugin = () => true
1133
- } = {}) {
1134
- const start = performance.now();
1135
- const out = await Promise.all(
1136
- plugins2.map((plugin) => {
976
+ async emit({ filterPlugin = () => true } = {}) {
977
+ return (await Promise.all(
978
+ plugins.map((plugin) => {
1137
979
  if (!filterPlugin(plugin) || !plugin.emit) return [];
1138
- return plugin.emit.call(this.getPluginContext());
980
+ return plugin.emit.call(pluginContext);
1139
981
  })
1140
- );
982
+ )).flat();
983
+ },
984
+ async emitAndWrite(emitOptions) {
985
+ const start = performance.now();
986
+ const out = await this.emit(emitOptions);
1141
987
  await Promise.all(
1142
- out.flat().map(async (entry) => {
1143
- const file = import_node_path7.default.join(options.outDir, entry.path);
1144
- await import_promises3.default.mkdir(import_node_path7.default.dirname(file), { recursive: true });
1145
- await import_promises3.default.writeFile(file, entry.content);
988
+ out.map(async (entry) => {
989
+ const file = import_node_path4.default.join(options.outDir, entry.path);
990
+ await import_promises4.default.mkdir(import_node_path4.default.dirname(file), { recursive: true });
991
+ await import_promises4.default.writeFile(file, entry.content);
1146
992
  })
1147
993
  );
1148
994
  console.log(`[MDX] generated files in ${performance.now() - start}ms`);
995
+ },
996
+ async transformMeta(options2, data) {
997
+ const ctx = {
998
+ ...pluginContext,
999
+ ...options2
1000
+ };
1001
+ data = await transformMetadata(options2, data);
1002
+ for (const plugin of plugins) {
1003
+ if (plugin.meta?.transform)
1004
+ data = await plugin.meta.transform.call(ctx, data) ?? data;
1005
+ }
1006
+ return data;
1007
+ },
1008
+ async transformFrontmatter(options2, data) {
1009
+ const ctx = {
1010
+ ...pluginContext,
1011
+ ...options2
1012
+ };
1013
+ data = await transformMetadata(options2, data);
1014
+ for (const plugin of plugins) {
1015
+ if (plugin.doc?.frontmatter)
1016
+ data = await plugin.doc.frontmatter.call(ctx, data) ?? data;
1017
+ }
1018
+ return data;
1019
+ },
1020
+ async transformVFile(options2, file) {
1021
+ const ctx = {
1022
+ ...pluginContext,
1023
+ ...options2
1024
+ };
1025
+ for (const plugin of plugins) {
1026
+ if (plugin.doc?.vfile)
1027
+ file = await plugin.doc.vfile.call(ctx, file) ?? file;
1028
+ }
1029
+ return file;
1149
1030
  }
1150
1031
  };
1032
+ const pluginContext = {
1033
+ core,
1034
+ ...options
1035
+ };
1036
+ return core;
1151
1037
  }
1152
1038
 
1153
1039
  // src/loaders/config.ts
1154
- var import_promises4 = __toESM(require("fs/promises"), 1);
1040
+ var import_promises5 = __toESM(require("fs/promises"), 1);
1155
1041
  function createIntegratedConfigLoader(core) {
1156
1042
  return {
1043
+ core,
1157
1044
  getConfig() {
1158
1045
  return core.getConfig();
1159
1046
  }
@@ -1166,72 +1053,479 @@ var import_zod2 = require("zod");
1166
1053
  var querySchema2 = import_zod2.z.object({
1167
1054
  collection: import_zod2.z.string().optional()
1168
1055
  }).loose();
1169
- function createMetaLoader(configLoader, resolve3 = {}) {
1170
- const { json: resolveJson = "js", yaml: resolveYaml = "js" } = resolve3;
1171
- function stringifyOutput(isJson, data) {
1172
- if (isJson) {
1173
- return resolveJson === "json" ? JSON.stringify(data) : `export default ${JSON.stringify(data)}`;
1174
- } else {
1175
- return resolveYaml === "yaml" ? (0, import_js_yaml2.dump)(data) : `export default ${JSON.stringify(data)}`;
1056
+ function createMetaLoader(configLoader, resolve2 = {}) {
1057
+ const { json: resolveJson = "js", yaml: resolveYaml = "js" } = resolve2;
1058
+ function parse2(filePath, source) {
1059
+ try {
1060
+ if (filePath.endsWith(".json")) return JSON.parse(source);
1061
+ if (filePath.endsWith(".yaml")) return (0, import_js_yaml2.load)(source);
1062
+ } catch (e) {
1063
+ throw new Error(`invalid data in ${filePath}`, { cause: e });
1176
1064
  }
1065
+ throw new Error("Unknown file type " + filePath);
1177
1066
  }
1178
- return {
1179
- test: metaLoaderGlob,
1180
- async load({ filePath, query, getSource }) {
1181
- const parsed = querySchema2.parse(query);
1182
- const collection = parsed.collection ? (await configLoader.getConfig()).getCollection(parsed.collection) : void 0;
1183
- if (!collection) return null;
1184
- const isJson = filePath.endsWith(".json");
1185
- const source = await getSource();
1186
- let data;
1187
- try {
1188
- data = isJson ? JSON.parse(source) : (0, import_js_yaml2.load)(source);
1189
- } catch (e) {
1190
- throw new Error(`invalid data in ${filePath}`, { cause: e });
1191
- }
1192
- let schema;
1067
+ function onMeta(source, { filePath, query }) {
1068
+ const parsed = querySchema2.safeParse(query);
1069
+ if (!parsed.success || !parsed.data.collection) return null;
1070
+ const collectionName = parsed.data.collection;
1071
+ return async () => {
1072
+ const config = await configLoader.getConfig();
1073
+ const collection = config.getCollection(collectionName);
1074
+ let metaCollection;
1193
1075
  switch (collection?.type) {
1194
1076
  case "meta":
1195
- schema = collection.schema;
1077
+ metaCollection = collection;
1196
1078
  break;
1197
1079
  case "docs":
1198
- schema = collection.meta.schema;
1080
+ metaCollection = collection.meta;
1199
1081
  break;
1200
1082
  }
1201
- if (schema) {
1202
- data = await validate(
1203
- schema,
1204
- data,
1205
- { path: filePath, source },
1206
- `invalid data in ${filePath}`
1207
- );
1083
+ const data = parse2(filePath, source);
1084
+ if (!metaCollection) return data;
1085
+ return configLoader.core.transformMeta(
1086
+ {
1087
+ collection: metaCollection,
1088
+ filePath,
1089
+ source
1090
+ },
1091
+ data
1092
+ );
1093
+ };
1094
+ }
1095
+ return {
1096
+ test: metaLoaderGlob,
1097
+ async load(input) {
1098
+ const result = onMeta(await input.getSource(), input);
1099
+ if (result === null) return null;
1100
+ const data = await result();
1101
+ if (input.filePath.endsWith(".json")) {
1102
+ return {
1103
+ code: resolveJson === "json" ? JSON.stringify(data) : `export default ${JSON.stringify(data)}`
1104
+ };
1105
+ } else {
1106
+ return {
1107
+ code: resolveYaml === "yaml" ? (0, import_js_yaml2.dump)(data) : `export default ${JSON.stringify(data)}`
1108
+ };
1208
1109
  }
1209
- return {
1210
- code: stringifyOutput(isJson, data)
1211
- };
1212
1110
  },
1213
1111
  bun: {
1214
- loadSync(source, { filePath }) {
1215
- const isJson = filePath.endsWith(".json");
1216
- let data;
1217
- try {
1218
- data = isJson ? JSON.parse(source) : (0, import_js_yaml2.load)(source);
1219
- } catch (e) {
1220
- throw new Error(`invalid data in ${filePath}`, { cause: e });
1112
+ load(source, input) {
1113
+ const result = onMeta(source, input);
1114
+ if (result === null)
1115
+ return {
1116
+ loader: "object",
1117
+ exports: parse2(input.filePath, source)
1118
+ };
1119
+ return result().then((data) => ({
1120
+ loader: "object",
1121
+ exports: { default: data }
1122
+ }));
1123
+ }
1124
+ }
1125
+ };
1126
+ }
1127
+
1128
+ // src/plugins/index-file.ts
1129
+ var import_path = __toESM(require("path"), 1);
1130
+
1131
+ // src/utils/codegen/index.ts
1132
+ var import_node_path5 = __toESM(require("path"), 1);
1133
+ var import_tinyglobby = require("tinyglobby");
1134
+ function createCodegen({
1135
+ target = "default",
1136
+ outDir = "",
1137
+ jsExtension = false,
1138
+ globCache = /* @__PURE__ */ new Map()
1139
+ }) {
1140
+ let eagerImportId = 0;
1141
+ const banner = ["// @ts-nocheck"];
1142
+ if (target === "vite") {
1143
+ banner.push('/// <reference types="vite/client" />');
1144
+ }
1145
+ return {
1146
+ options: {
1147
+ target,
1148
+ outDir
1149
+ },
1150
+ lines: [],
1151
+ addImport(statement) {
1152
+ this.lines.unshift(statement);
1153
+ },
1154
+ async pushAsync(insert) {
1155
+ for (const line of await Promise.all(insert)) {
1156
+ if (line === void 0) continue;
1157
+ this.lines.push(line);
1158
+ }
1159
+ },
1160
+ async generateGlobImport(patterns, options) {
1161
+ if (target === "vite") {
1162
+ return this.generateViteGlobImport(patterns, options);
1163
+ }
1164
+ return this.generateNodeGlobImport(patterns, options);
1165
+ },
1166
+ generateViteGlobImport(patterns, { base, ...rest }) {
1167
+ patterns = (typeof patterns === "string" ? [patterns] : patterns).map(
1168
+ normalizeViteGlobPath
1169
+ );
1170
+ return `import.meta.glob(${JSON.stringify(patterns)}, ${JSON.stringify(
1171
+ {
1172
+ base: normalizeViteGlobPath(import_node_path5.default.relative(outDir, base)),
1173
+ ...rest
1174
+ },
1175
+ null,
1176
+ 2
1177
+ )})`;
1178
+ },
1179
+ async generateNodeGlobImport(patterns, {
1180
+ base,
1181
+ eager = false,
1182
+ query = {},
1183
+ import: importName
1184
+ }) {
1185
+ const cacheKey = JSON.stringify({ patterns, base });
1186
+ let files = globCache.get(cacheKey);
1187
+ if (!files) {
1188
+ files = (0, import_tinyglobby.glob)(patterns, {
1189
+ cwd: base
1190
+ });
1191
+ globCache.set(cacheKey, files);
1192
+ }
1193
+ let code = "{";
1194
+ for (const item of await files) {
1195
+ const fullPath = import_node_path5.default.join(base, item);
1196
+ const searchParams = new URLSearchParams();
1197
+ for (const [k, v] of Object.entries(query)) {
1198
+ searchParams.set(k, v);
1199
+ }
1200
+ const importPath = this.formatImportPath(fullPath) + "?" + searchParams.toString();
1201
+ if (eager) {
1202
+ const name = `__fd_glob_${eagerImportId++}`;
1203
+ this.lines.unshift(
1204
+ importName ? `import { ${importName} as ${name} } from ${JSON.stringify(importPath)}` : `import * as ${name} from ${JSON.stringify(importPath)}`
1205
+ );
1206
+ code += `${JSON.stringify(item)}: ${name}, `;
1207
+ } else {
1208
+ let line = `${JSON.stringify(item)}: () => import(${JSON.stringify(importPath)})`;
1209
+ if (importName) {
1210
+ line += `.then(mod => mod.${importName})`;
1211
+ }
1212
+ code += `${line}, `;
1213
+ }
1214
+ }
1215
+ code += "}";
1216
+ return code;
1217
+ },
1218
+ formatImportPath(file) {
1219
+ const ext = import_node_path5.default.extname(file);
1220
+ let filename;
1221
+ if (ext === ".ts" && jsExtension) {
1222
+ filename = file.substring(0, file.length - ext.length) + ".js";
1223
+ } else if (ext === ".ts") {
1224
+ filename = file.substring(0, file.length - ext.length);
1225
+ } else {
1226
+ filename = file;
1227
+ }
1228
+ const importPath = slash(import_node_path5.default.relative(outDir, filename));
1229
+ return importPath.startsWith(".") ? importPath : `./${importPath}`;
1230
+ },
1231
+ toString() {
1232
+ return [...banner, ...this.lines].join("\n");
1233
+ }
1234
+ };
1235
+ }
1236
+ function normalizeViteGlobPath(file) {
1237
+ file = slash(file);
1238
+ if (file.startsWith("./")) return file;
1239
+ if (file.startsWith("/")) return `.${file}`;
1240
+ return `./${file}`;
1241
+ }
1242
+ function slash(path8) {
1243
+ const isExtendedLengthPath = path8.startsWith("\\\\?\\");
1244
+ if (isExtendedLengthPath) {
1245
+ return path8;
1246
+ }
1247
+ return path8.replaceAll("\\", "/");
1248
+ }
1249
+ function ident(code, tab = 1) {
1250
+ return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
1251
+ }
1252
+
1253
+ // src/plugins/index-file.ts
1254
+ var import_tinyglobby2 = require("tinyglobby");
1255
+ var import_crypto = require("crypto");
1256
+ init_fuma_matter();
1257
+ function indexFile(options = {}) {
1258
+ const {
1259
+ target = "default",
1260
+ addJsExtension,
1261
+ browser = true,
1262
+ dynamic = true
1263
+ } = options;
1264
+ let config;
1265
+ let dynamicCollections;
1266
+ function isDynamic(collection) {
1267
+ return collection.type === "docs" && collection.docs.dynamic || collection.type === "doc" && collection.dynamic;
1268
+ }
1269
+ return {
1270
+ name: "index-file",
1271
+ config(v) {
1272
+ config = v;
1273
+ dynamicCollections = config.collectionList.filter(isDynamic);
1274
+ },
1275
+ configureServer(server) {
1276
+ if (!server.watcher) return;
1277
+ server.watcher.on("all", async (event, file) => {
1278
+ if (dynamicCollections.length === 0) {
1279
+ if (target === "vite") return;
1280
+ if (target === "default" && event === "change") return;
1281
+ }
1282
+ const updatedCollection = config.collectionList.find(
1283
+ (collection) => collection.hasFile(file)
1284
+ );
1285
+ if (!updatedCollection) return;
1286
+ if (!isDynamic(updatedCollection)) {
1287
+ if (target === "vite") return;
1288
+ if (target === "default" && event === "change") return;
1221
1289
  }
1290
+ await this.core.emitAndWrite({
1291
+ filterPlugin: (plugin) => plugin.name === "index-file"
1292
+ });
1293
+ });
1294
+ },
1295
+ async emit() {
1296
+ const globCache = /* @__PURE__ */ new Map();
1297
+ const makeCodeGen = () => createCodegen({
1298
+ target,
1299
+ outDir: this.outDir,
1300
+ jsExtension: addJsExtension,
1301
+ globCache
1302
+ });
1303
+ async function toEmitEntry(path8, content) {
1222
1304
  return {
1223
- loader: "object",
1224
- exports: data
1305
+ path: path8,
1306
+ content: await content
1225
1307
  };
1226
1308
  }
1309
+ const out = [
1310
+ toEmitEntry(
1311
+ "server.ts",
1312
+ generateServerIndexFile(makeCodeGen(), config, this.configPath)
1313
+ )
1314
+ ];
1315
+ if (dynamic)
1316
+ out.push(
1317
+ toEmitEntry(
1318
+ "dynamic.ts",
1319
+ generateDynamicIndexFile(this.core, makeCodeGen())
1320
+ )
1321
+ );
1322
+ if (browser)
1323
+ out.push(
1324
+ toEmitEntry(
1325
+ "browser.ts",
1326
+ generateBrowserIndexFile(makeCodeGen(), config, this.configPath)
1327
+ )
1328
+ );
1329
+ return await Promise.all(out);
1227
1330
  }
1228
1331
  };
1229
1332
  }
1333
+ async function generateServerIndexFile(codegen, config, configPath) {
1334
+ codegen.lines.push(
1335
+ `import { fromConfig } from 'fumadocs-mdx/runtime/server';`,
1336
+ `import type * as Config from '${codegen.formatImportPath(configPath)}';`,
1337
+ "",
1338
+ `const create = fromConfig<typeof Config>();`
1339
+ );
1340
+ async function generateCollectionObject(collection) {
1341
+ switch (collection.type) {
1342
+ case "docs": {
1343
+ if (collection.docs.dynamic) return;
1344
+ if (collection.docs.async) {
1345
+ const [metaGlob2, headGlob, bodyGlob] = await Promise.all([
1346
+ generateMetaCollectionGlob(codegen, collection.meta, true),
1347
+ generateDocCollectionFrontmatterGlob(
1348
+ codegen,
1349
+ collection.docs,
1350
+ true
1351
+ ),
1352
+ generateDocCollectionGlob(codegen, collection.docs)
1353
+ ]);
1354
+ return `await create.docsLazy("${collection.name}", "${collection.dir}", ${metaGlob2}, ${headGlob}, ${bodyGlob})`;
1355
+ }
1356
+ const [metaGlob, docGlob] = await Promise.all([
1357
+ generateMetaCollectionGlob(codegen, collection.meta, true),
1358
+ generateDocCollectionGlob(codegen, collection.docs, true)
1359
+ ]);
1360
+ return `await create.docs("${collection.name}", "${collection.dir}", ${metaGlob}, ${docGlob})`;
1361
+ }
1362
+ case "doc":
1363
+ if (collection.dynamic) return;
1364
+ if (collection.async) {
1365
+ const [headGlob, bodyGlob] = await Promise.all([
1366
+ generateDocCollectionFrontmatterGlob(codegen, collection, true),
1367
+ generateDocCollectionGlob(codegen, collection)
1368
+ ]);
1369
+ return `await create.docLazy("${collection.name}", "${collection.dir}", ${headGlob}, ${bodyGlob})`;
1370
+ }
1371
+ return `await create.doc("${collection.name}", "${collection.dir}", ${await generateDocCollectionGlob(
1372
+ codegen,
1373
+ collection,
1374
+ true
1375
+ )})`;
1376
+ case "meta":
1377
+ return `await create.meta("${collection.name}", "${collection.dir}", ${await generateMetaCollectionGlob(
1378
+ codegen,
1379
+ collection,
1380
+ true
1381
+ )})`;
1382
+ }
1383
+ }
1384
+ await codegen.pushAsync(
1385
+ config.collectionList.map(async (collection) => {
1386
+ const obj = await generateCollectionObject(collection);
1387
+ if (!obj) return;
1388
+ return `
1389
+ export const ${collection.name} = ${obj};`;
1390
+ })
1391
+ );
1392
+ return codegen.toString();
1393
+ }
1394
+ async function generateDynamicIndexFile(core, codegen) {
1395
+ const { configPath } = core._options;
1396
+ codegen.lines.push(
1397
+ `import { fromConfigDynamic } from 'fumadocs-mdx/runtime/dynamic';`,
1398
+ `import * as Config from '${codegen.formatImportPath(configPath)}';`,
1399
+ "",
1400
+ `const create = await fromConfigDynamic(Config);`
1401
+ );
1402
+ async function generateCollectionObjectEntry(collection, file) {
1403
+ const fullPath = import_path.default.join(collection.dir, file);
1404
+ const content = await readFileWithCache(fullPath).catch(() => "");
1405
+ const parsed = fumaMatter(content);
1406
+ const data = await core.transformFrontmatter(
1407
+ {
1408
+ collection,
1409
+ filePath: fullPath,
1410
+ source: content
1411
+ },
1412
+ parsed.data
1413
+ );
1414
+ const hash = (0, import_crypto.createHash)("md5").update(content).digest("hex");
1415
+ const infoStr = [
1416
+ // make sure it's included in vercel/nft
1417
+ `absolutePath: path.resolve(${JSON.stringify(fullPath)})`
1418
+ ];
1419
+ for (const [k, v] of Object.entries({
1420
+ info: {
1421
+ fullPath,
1422
+ path: file
1423
+ },
1424
+ data,
1425
+ hash
1426
+ })) {
1427
+ infoStr.push(`${k}: ${JSON.stringify(v)}`);
1428
+ }
1429
+ return `{ ${infoStr.join(", ")} }`;
1430
+ }
1431
+ async function generateCollectionObject(parent) {
1432
+ let collection;
1433
+ if (parent.type === "doc") collection = parent;
1434
+ else if (parent.type === "docs") collection = parent.docs;
1435
+ if (!collection || !collection.dynamic) return;
1436
+ const files = await (0, import_tinyglobby2.glob)(collection.patterns, {
1437
+ cwd: collection.dir
1438
+ });
1439
+ const entries = await Promise.all(
1440
+ files.map((file) => generateCollectionObjectEntry(collection, file))
1441
+ );
1442
+ switch (parent.type) {
1443
+ case "docs": {
1444
+ const metaGlob = await generateMetaCollectionGlob(
1445
+ codegen,
1446
+ parent.meta,
1447
+ true
1448
+ );
1449
+ return `await create.docs("${parent.name}", "${parent.dir}", ${metaGlob}, ${entries.join(", ")})`;
1450
+ }
1451
+ case "doc":
1452
+ return `await create.doc("${collection.name}", "${collection.dir}", ${entries.join(", ")})`;
1453
+ }
1454
+ }
1455
+ await codegen.pushAsync(
1456
+ core.getConfig().collectionList.map(async (collection) => {
1457
+ const obj = await generateCollectionObject(collection);
1458
+ if (!obj) return;
1459
+ return `
1460
+ export const ${collection.name} = ${obj};`;
1461
+ })
1462
+ );
1463
+ return codegen.toString();
1464
+ }
1465
+ async function generateBrowserIndexFile(codegen, config, configPath) {
1466
+ codegen.lines.push(
1467
+ `import { fromConfig } from 'fumadocs-mdx/runtime/browser';`,
1468
+ `import type * as Config from '${codegen.formatImportPath(configPath)}';`,
1469
+ "",
1470
+ `const create = fromConfig<typeof Config>();`
1471
+ );
1472
+ async function generateCollectionObject(collection) {
1473
+ switch (collection.type) {
1474
+ case "docs": {
1475
+ if (collection.docs.dynamic) return;
1476
+ return generateCollectionObject(collection.docs);
1477
+ }
1478
+ case "doc":
1479
+ if (collection.dynamic) return;
1480
+ return `create.doc("${collection.name}", ${await generateDocCollectionGlob(codegen, collection)})`;
1481
+ }
1482
+ }
1483
+ codegen.lines.push("const browserCollections = {");
1484
+ await codegen.pushAsync(
1485
+ config.collectionList.map(async (collection) => {
1486
+ const obj = await generateCollectionObject(collection);
1487
+ if (!obj) return;
1488
+ return ident(`${collection.name}: ${obj},`);
1489
+ })
1490
+ );
1491
+ codegen.lines.push("};", "export default browserCollections;");
1492
+ return codegen.toString();
1493
+ }
1494
+ function generateDocCollectionFrontmatterGlob(codegen, collection, eager = false) {
1495
+ return codegen.generateGlobImport(collection.patterns, {
1496
+ query: {
1497
+ collection: collection.name,
1498
+ only: "frontmatter"
1499
+ },
1500
+ import: "frontmatter",
1501
+ base: collection.dir,
1502
+ eager
1503
+ });
1504
+ }
1505
+ function generateDocCollectionGlob(codegen, collection, eager = false) {
1506
+ return codegen.generateGlobImport(collection.patterns, {
1507
+ query: {
1508
+ collection: collection.name
1509
+ },
1510
+ base: collection.dir,
1511
+ eager
1512
+ });
1513
+ }
1514
+ function generateMetaCollectionGlob(codegen, collection, eager = false) {
1515
+ return codegen.generateGlobImport(collection.patterns, {
1516
+ query: {
1517
+ collection: collection.name
1518
+ },
1519
+ import: "default",
1520
+ base: collection.dir,
1521
+ eager
1522
+ });
1523
+ }
1230
1524
 
1231
1525
  // src/vite/index.ts
1232
1526
  var FumadocsDeps = ["fumadocs-core", "fumadocs-ui", "fumadocs-openapi"];
1233
1527
  async function mdx(config, pluginOptions = {}) {
1234
- const options = applyDefaults2(pluginOptions);
1528
+ const options = applyDefaults(pluginOptions);
1235
1529
  const core = await createViteCore(options).init({
1236
1530
  config: buildConfig(config)
1237
1531
  });
@@ -1277,26 +1571,27 @@ async function mdx(config, pluginOptions = {}) {
1277
1571
  }
1278
1572
  } catch (e) {
1279
1573
  if (e instanceof ValidationError) {
1280
- throw new Error(e.toStringFormatted());
1574
+ throw new Error(await e.toStringFormatted());
1281
1575
  }
1282
1576
  throw e;
1283
1577
  }
1284
1578
  }
1285
1579
  };
1286
1580
  }
1287
- async function postInstall(configPath = findConfigFile(), pluginOptions = {}) {
1581
+ async function postInstall(pluginOptions = {}) {
1288
1582
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_load_from_file(), load_from_file_exports));
1289
- const options = applyDefaults2(pluginOptions);
1290
- const core = await createViteCore(options).init({
1291
- config: loadConfig2(configPath, options.outDir, true)
1583
+ const core = createViteCore(applyDefaults(pluginOptions));
1584
+ await core.init({
1585
+ config: loadConfig2(core, true)
1292
1586
  });
1293
1587
  await core.emitAndWrite();
1294
1588
  }
1295
1589
  function createViteCore({
1590
+ index,
1296
1591
  configPath,
1297
- outDir,
1298
- generateIndexFile
1592
+ outDir
1299
1593
  }) {
1594
+ if (index === true) index = {};
1300
1595
  return createCore(
1301
1596
  {
1302
1597
  environment: "vite",
@@ -1304,18 +1599,19 @@ function createViteCore({
1304
1599
  outDir
1305
1600
  },
1306
1601
  [
1307
- vite({
1308
- index: generateIndexFile
1602
+ index && indexFile({
1603
+ ...index,
1604
+ target: index.target ?? "vite"
1309
1605
  })
1310
1606
  ]
1311
1607
  );
1312
1608
  }
1313
- function applyDefaults2(options) {
1609
+ function applyDefaults(options) {
1314
1610
  return {
1315
1611
  updateViteConfig: options.updateViteConfig ?? true,
1316
- generateIndexFile: options.generateIndexFile ?? true,
1317
- configPath: options.configPath ?? "source.config.ts",
1318
- outDir: options.outDir ?? ".source"
1612
+ index: options.index ?? true,
1613
+ configPath: options.configPath ?? _Defaults.configPath,
1614
+ outDir: options.outDir ?? _Defaults.outDir
1319
1615
  };
1320
1616
  }
1321
1617
  // Annotate the CommonJS export names for ESM import in node: