fumadocs-mdx 11.6.0 → 13.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 (93) hide show
  1. package/dist/bin.cjs +1728 -0
  2. package/dist/bin.d.cts +1 -0
  3. package/dist/bin.d.ts +1 -0
  4. package/dist/bin.js +16 -0
  5. package/dist/build-mdx-CCNr86q6.d.ts +53 -0
  6. package/dist/build-mdx-D-r3_eQL.d.cts +53 -0
  7. package/dist/bun/index.cjs +857 -0
  8. package/dist/bun/index.d.cts +13 -0
  9. package/dist/bun/index.d.ts +13 -0
  10. package/dist/bun/index.js +62 -0
  11. package/dist/chunk-3J3WL7WN.js +160 -0
  12. package/dist/chunk-CXA4JO4Z.js +45 -0
  13. package/dist/chunk-EELYB2XC.js +207 -0
  14. package/dist/chunk-FSZMKRVH.js +80 -0
  15. package/dist/chunk-II3H5ZVZ.js +77 -0
  16. package/dist/chunk-JVZFH6ND.js +40 -0
  17. package/dist/chunk-K5ZLPEIQ.js +207 -0
  18. package/dist/{chunk-VFALQK6O.js → chunk-KILFIBVW.js} +21 -12
  19. package/dist/chunk-NVRDCY6Z.js +30 -0
  20. package/dist/chunk-U4MQ44TS.js +53 -0
  21. package/dist/chunk-VWJKRQZR.js +19 -0
  22. package/dist/chunk-XQ5O7IPO.js +128 -0
  23. package/dist/chunk-XZY2AWJI.js +81 -0
  24. package/dist/chunk-YVCR6FUH.js +82 -0
  25. package/dist/config/index.cjs +232 -128
  26. package/dist/config/index.d.cts +4 -6
  27. package/dist/config/index.d.ts +4 -6
  28. package/dist/config/index.js +26 -19
  29. package/dist/core-B6j6Fxse.d.cts +218 -0
  30. package/dist/core-B6j6Fxse.d.ts +218 -0
  31. package/dist/index.cjs +0 -76
  32. package/dist/index.d.cts +73 -20
  33. package/dist/index.d.ts +73 -20
  34. package/dist/index.js +0 -10
  35. package/dist/load-MNG3CLET.js +7 -0
  36. package/dist/next/index.cjs +567 -314
  37. package/dist/next/index.d.cts +9 -12
  38. package/dist/next/index.d.ts +9 -12
  39. package/dist/next/index.js +238 -211
  40. package/dist/node/loader.cjs +922 -0
  41. package/dist/node/loader.d.cts +5 -0
  42. package/dist/node/loader.d.ts +5 -0
  43. package/dist/node/loader.js +33 -0
  44. package/dist/plugins/json-schema.cjs +162 -0
  45. package/dist/plugins/json-schema.d.cts +24 -0
  46. package/dist/plugins/json-schema.d.ts +24 -0
  47. package/dist/plugins/json-schema.js +78 -0
  48. package/dist/{mdx-options-CAU273O3.js → preset-ZMP6U62C.js} +1 -1
  49. package/dist/runtime/next/async.cjs +715 -0
  50. package/dist/runtime/next/async.d.cts +21 -0
  51. package/dist/runtime/next/async.d.ts +21 -0
  52. package/dist/runtime/next/async.js +89 -0
  53. package/dist/runtime/next/index.cjs +136 -0
  54. package/dist/runtime/next/index.d.cts +33 -0
  55. package/dist/runtime/next/index.d.ts +33 -0
  56. package/dist/runtime/next/index.js +11 -0
  57. package/dist/runtime/vite/browser.cjs +107 -0
  58. package/dist/runtime/vite/browser.d.cts +59 -0
  59. package/dist/runtime/vite/browser.d.ts +59 -0
  60. package/dist/runtime/vite/browser.js +11 -0
  61. package/dist/runtime/vite/server.cjs +243 -0
  62. package/dist/runtime/vite/server.d.cts +30 -0
  63. package/dist/runtime/vite/server.d.ts +30 -0
  64. package/dist/runtime/vite/server.js +111 -0
  65. package/dist/types-AGzTfBmf.d.ts +45 -0
  66. package/dist/types-DKGMoay5.d.cts +45 -0
  67. package/dist/vite/index.cjs +1185 -0
  68. package/dist/vite/index.d.cts +45 -0
  69. package/dist/vite/index.d.ts +45 -0
  70. package/dist/vite/index.js +297 -0
  71. package/dist/webpack/index.cjs +957 -0
  72. package/dist/{loader-mdx.d.cts → webpack/index.d.cts} +3 -6
  73. package/dist/{loader-mdx.d.ts → webpack/index.d.ts} +3 -6
  74. package/dist/webpack/index.js +44 -0
  75. package/loader-mdx.cjs +1 -1
  76. package/package.json +86 -29
  77. package/bin.js +0 -5
  78. package/dist/chunk-2ZOW45YZ.js +0 -63
  79. package/dist/chunk-DRVUBK5B.js +0 -39
  80. package/dist/chunk-HFLDWPJA.js +0 -62
  81. package/dist/chunk-IOENRFUX.js +0 -112
  82. package/dist/chunk-MK7EXW7O.js +0 -75
  83. package/dist/define-BaW0PQDJ.d.cts +0 -201
  84. package/dist/define-BaW0PQDJ.d.ts +0 -201
  85. package/dist/loader-mdx.cjs +0 -527
  86. package/dist/loader-mdx.js +0 -162
  87. package/dist/runtime/async.cjs +0 -269
  88. package/dist/runtime/async.d.cts +0 -18
  89. package/dist/runtime/async.d.ts +0 -18
  90. package/dist/runtime/async.js +0 -73
  91. package/dist/types-BNrQHCj5.d.cts +0 -100
  92. package/dist/types-DEduCvIT.d.ts +0 -100
  93. package/dist/watcher-IAZDSTU7.js +0 -24
package/dist/bin.cjs ADDED
@@ -0,0 +1,1728 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+
33
+ // src/loaders/config/index.ts
34
+ function findConfigFile() {
35
+ return import_node_path.default.resolve("source.config.ts");
36
+ }
37
+ var import_node_path, import_promises;
38
+ var init_config = __esm({
39
+ "src/loaders/config/index.ts"() {
40
+ "use strict";
41
+ import_node_path = __toESM(require("path"), 1);
42
+ import_promises = __toESM(require("fs/promises"), 1);
43
+ }
44
+ });
45
+
46
+ // src/loaders/mdx/preset.ts
47
+ var preset_exports = {};
48
+ __export(preset_exports, {
49
+ getDefaultMDXOptions: () => getDefaultMDXOptions
50
+ });
51
+ function pluginOption(def, options = []) {
52
+ const list = def(Array.isArray(options) ? options : []).filter(
53
+ Boolean
54
+ );
55
+ if (typeof options === "function") {
56
+ return options(list);
57
+ }
58
+ return list;
59
+ }
60
+ function getDefaultMDXOptions({
61
+ valueToExport = [],
62
+ rehypeCodeOptions,
63
+ remarkImageOptions,
64
+ remarkHeadingOptions,
65
+ remarkStructureOptions,
66
+ remarkCodeTabOptions,
67
+ remarkNpmOptions,
68
+ _withoutBundler = false,
69
+ ...mdxOptions
70
+ }) {
71
+ const remarkPlugins = pluginOption(
72
+ (v) => [
73
+ plugins.remarkGfm,
74
+ [
75
+ plugins.remarkHeading,
76
+ {
77
+ generateToc: false,
78
+ ...remarkHeadingOptions
79
+ }
80
+ ],
81
+ remarkImageOptions !== false && [
82
+ plugins.remarkImage,
83
+ {
84
+ ...remarkImageOptions,
85
+ useImport: _withoutBundler ? false : remarkImageOptions?.useImport
86
+ }
87
+ ],
88
+ "remarkCodeTab" in plugins && remarkCodeTabOptions !== false && [
89
+ plugins.remarkCodeTab,
90
+ remarkCodeTabOptions
91
+ ],
92
+ "remarkNpm" in plugins && remarkNpmOptions !== false && [plugins.remarkNpm, remarkNpmOptions],
93
+ ...v,
94
+ remarkStructureOptions !== false && [
95
+ plugins.remarkStructure,
96
+ remarkStructureOptions
97
+ ],
98
+ () => {
99
+ return (_, file) => {
100
+ file.data["mdx-export"] ??= [];
101
+ for (const name of valueToExport) {
102
+ if (name in file.data)
103
+ file.data["mdx-export"].push({ name, value: file.data[name] });
104
+ }
105
+ };
106
+ }
107
+ ],
108
+ mdxOptions.remarkPlugins
109
+ );
110
+ const rehypePlugins = pluginOption(
111
+ (v) => [
112
+ rehypeCodeOptions !== false && [plugins.rehypeCode, rehypeCodeOptions],
113
+ ...v,
114
+ plugins.rehypeToc
115
+ ],
116
+ mdxOptions.rehypePlugins
117
+ );
118
+ return {
119
+ ...mdxOptions,
120
+ outputFormat: _withoutBundler ? "function-body" : mdxOptions.outputFormat,
121
+ remarkPlugins,
122
+ rehypePlugins
123
+ };
124
+ }
125
+ var plugins;
126
+ var init_preset = __esm({
127
+ "src/loaders/mdx/preset.ts"() {
128
+ "use strict";
129
+ plugins = __toESM(require("fumadocs-core/mdx-plugins"), 1);
130
+ }
131
+ });
132
+
133
+ // src/config/build.ts
134
+ function buildConfig(config) {
135
+ const collections = /* @__PURE__ */ new Map();
136
+ let globalConfig = {};
137
+ for (const [k, v] of Object.entries(config)) {
138
+ if (!v) {
139
+ continue;
140
+ }
141
+ if (typeof v === "object" && "type" in v) {
142
+ if (v.type === "docs") {
143
+ collections.set(k, v);
144
+ continue;
145
+ }
146
+ if (v.type === "doc" || v.type === "meta") {
147
+ collections.set(k, v);
148
+ continue;
149
+ }
150
+ }
151
+ if (k === "default" && v) {
152
+ globalConfig = v;
153
+ continue;
154
+ }
155
+ throw new Error(
156
+ `Unknown export "${k}", you can only export collections from source configuration file.`
157
+ );
158
+ }
159
+ const mdxOptionsCache = /* @__PURE__ */ new Map();
160
+ return {
161
+ global: globalConfig,
162
+ collections,
163
+ async getDefaultMDXOptions(mode = "default") {
164
+ const cached = mdxOptionsCache.get(mode);
165
+ if (cached) return cached;
166
+ const input = this.global.mdxOptions;
167
+ async function uncached() {
168
+ const options = typeof input === "function" ? await input() : input;
169
+ const { getDefaultMDXOptions: getDefaultMDXOptions2 } = await Promise.resolve().then(() => (init_preset(), preset_exports));
170
+ if (options?.preset === "minimal") return options;
171
+ return getDefaultMDXOptions2({
172
+ ...options,
173
+ _withoutBundler: mode === "remote"
174
+ });
175
+ }
176
+ const result = uncached();
177
+ mdxOptionsCache.set(mode, result);
178
+ return result;
179
+ }
180
+ };
181
+ }
182
+ var init_build = __esm({
183
+ "src/config/build.ts"() {
184
+ "use strict";
185
+ }
186
+ });
187
+
188
+ // src/loaders/config/load.ts
189
+ var load_exports = {};
190
+ __export(load_exports, {
191
+ loadConfig: () => loadConfig
192
+ });
193
+ async function compileConfig(configPath, outDir) {
194
+ const { build } = await import("esbuild");
195
+ const transformed = await build({
196
+ entryPoints: [{ in: configPath, out: "source.config" }],
197
+ bundle: true,
198
+ outdir: outDir,
199
+ target: "node20",
200
+ write: true,
201
+ platform: "node",
202
+ format: "esm",
203
+ packages: "external",
204
+ outExtension: {
205
+ ".js": ".mjs"
206
+ },
207
+ allowOverwrite: true
208
+ });
209
+ if (transformed.errors.length > 0) {
210
+ throw new Error("failed to compile configuration file");
211
+ }
212
+ }
213
+ async function loadConfig(configPath, outDir, build = false) {
214
+ if (build) await compileConfig(configPath, outDir);
215
+ const url = (0, import_node_url.pathToFileURL)(path2.resolve(outDir, "source.config.mjs"));
216
+ url.searchParams.set("hash", Date.now().toString());
217
+ const config = import(url.href).then(
218
+ (loaded) => buildConfig(loaded)
219
+ );
220
+ return await config;
221
+ }
222
+ var path2, import_node_url;
223
+ var init_load = __esm({
224
+ "src/loaders/config/load.ts"() {
225
+ "use strict";
226
+ path2 = __toESM(require("path"), 1);
227
+ import_node_url = require("url");
228
+ init_build();
229
+ }
230
+ });
231
+
232
+ // src/next/file-cache.ts
233
+ function toFullPath(file) {
234
+ if (import_node_path2.default.isAbsolute(file)) {
235
+ return import_node_path2.default.relative(process.cwd(), file);
236
+ }
237
+ return file;
238
+ }
239
+ async function readFileWithCache(file) {
240
+ const fullPath = toFullPath(file);
241
+ const cached = map.get(fullPath);
242
+ if (cached) return cached;
243
+ const read = import_promises2.default.readFile(fullPath).then((s) => s.toString());
244
+ map.set(fullPath, read);
245
+ return read;
246
+ }
247
+ function removeFileCache(file) {
248
+ map.delete(toFullPath(file));
249
+ }
250
+ var import_lru_cache, import_promises2, import_node_path2, map;
251
+ var init_file_cache = __esm({
252
+ "src/next/file-cache.ts"() {
253
+ "use strict";
254
+ import_lru_cache = require("lru-cache");
255
+ import_promises2 = __toESM(require("fs/promises"), 1);
256
+ import_node_path2 = __toESM(require("path"), 1);
257
+ map = new import_lru_cache.LRUCache({
258
+ max: 100
259
+ });
260
+ }
261
+ });
262
+
263
+ // src/utils/validation.ts
264
+ async function validate(schema, data, context, errorMessage) {
265
+ if (typeof schema === "function" && !("~standard" in schema)) {
266
+ schema = schema(context);
267
+ }
268
+ if ("~standard" in schema) {
269
+ const result = await schema["~standard"].validate(
270
+ data
271
+ );
272
+ if (result.issues) {
273
+ throw new ValidationError(errorMessage, result.issues);
274
+ }
275
+ return result.value;
276
+ }
277
+ return data;
278
+ }
279
+ var import_picocolors, ValidationError;
280
+ var init_validation = __esm({
281
+ "src/utils/validation.ts"() {
282
+ "use strict";
283
+ import_picocolors = __toESM(require("picocolors"), 1);
284
+ ValidationError = class extends Error {
285
+ constructor(message, issues) {
286
+ super(
287
+ `${message}:
288
+ ${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
289
+ );
290
+ this.title = message;
291
+ this.issues = issues;
292
+ }
293
+ toStringFormatted() {
294
+ return [
295
+ import_picocolors.default.bold(`[MDX] ${this.title}:`),
296
+ ...this.issues.map(
297
+ (issue) => import_picocolors.default.redBright(
298
+ `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
299
+ )
300
+ )
301
+ ].join("\n");
302
+ }
303
+ };
304
+ }
305
+ });
306
+
307
+ // src/utils/git-timestamp.ts
308
+ async function getGitTimestamp(file) {
309
+ const cached = cache.get(file);
310
+ if (cached) return cached;
311
+ try {
312
+ const out = await (0, import_tinyexec.x)(
313
+ "git",
314
+ ["log", "-1", '--pretty="%ai"', import_node_path3.default.relative(process.cwd(), file)],
315
+ {
316
+ throwOnError: true
317
+ }
318
+ );
319
+ const time = new Date(out.stdout);
320
+ cache.set(file, time);
321
+ return time;
322
+ } catch {
323
+ return;
324
+ }
325
+ }
326
+ var import_node_path3, import_tinyexec, cache;
327
+ var init_git_timestamp = __esm({
328
+ "src/utils/git-timestamp.ts"() {
329
+ "use strict";
330
+ import_node_path3 = __toESM(require("path"), 1);
331
+ import_tinyexec = require("tinyexec");
332
+ cache = /* @__PURE__ */ new Map();
333
+ }
334
+ });
335
+
336
+ // src/utils/fuma-matter.ts
337
+ function fumaMatter(input) {
338
+ const output = { matter: "", data: {}, content: input };
339
+ const match = regex.exec(input);
340
+ if (!match) {
341
+ return output;
342
+ }
343
+ output.matter = match[0];
344
+ output.content = input.slice(match[0].length);
345
+ const loaded = (0, import_js_yaml.load)(match[1]);
346
+ output.data = loaded ?? {};
347
+ return output;
348
+ }
349
+ var import_js_yaml, regex;
350
+ var init_fuma_matter = __esm({
351
+ "src/utils/fuma-matter.ts"() {
352
+ "use strict";
353
+ import_js_yaml = require("js-yaml");
354
+ regex = /^---\r?\n(.+?)\r?\n---\r?\n/s;
355
+ }
356
+ });
357
+
358
+ // src/utils/import-formatter.ts
359
+ function getImportCode(info) {
360
+ const specifier = JSON.stringify(info.specifier);
361
+ if (info.type === "default") return `import ${info.name} from ${specifier}`;
362
+ if (info.type === "namespace")
363
+ return `import * as ${info.name} from ${specifier}`;
364
+ if (info.type === "named") {
365
+ const names = info.names.map(
366
+ (name) => Array.isArray(name) ? `${name[0]} as ${name[1]}` : name
367
+ );
368
+ return `import { ${names.join(", ")} } from ${specifier}`;
369
+ }
370
+ return `import ${specifier}`;
371
+ }
372
+ function toImportPath(file, config) {
373
+ const ext = import_node_path4.default.extname(file);
374
+ let filename;
375
+ if (ext === ".ts" && config.jsExtension) {
376
+ filename = file.substring(0, file.length - ext.length) + ".js";
377
+ } else if (ext === ".ts") {
378
+ filename = file.substring(0, file.length - ext.length);
379
+ } else {
380
+ filename = file;
381
+ }
382
+ let importPath;
383
+ if ("relativeTo" in config) {
384
+ importPath = import_node_path4.default.relative(config.relativeTo, filename);
385
+ if (!import_node_path4.default.isAbsolute(importPath) && !importPath.startsWith(".")) {
386
+ importPath = `./${importPath}`;
387
+ }
388
+ } else {
389
+ importPath = import_node_path4.default.resolve(filename);
390
+ }
391
+ return importPath.replaceAll(import_node_path4.default.sep, "/");
392
+ }
393
+ function ident(code, tab = 1) {
394
+ return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
395
+ }
396
+ var import_node_path4;
397
+ var init_import_formatter = __esm({
398
+ "src/utils/import-formatter.ts"() {
399
+ "use strict";
400
+ import_node_path4 = __toESM(require("path"), 1);
401
+ }
402
+ });
403
+
404
+ // src/utils/collections.ts
405
+ function getGlobPatterns(collection) {
406
+ if (collection.files) return collection.files;
407
+ return [`**/*.{${SupportedFormats[collection.type].join(",")}}`];
408
+ }
409
+ function isFileSupported(filePath, collection) {
410
+ return SupportedFormats[collection.type].some(
411
+ (format) => filePath.endsWith(`.${format}`)
412
+ );
413
+ }
414
+ async function getCollectionFiles(collection) {
415
+ const files = /* @__PURE__ */ new Map();
416
+ const dirs = Array.isArray(collection.dir) ? collection.dir : [collection.dir];
417
+ const patterns = getGlobPatterns(collection);
418
+ await Promise.all(
419
+ dirs.map(async (dir) => {
420
+ const result = await (0, import_tinyglobby.glob)(patterns, {
421
+ cwd: import_node_path5.default.resolve(dir)
422
+ });
423
+ for (const item of result) {
424
+ if (!isFileSupported(item, collection)) continue;
425
+ const fullPath = import_node_path5.default.join(dir, item);
426
+ files.set(fullPath, {
427
+ path: item,
428
+ fullPath
429
+ });
430
+ }
431
+ })
432
+ );
433
+ return Array.from(files.values());
434
+ }
435
+ var import_picomatch, import_tinyglobby, import_node_path5, SupportedFormats;
436
+ var init_collections = __esm({
437
+ "src/utils/collections.ts"() {
438
+ "use strict";
439
+ import_picomatch = __toESM(require("picomatch"), 1);
440
+ import_tinyglobby = require("tinyglobby");
441
+ import_node_path5 = __toESM(require("path"), 1);
442
+ SupportedFormats = {
443
+ doc: ["mdx", "md"],
444
+ meta: ["json", "yaml"]
445
+ };
446
+ }
447
+ });
448
+
449
+ // src/plugins/next.ts
450
+ function next() {
451
+ let config;
452
+ let shouldEmitOnChange = false;
453
+ return {
454
+ name: "next",
455
+ config(v) {
456
+ config = v;
457
+ shouldEmitOnChange = false;
458
+ for (const collection of config.collections.values()) {
459
+ if (collection.type === "doc" && collection.async || collection.type === "docs" && collection.docs.async) {
460
+ shouldEmitOnChange = true;
461
+ }
462
+ }
463
+ },
464
+ configureServer(server) {
465
+ if (!server.watcher) return;
466
+ server.watcher.on("all", async () => {
467
+ if (!shouldEmitOnChange) return;
468
+ await this.core.emitAndWrite({
469
+ filterPlugin: (plugin) => plugin.name === "next"
470
+ });
471
+ });
472
+ },
473
+ async emit() {
474
+ return [
475
+ {
476
+ path: "index.ts",
477
+ content: await indexFile(this.configPath, config, {
478
+ relativeTo: this.outDir
479
+ })
480
+ }
481
+ ];
482
+ }
483
+ };
484
+ }
485
+ async function indexFile(configPath, config, importPath, configHash = false) {
486
+ let asyncInit = false;
487
+ const lines = [
488
+ getImportCode({
489
+ type: "named",
490
+ names: ["_runtime"],
491
+ specifier: "fumadocs-mdx/runtime/next"
492
+ }),
493
+ getImportCode({
494
+ type: "namespace",
495
+ specifier: toImportPath(configPath, importPath),
496
+ name: "_source"
497
+ })
498
+ ];
499
+ const entries = Array.from(config.collections.entries());
500
+ async function getDocEntries(collectionName, files) {
501
+ const items = files.map(async (file, i) => {
502
+ const importId = `${collectionName}_${i}`;
503
+ const params = [`collection=${collectionName}`];
504
+ if (configHash) {
505
+ params.push(`hash=${configHash}`);
506
+ }
507
+ lines.unshift(
508
+ getImportCode({
509
+ type: "namespace",
510
+ name: importId,
511
+ specifier: `${toImportPath(file.fullPath, importPath)}?${params.join("&")}`
512
+ })
513
+ );
514
+ return `{ info: ${JSON.stringify(file)}, data: ${importId} }`;
515
+ });
516
+ return Promise.all(items);
517
+ }
518
+ async function getMetaEntries(collection, files) {
519
+ const items = files.map(async (file) => {
520
+ const source = await readFileWithCache(file.fullPath).catch(() => "");
521
+ let data = source.length === 0 ? {} : parseMetaEntry(file.fullPath, source);
522
+ if (collection?.schema) {
523
+ data = await validate(
524
+ collection.schema,
525
+ data,
526
+ {
527
+ source,
528
+ path: file.fullPath
529
+ },
530
+ `invalid data in ${file.fullPath}`
531
+ );
532
+ }
533
+ return JSON.stringify({
534
+ info: file,
535
+ data
536
+ });
537
+ });
538
+ return Promise.all(items);
539
+ }
540
+ async function getAsyncEntries(collection, files) {
541
+ if (!asyncInit) {
542
+ lines.unshift(
543
+ getImportCode({
544
+ type: "named",
545
+ specifier: "fumadocs-mdx/runtime/async",
546
+ names: ["_runtimeAsync", "buildConfig"]
547
+ }),
548
+ "const _sourceConfig = buildConfig(_source)",
549
+ getImportCode({
550
+ type: "default",
551
+ name: "path",
552
+ specifier: "node:path"
553
+ })
554
+ );
555
+ asyncInit = true;
556
+ }
557
+ const entries2 = files.map(async (file) => {
558
+ const content = await readFileWithCache(file.fullPath).catch(() => "");
559
+ const parsed = fumaMatter(content);
560
+ let data = parsed.data;
561
+ if (collection.schema) {
562
+ data = await validate(
563
+ collection.schema,
564
+ parsed.data,
565
+ { path: file.fullPath, source: parsed.content },
566
+ `invalid frontmatter in ${file.fullPath}`
567
+ );
568
+ }
569
+ let lastModified;
570
+ if (config.global?.lastModifiedTime === "git") {
571
+ lastModified = await getGitTimestamp(file.fullPath);
572
+ }
573
+ const hash = (0, import_node_crypto.createHash)("md5").update(content).digest("hex");
574
+ const infoStr = [];
575
+ for (const [k, v] of Object.entries({ ...file, hash })) {
576
+ infoStr.push(`${k}: ${JSON.stringify(v)}`);
577
+ }
578
+ infoStr.push(
579
+ `absolutePath: path.resolve(${JSON.stringify(file.fullPath)})`
580
+ );
581
+ return `{ info: { ${infoStr.join(", ")} }, lastModified: ${JSON.stringify(lastModified)}, data: ${JSON.stringify(data)} }`;
582
+ });
583
+ return Promise.all(entries2);
584
+ }
585
+ const declares = entries.map(async ([k, collection]) => {
586
+ if (collection.type === "docs") {
587
+ const docs = await getCollectionFiles(collection.docs);
588
+ const metas = await getCollectionFiles(collection.meta);
589
+ const metaEntries = (await getMetaEntries(collection.meta, metas)).join(
590
+ ", "
591
+ );
592
+ if (collection.docs.async) {
593
+ const docsEntries2 = (await getAsyncEntries(collection.docs, docs)).join(
594
+ ", "
595
+ );
596
+ return `export const ${k} = _runtimeAsync.docs<typeof _source.${k}>([${docsEntries2}], [${metaEntries}], "${k}", _sourceConfig)`;
597
+ }
598
+ const docsEntries = (await getDocEntries(k, docs)).join(", ");
599
+ return `export const ${k} = _runtime.docs<typeof _source.${k}>([${docsEntries}], [${metaEntries}])`;
600
+ }
601
+ const files = await getCollectionFiles(collection);
602
+ if (collection.type === "doc" && collection.async) {
603
+ return `export const ${k} = _runtimeAsync.doc<typeof _source.${k}>([${(await getAsyncEntries(collection, files)).join(", ")}], "${k}", _sourceConfig)`;
604
+ }
605
+ return `export const ${k} = _runtime.${collection.type}<typeof _source.${k}>([${(await getDocEntries(k, files)).join(", ")}]);`;
606
+ });
607
+ const resolvedDeclares = await Promise.all(declares);
608
+ return [
609
+ `// @ts-nocheck -- skip type checking`,
610
+ ...lines,
611
+ ...resolvedDeclares
612
+ ].join("\n");
613
+ }
614
+ function parseMetaEntry(file, content) {
615
+ const extname4 = path7.extname(file);
616
+ try {
617
+ if (extname4 === ".json") return JSON.parse(content);
618
+ if (extname4 === ".yaml") return (0, import_js_yaml2.load)(content);
619
+ } catch (e) {
620
+ throw new Error(`Failed to parse meta file: ${file}.`, {
621
+ cause: e
622
+ });
623
+ }
624
+ throw new Error(`Unknown meta file format: ${extname4}, in ${file}.`);
625
+ }
626
+ var path7, import_node_crypto, import_js_yaml2;
627
+ var init_next = __esm({
628
+ "src/plugins/next.ts"() {
629
+ "use strict";
630
+ path7 = __toESM(require("path"), 1);
631
+ import_node_crypto = require("crypto");
632
+ init_validation();
633
+ init_file_cache();
634
+ import_js_yaml2 = require("js-yaml");
635
+ init_git_timestamp();
636
+ init_fuma_matter();
637
+ init_import_formatter();
638
+ init_collections();
639
+ }
640
+ });
641
+
642
+ // src/core.ts
643
+ function createCore(options, defaultPlugins = []) {
644
+ let config;
645
+ let plugins2;
646
+ return {
647
+ _options: options,
648
+ getPluginContext() {
649
+ return {
650
+ core: this,
651
+ ...options
652
+ };
653
+ },
654
+ /**
655
+ * Convenient cache store, reset when config changes
656
+ */
657
+ cache: /* @__PURE__ */ new Map(),
658
+ async init({ config: newConfig }) {
659
+ config = await newConfig;
660
+ this.cache.clear();
661
+ plugins2 = [];
662
+ for await (const option of [
663
+ ...defaultPlugins,
664
+ ...config.global.plugins ?? []
665
+ ]) {
666
+ if (!option) continue;
667
+ if (Array.isArray(option)) plugins2.push(...option);
668
+ else plugins2.push(option);
669
+ }
670
+ for (const plugin of plugins2) {
671
+ const out = await plugin.config?.call(this.getPluginContext(), config);
672
+ if (out) config = out;
673
+ }
674
+ return this;
675
+ },
676
+ getConfig() {
677
+ return config;
678
+ },
679
+ creatConfigLoader() {
680
+ return {
681
+ getConfig() {
682
+ return config;
683
+ }
684
+ };
685
+ },
686
+ async initServer(server) {
687
+ for (const plugin of plugins2) {
688
+ await plugin.configureServer?.call(this.getPluginContext(), server);
689
+ }
690
+ },
691
+ async emitAndWrite({
692
+ filterPlugin = () => true
693
+ } = {}) {
694
+ const start2 = performance.now();
695
+ const out = await Promise.all(
696
+ plugins2.map((plugin) => {
697
+ if (!filterPlugin(plugin) || !plugin.emit) return [];
698
+ return plugin.emit.call(this.getPluginContext());
699
+ })
700
+ );
701
+ await Promise.all(
702
+ out.flat().map(async (entry) => {
703
+ const file = import_node_path6.default.join(options.outDir, entry.path);
704
+ await import_promises3.default.mkdir(import_node_path6.default.dirname(file), { recursive: true });
705
+ await import_promises3.default.writeFile(file, entry.content);
706
+ })
707
+ );
708
+ console.log(`[MDX] generated files in ${performance.now() - start2}ms`);
709
+ }
710
+ };
711
+ }
712
+ var import_node_path6, import_promises3;
713
+ var init_core = __esm({
714
+ "src/core.ts"() {
715
+ "use strict";
716
+ import_node_path6 = __toESM(require("path"), 1);
717
+ import_promises3 = __toESM(require("fs/promises"), 1);
718
+ }
719
+ });
720
+
721
+ // src/next/index.ts
722
+ var next_exports = {};
723
+ __export(next_exports, {
724
+ createMDX: () => createMDX,
725
+ postInstall: () => postInstall
726
+ });
727
+ function createMDX(createOptions = {}) {
728
+ const options = applyDefaults(createOptions);
729
+ const isDev = process.env.NODE_ENV === "development";
730
+ if (process.env._FUMADOCS_MDX !== "1") {
731
+ process.env._FUMADOCS_MDX = "1";
732
+ void init(isDev, options);
733
+ }
734
+ return (nextConfig = {}) => {
735
+ const mdxLoaderOptions = {
736
+ ...options,
737
+ isDev
738
+ };
739
+ const turbopack = {
740
+ ...nextConfig.turbopack,
741
+ rules: {
742
+ ...nextConfig.turbopack?.rules,
743
+ "*.{md,mdx}": {
744
+ loaders: [
745
+ {
746
+ loader: "fumadocs-mdx/loader-mdx",
747
+ options: mdxLoaderOptions
748
+ }
749
+ ],
750
+ as: "*.js"
751
+ }
752
+ }
753
+ };
754
+ return {
755
+ ...nextConfig,
756
+ turbopack,
757
+ pageExtensions: nextConfig.pageExtensions ?? defaultPageExtensions,
758
+ webpack: (config, options2) => {
759
+ config.resolve ||= {};
760
+ config.module ||= {};
761
+ config.module.rules ||= [];
762
+ config.module.rules.push({
763
+ test: /\.mdx?$/,
764
+ use: [
765
+ options2.defaultLoaders.babel,
766
+ {
767
+ loader: "fumadocs-mdx/loader-mdx",
768
+ options: mdxLoaderOptions
769
+ }
770
+ ]
771
+ });
772
+ config.plugins ||= [];
773
+ return nextConfig.webpack?.(config, options2) ?? config;
774
+ }
775
+ };
776
+ };
777
+ }
778
+ async function init(dev, options) {
779
+ const core = createNextCore(options);
780
+ async function initOrReload() {
781
+ await core.init({
782
+ config: loadConfig(options.configPath, options.outDir, true)
783
+ });
784
+ await core.emitAndWrite();
785
+ }
786
+ async function devServer() {
787
+ const { FSWatcher } = await import("chokidar");
788
+ const watcher = new FSWatcher({
789
+ ignoreInitial: true,
790
+ persistent: true,
791
+ ignored: [options.outDir]
792
+ });
793
+ watcher.add(options.configPath);
794
+ for (const collection of core.getConfig().collections.values()) {
795
+ if (collection.type === "docs") {
796
+ watcher.add(collection.docs.dir);
797
+ watcher.add(collection.meta.dir);
798
+ } else {
799
+ watcher.add(collection.dir);
800
+ }
801
+ }
802
+ watcher.on("ready", () => {
803
+ console.log("[MDX] started dev server");
804
+ });
805
+ watcher.on("all", async (event, file) => {
806
+ const absolutePath = path9.resolve(file);
807
+ if (event === "change") removeFileCache(absolutePath);
808
+ if (absolutePath === path9.resolve(options.configPath)) {
809
+ watcher.removeAllListeners();
810
+ await watcher.close();
811
+ await initOrReload();
812
+ console.log("[MDX] restarting dev server");
813
+ await devServer();
814
+ }
815
+ });
816
+ process.on("exit", () => {
817
+ if (watcher.closed) return;
818
+ console.log("[MDX] closing dev server");
819
+ void watcher.close();
820
+ });
821
+ await core.initServer({ watcher });
822
+ }
823
+ await initOrReload();
824
+ if (dev) {
825
+ await devServer();
826
+ }
827
+ }
828
+ async function postInstall(configPath = findConfigFile(), outDir = ".source") {
829
+ const core = await createNextCore({
830
+ outDir,
831
+ configPath
832
+ }).init({
833
+ config: loadConfig(configPath, outDir, true)
834
+ });
835
+ await core.emitAndWrite();
836
+ }
837
+ function applyDefaults(options) {
838
+ return {
839
+ outDir: options.outDir ?? ".source",
840
+ configPath: options.configPath ?? findConfigFile()
841
+ };
842
+ }
843
+ function createNextCore({
844
+ outDir,
845
+ configPath
846
+ }) {
847
+ const core = createCore(
848
+ {
849
+ environment: "next",
850
+ outDir,
851
+ configPath
852
+ },
853
+ [next()]
854
+ );
855
+ return {
856
+ ...core,
857
+ async emitAndWrite(...args) {
858
+ try {
859
+ await core.emitAndWrite(...args);
860
+ } catch (err) {
861
+ if (err instanceof ValidationError) {
862
+ console.error(err.toStringFormatted());
863
+ } else {
864
+ console.error(err);
865
+ }
866
+ }
867
+ }
868
+ };
869
+ }
870
+ var path9, defaultPageExtensions;
871
+ var init_next2 = __esm({
872
+ "src/next/index.ts"() {
873
+ "use strict";
874
+ init_config();
875
+ path9 = __toESM(require("path"), 1);
876
+ init_load();
877
+ init_file_cache();
878
+ init_validation();
879
+ init_next();
880
+ init_core();
881
+ defaultPageExtensions = ["mdx", "md", "jsx", "js", "tsx", "ts"];
882
+ }
883
+ });
884
+
885
+ // src/loaders/mdx/remark-unravel.ts
886
+ function remarkMarkAndUnravel() {
887
+ return (tree) => {
888
+ (0, import_unist_util_visit.visit)(tree, function(node, index, parent) {
889
+ let offset = -1;
890
+ let all = true;
891
+ let oneOrMore = false;
892
+ if (parent && typeof index === "number" && node.type === "paragraph") {
893
+ const children = node.children;
894
+ while (++offset < children.length) {
895
+ const child = children[offset];
896
+ if (child.type === "mdxJsxTextElement" || child.type === "mdxTextExpression") {
897
+ oneOrMore = true;
898
+ } else if (child.type === "text" && child.value.trim().length === 0) {
899
+ } else {
900
+ all = false;
901
+ break;
902
+ }
903
+ }
904
+ if (all && oneOrMore) {
905
+ offset = -1;
906
+ const newChildren = [];
907
+ while (++offset < children.length) {
908
+ const child = children[offset];
909
+ if (child.type === "mdxJsxTextElement") {
910
+ child.type = "mdxJsxFlowElement";
911
+ }
912
+ if (child.type === "mdxTextExpression") {
913
+ child.type = "mdxFlowExpression";
914
+ }
915
+ if (child.type === "text" && /^[\t\r\n ]+$/.test(String(child.value))) {
916
+ } else {
917
+ newChildren.push(child);
918
+ }
919
+ }
920
+ parent.children.splice(index, 1, ...newChildren);
921
+ return index;
922
+ }
923
+ }
924
+ });
925
+ };
926
+ }
927
+ var import_unist_util_visit;
928
+ var init_remark_unravel = __esm({
929
+ "src/loaders/mdx/remark-unravel.ts"() {
930
+ "use strict";
931
+ import_unist_util_visit = require("unist-util-visit");
932
+ }
933
+ });
934
+
935
+ // src/loaders/mdx/remark-include.ts
936
+ function isElementLike(node) {
937
+ return ElementLikeTypes.includes(node.type);
938
+ }
939
+ function parseElementAttributes(element) {
940
+ if (Array.isArray(element.attributes)) {
941
+ const attributes = {};
942
+ for (const attr of element.attributes) {
943
+ if (attr.type === "mdxJsxAttribute" && (typeof attr.value === "string" || attr.value === null)) {
944
+ attributes[attr.name] = attr.value;
945
+ }
946
+ }
947
+ return attributes;
948
+ }
949
+ return element.attributes ?? {};
950
+ }
951
+ function flattenNode(node) {
952
+ if ("children" in node)
953
+ return node.children.map((child) => flattenNode(child)).join("");
954
+ if ("value" in node) return node.value;
955
+ return "";
956
+ }
957
+ function parseSpecifier(specifier) {
958
+ const idx = specifier.lastIndexOf("#");
959
+ if (idx === -1) return { file: specifier };
960
+ return {
961
+ file: specifier.slice(0, idx),
962
+ section: specifier.slice(idx + 1)
963
+ };
964
+ }
965
+ function extractSection(root, section) {
966
+ let nodes;
967
+ let capturingHeadingContent = false;
968
+ (0, import_unist_util_visit2.visit)(root, (node) => {
969
+ if (node.type === "heading") {
970
+ if (capturingHeadingContent) {
971
+ return false;
972
+ }
973
+ if (node.data?.hProperties?.id === section) {
974
+ capturingHeadingContent = true;
975
+ nodes = [node];
976
+ return "skip";
977
+ }
978
+ return;
979
+ }
980
+ if (capturingHeadingContent) {
981
+ nodes?.push(node);
982
+ return "skip";
983
+ }
984
+ if (isElementLike(node) && node.name === "section") {
985
+ const attributes = parseElementAttributes(node);
986
+ if (attributes.id === section) {
987
+ nodes = node.children;
988
+ return false;
989
+ }
990
+ }
991
+ });
992
+ if (nodes)
993
+ return {
994
+ type: "root",
995
+ children: nodes
996
+ };
997
+ }
998
+ function remarkInclude() {
999
+ const TagName = "include";
1000
+ const embedContent = async (file, heading, params, data) => {
1001
+ let content;
1002
+ try {
1003
+ content = (await fs4.readFile(file)).toString();
1004
+ } catch (e) {
1005
+ throw new Error(
1006
+ `failed to read file ${file}
1007
+ ${e instanceof Error ? e.message : String(e)}`,
1008
+ { cause: e }
1009
+ );
1010
+ }
1011
+ const ext = path10.extname(file);
1012
+ data._compiler?.addDependency(file);
1013
+ if (params.lang || ext !== ".md" && ext !== ".mdx") {
1014
+ const lang = params.lang ?? ext.slice(1);
1015
+ return {
1016
+ type: "code",
1017
+ lang,
1018
+ meta: params.meta,
1019
+ value: content,
1020
+ data: {}
1021
+ };
1022
+ }
1023
+ const parser = data._getProcessor ? data._getProcessor(ext === ".mdx" ? "mdx" : "md") : this;
1024
+ const parsed = fumaMatter(content);
1025
+ let mdast = parser.parse({
1026
+ path: file,
1027
+ value: parsed.content,
1028
+ data: { frontmatter: parsed.data }
1029
+ });
1030
+ const baseProcessor = (0, import_unified.unified)().use(remarkMarkAndUnravel);
1031
+ if (heading) {
1032
+ const extracted = extractSection(
1033
+ await baseProcessor.use(import_mdx_plugins.remarkHeading).run(mdast),
1034
+ heading
1035
+ );
1036
+ if (!extracted)
1037
+ throw new Error(
1038
+ `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.`
1039
+ );
1040
+ mdast = extracted;
1041
+ } else {
1042
+ mdast = await baseProcessor.run(mdast);
1043
+ }
1044
+ await update(mdast, path10.dirname(file), data);
1045
+ return mdast;
1046
+ };
1047
+ async function update(tree, directory, data) {
1048
+ const queue = [];
1049
+ (0, import_unist_util_visit2.visit)(tree, ElementLikeTypes, (_node, _, parent) => {
1050
+ const node = _node;
1051
+ if (node.name !== TagName) return;
1052
+ const specifier = flattenNode(node);
1053
+ if (specifier.length === 0) return "skip";
1054
+ const attributes = parseElementAttributes(node);
1055
+ const { file: relativePath, section } = parseSpecifier(specifier);
1056
+ const file = path10.resolve(
1057
+ "cwd" in attributes ? process.cwd() : directory,
1058
+ relativePath
1059
+ );
1060
+ queue.push(
1061
+ embedContent(file, section, attributes, data).then((replace) => {
1062
+ Object.assign(
1063
+ parent && parent.type === "paragraph" ? parent : node,
1064
+ replace
1065
+ );
1066
+ })
1067
+ );
1068
+ return "skip";
1069
+ });
1070
+ await Promise.all(queue);
1071
+ }
1072
+ return async (tree, file) => {
1073
+ await update(tree, path10.dirname(file.path), file.data);
1074
+ };
1075
+ }
1076
+ var import_unified, import_unist_util_visit2, path10, fs4, import_mdx_plugins, ElementLikeTypes;
1077
+ var init_remark_include = __esm({
1078
+ "src/loaders/mdx/remark-include.ts"() {
1079
+ "use strict";
1080
+ import_unified = require("unified");
1081
+ import_unist_util_visit2 = require("unist-util-visit");
1082
+ path10 = __toESM(require("path"), 1);
1083
+ fs4 = __toESM(require("fs/promises"), 1);
1084
+ init_fuma_matter();
1085
+ import_mdx_plugins = require("fumadocs-core/mdx-plugins");
1086
+ init_remark_unravel();
1087
+ ElementLikeTypes = [
1088
+ "mdxJsxFlowElement",
1089
+ "mdxJsxTextElement",
1090
+ "containerDirective",
1091
+ "textDirective",
1092
+ "leafDirective"
1093
+ ];
1094
+ }
1095
+ });
1096
+
1097
+ // src/loaders/mdx/remark-postprocess.ts
1098
+ function remarkPostprocess({
1099
+ _format,
1100
+ includeProcessedMarkdown = false,
1101
+ includeMDAST = false,
1102
+ valueToExport = []
1103
+ }) {
1104
+ let _stringifyProcessor;
1105
+ const getStringifyProcessor = () => {
1106
+ if (_format === "mdx") return this;
1107
+ return _stringifyProcessor ??= this().use(import_remark_mdx.default).freeze();
1108
+ };
1109
+ return (tree, file) => {
1110
+ let title;
1111
+ const urls = [];
1112
+ (0, import_unist_util_visit3.visit)(tree, ["heading", "link"], (node) => {
1113
+ if (node.type === "heading" && node.depth === 1) {
1114
+ title = flattenNode2(node);
1115
+ }
1116
+ if (node.type !== "link") return;
1117
+ urls.push({
1118
+ href: node.url
1119
+ });
1120
+ return "skip";
1121
+ });
1122
+ if (title) {
1123
+ file.data.frontmatter ??= {};
1124
+ if (!file.data.frontmatter.title) file.data.frontmatter.title = title;
1125
+ }
1126
+ file.data.extractedReferences = urls;
1127
+ if (includeProcessedMarkdown) {
1128
+ const processor = getStringifyProcessor();
1129
+ file.data._markdown = (0, import_mdast_util_to_markdown.toMarkdown)(tree, {
1130
+ ...processor.data("settings"),
1131
+ // from https://github.com/remarkjs/remark/blob/main/packages/remark-stringify/lib/index.js
1132
+ extensions: processor.data("toMarkdownExtensions") || []
1133
+ });
1134
+ }
1135
+ if (includeMDAST) {
1136
+ const options = includeMDAST === true ? {} : includeMDAST;
1137
+ file.data._mdast = JSON.stringify(
1138
+ options.removePosition ? (0, import_unist_util_remove_position.removePosition)(structuredClone(tree)) : tree
1139
+ );
1140
+ }
1141
+ for (const { name, value } of file.data["mdx-export"] ?? []) {
1142
+ tree.children.unshift(getMdastExport(name, value));
1143
+ }
1144
+ for (const name of valueToExport) {
1145
+ if (!(name in file.data)) continue;
1146
+ tree.children.unshift(getMdastExport(name, file.data[name]));
1147
+ }
1148
+ };
1149
+ }
1150
+ function getMdastExport(name, value) {
1151
+ return {
1152
+ type: "mdxjsEsm",
1153
+ value: "",
1154
+ data: {
1155
+ estree: {
1156
+ type: "Program",
1157
+ sourceType: "module",
1158
+ body: [
1159
+ {
1160
+ type: "ExportNamedDeclaration",
1161
+ attributes: [],
1162
+ specifiers: [],
1163
+ source: null,
1164
+ declaration: {
1165
+ type: "VariableDeclaration",
1166
+ kind: "let",
1167
+ declarations: [
1168
+ {
1169
+ type: "VariableDeclarator",
1170
+ id: {
1171
+ type: "Identifier",
1172
+ name
1173
+ },
1174
+ init: (0, import_estree_util_value_to_estree.valueToEstree)(value)
1175
+ }
1176
+ ]
1177
+ }
1178
+ }
1179
+ ]
1180
+ }
1181
+ }
1182
+ };
1183
+ }
1184
+ function flattenNode2(node) {
1185
+ if ("children" in node)
1186
+ return node.children.map((child) => flattenNode2(child)).join("");
1187
+ if ("value" in node) return node.value;
1188
+ return "";
1189
+ }
1190
+ var import_unist_util_visit3, import_mdast_util_to_markdown, import_estree_util_value_to_estree, import_unist_util_remove_position, import_remark_mdx;
1191
+ var init_remark_postprocess = __esm({
1192
+ "src/loaders/mdx/remark-postprocess.ts"() {
1193
+ "use strict";
1194
+ import_unist_util_visit3 = require("unist-util-visit");
1195
+ import_mdast_util_to_markdown = require("mdast-util-to-markdown");
1196
+ import_estree_util_value_to_estree = require("estree-util-value-to-estree");
1197
+ import_unist_util_remove_position = require("unist-util-remove-position");
1198
+ import_remark_mdx = __toESM(require("remark-mdx"), 1);
1199
+ }
1200
+ });
1201
+
1202
+ // src/loaders/mdx/build-mdx.ts
1203
+ async function buildMDX(cacheKey, source, options) {
1204
+ const { filePath, frontmatter, data, _compiler, ...rest } = options;
1205
+ function getProcessor(format) {
1206
+ const key = `${cacheKey}:${format}`;
1207
+ let processor = cache2.get(key);
1208
+ if (!processor) {
1209
+ processor = (0, import_mdx.createProcessor)({
1210
+ outputFormat: "program",
1211
+ ...rest,
1212
+ remarkPlugins: [
1213
+ remarkInclude,
1214
+ ...rest.remarkPlugins ?? [],
1215
+ [
1216
+ remarkPostprocess,
1217
+ {
1218
+ _format: format,
1219
+ ...options.postprocess,
1220
+ valueToExport: [
1221
+ ...options.postprocess?.valueToExport ?? [],
1222
+ "structuredData",
1223
+ "extractedReferences",
1224
+ "frontmatter",
1225
+ "lastModified",
1226
+ "_markdown",
1227
+ "_mdast"
1228
+ ]
1229
+ }
1230
+ ]
1231
+ ],
1232
+ format
1233
+ });
1234
+ cache2.set(key, processor);
1235
+ }
1236
+ return processor;
1237
+ }
1238
+ return getProcessor(
1239
+ options.format ?? (filePath.endsWith(".mdx") ? "mdx" : "md")
1240
+ ).process({
1241
+ value: source,
1242
+ path: filePath,
1243
+ data: {
1244
+ ...data,
1245
+ frontmatter,
1246
+ _compiler,
1247
+ _getProcessor: getProcessor
1248
+ }
1249
+ });
1250
+ }
1251
+ var import_mdx, cache2;
1252
+ var init_build_mdx = __esm({
1253
+ "src/loaders/mdx/build-mdx.ts"() {
1254
+ "use strict";
1255
+ import_mdx = require("@mdx-js/mdx");
1256
+ init_remark_include();
1257
+ init_remark_postprocess();
1258
+ cache2 = /* @__PURE__ */ new Map();
1259
+ }
1260
+ });
1261
+
1262
+ // src/loaders/mdx/index.ts
1263
+ function createMdxLoader(configLoader) {
1264
+ return async ({
1265
+ source: value,
1266
+ development: isDevelopment,
1267
+ query,
1268
+ compiler,
1269
+ filePath
1270
+ }) => {
1271
+ const matter = fumaMatter(value);
1272
+ const parsed = querySchema.parse(query);
1273
+ const config = await configLoader.getConfig();
1274
+ let after;
1275
+ if (!isDevelopment && config.global.experimentalBuildCache) {
1276
+ const cacheDir = config.global.experimentalBuildCache;
1277
+ const cacheKey = `${parsed.hash}_${parsed.collection ?? "global"}_${generateCacheHash(filePath)}`;
1278
+ const cached = await import_promises4.default.readFile(import_node_path7.default.join(cacheDir, cacheKey)).then((content) => cacheEntry.parse(JSON.parse(content.toString()))).catch(() => null);
1279
+ if (cached && cached.hash === generateCacheHash(value)) return cached;
1280
+ after = async () => {
1281
+ await import_promises4.default.mkdir(cacheDir, { recursive: true });
1282
+ await import_promises4.default.writeFile(
1283
+ import_node_path7.default.join(cacheDir, cacheKey),
1284
+ JSON.stringify({
1285
+ ...out,
1286
+ hash: generateCacheHash(value)
1287
+ })
1288
+ );
1289
+ };
1290
+ }
1291
+ const collection = parsed.collection ? config.collections.get(parsed.collection) : void 0;
1292
+ let docCollection;
1293
+ switch (collection?.type) {
1294
+ case "doc":
1295
+ docCollection = collection;
1296
+ break;
1297
+ case "docs":
1298
+ docCollection = collection.docs;
1299
+ break;
1300
+ }
1301
+ if (docCollection?.schema) {
1302
+ matter.data = await validate(
1303
+ docCollection.schema,
1304
+ matter.data,
1305
+ {
1306
+ source: value,
1307
+ path: filePath
1308
+ },
1309
+ `invalid frontmatter in ${filePath}`
1310
+ );
1311
+ }
1312
+ if (parsed.only === "frontmatter") {
1313
+ return {
1314
+ code: `export const frontmatter = ${JSON.stringify(matter.data)}`,
1315
+ map: null
1316
+ };
1317
+ }
1318
+ const data = {};
1319
+ if (config.global.lastModifiedTime === "git") {
1320
+ data.lastModified = (await getGitTimestamp(filePath))?.getTime();
1321
+ }
1322
+ const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
1323
+ const compiled = await buildMDX(
1324
+ `${getConfigHash(config)}:${parsed.collection ?? "global"}`,
1325
+ "\n".repeat(lineOffset) + matter.content,
1326
+ {
1327
+ development: isDevelopment,
1328
+ ...docCollection?.mdxOptions ?? await config.getDefaultMDXOptions(),
1329
+ postprocess: docCollection?.postprocess,
1330
+ data,
1331
+ filePath,
1332
+ frontmatter: matter.data,
1333
+ _compiler: compiler
1334
+ }
1335
+ );
1336
+ const out = {
1337
+ code: String(compiled.value),
1338
+ map: compiled.map
1339
+ };
1340
+ await after?.();
1341
+ return out;
1342
+ };
1343
+ }
1344
+ function getConfigHash(config) {
1345
+ let hash = hashes.get(config);
1346
+ if (hash) return hash;
1347
+ hash = Date.now().toString();
1348
+ hashes.set(config, hash);
1349
+ return hash;
1350
+ }
1351
+ function generateCacheHash(input) {
1352
+ return (0, import_node_crypto2.createHash)("md5").update(input).digest("hex");
1353
+ }
1354
+ function countLines(s) {
1355
+ let num = 0;
1356
+ for (const c of s) {
1357
+ if (c === "\n") num++;
1358
+ }
1359
+ return num;
1360
+ }
1361
+ var import_zod, import_promises4, import_node_path7, import_node_crypto2, querySchema, cacheEntry, hashes;
1362
+ var init_mdx = __esm({
1363
+ "src/loaders/mdx/index.ts"() {
1364
+ "use strict";
1365
+ init_fuma_matter();
1366
+ init_validation();
1367
+ init_git_timestamp();
1368
+ init_build_mdx();
1369
+ import_zod = require("zod");
1370
+ import_promises4 = __toESM(require("fs/promises"), 1);
1371
+ import_node_path7 = __toESM(require("path"), 1);
1372
+ import_node_crypto2 = require("crypto");
1373
+ querySchema = import_zod.z.object({
1374
+ only: import_zod.z.literal(["frontmatter", "all"]).default("all"),
1375
+ collection: import_zod.z.string().optional()
1376
+ }).loose();
1377
+ cacheEntry = import_zod.z.object({
1378
+ code: import_zod.z.string(),
1379
+ map: import_zod.z.any().optional(),
1380
+ hash: import_zod.z.string().optional()
1381
+ });
1382
+ hashes = /* @__PURE__ */ new WeakMap();
1383
+ }
1384
+ });
1385
+
1386
+ // src/loaders/adapter.ts
1387
+ function toVite(loader) {
1388
+ return async function(file, query, value) {
1389
+ const result = await loader({
1390
+ filePath: file,
1391
+ query: (0, import_node_querystring.parse)(query),
1392
+ source: value,
1393
+ development: this.environment.mode === "dev",
1394
+ compiler: {
1395
+ addDependency: (file2) => {
1396
+ this.addWatchFile(file2);
1397
+ }
1398
+ }
1399
+ });
1400
+ return {
1401
+ code: result.code,
1402
+ map: result.map
1403
+ };
1404
+ };
1405
+ }
1406
+ var import_node_url2, import_promises5, import_node_querystring, import_node_path8;
1407
+ var init_adapter = __esm({
1408
+ "src/loaders/adapter.ts"() {
1409
+ "use strict";
1410
+ import_node_url2 = require("url");
1411
+ import_promises5 = __toESM(require("fs/promises"), 1);
1412
+ import_node_querystring = require("querystring");
1413
+ init_validation();
1414
+ import_node_path8 = __toESM(require("path"), 1);
1415
+ }
1416
+ });
1417
+
1418
+ // src/utils/glob-import.ts
1419
+ function generateGlobImport(patterns, options) {
1420
+ let code = "{";
1421
+ const result = (0, import_tinyglobby2.globSync)(patterns, {
1422
+ cwd: options.base
1423
+ });
1424
+ for (const item of result) {
1425
+ const fullPath = import_node_path9.default.join(options.base, item);
1426
+ const url = (0, import_node_url3.pathToFileURL)(fullPath);
1427
+ for (const [k, v] of Object.entries(options.query ?? {})) {
1428
+ url.searchParams.set(k, v);
1429
+ }
1430
+ let line = `${JSON.stringify(item)}: () => import(${JSON.stringify(url.href)})`;
1431
+ if (options.import) {
1432
+ line += `.then(mod => mod[${JSON.stringify(options.import)}])`;
1433
+ }
1434
+ code += `${line}, `;
1435
+ }
1436
+ code += "}";
1437
+ return code;
1438
+ }
1439
+ var import_tinyglobby2, import_node_path9, import_node_url3;
1440
+ var init_glob_import = __esm({
1441
+ "src/utils/glob-import.ts"() {
1442
+ "use strict";
1443
+ import_tinyglobby2 = require("tinyglobby");
1444
+ import_node_path9 = __toESM(require("path"), 1);
1445
+ import_node_url3 = require("url");
1446
+ }
1447
+ });
1448
+
1449
+ // src/plugins/vite.ts
1450
+ function vite(options) {
1451
+ let config;
1452
+ return {
1453
+ config(v) {
1454
+ config = v;
1455
+ },
1456
+ emit() {
1457
+ return [
1458
+ {
1459
+ path: "index.ts",
1460
+ content: indexFile2(this.configPath, this.outDir, config, options)
1461
+ }
1462
+ ];
1463
+ }
1464
+ };
1465
+ }
1466
+ function indexFile2(configPath, outDir, config, options) {
1467
+ const { addJsExtension = false, runtime } = options;
1468
+ const lines = [
1469
+ '/// <reference types="vite/client" />',
1470
+ `import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
1471
+ `import type * as Config from '${toImportPath(configPath, {
1472
+ relativeTo: outDir,
1473
+ jsExtension: addJsExtension
1474
+ })}';`,
1475
+ "",
1476
+ `export const create = fromConfig<typeof Config>();`
1477
+ ];
1478
+ function docs(name, collection) {
1479
+ const obj = [
1480
+ ident(`doc: ${doc(name, collection.docs)}`),
1481
+ ident(`meta: ${meta(name, collection.meta)}`)
1482
+ ].join(",\n");
1483
+ return `{
1484
+ ${obj}
1485
+ }`;
1486
+ }
1487
+ function doc(name, collection) {
1488
+ const patterns = getGlobPatterns(collection);
1489
+ const base = getGlobBase(collection);
1490
+ const docGlob = generateGlob(patterns, {
1491
+ query: {
1492
+ collection: name
1493
+ },
1494
+ base
1495
+ });
1496
+ if (collection.async) {
1497
+ const headBlob = generateGlob(patterns, {
1498
+ query: {
1499
+ only: "frontmatter",
1500
+ collection: name
1501
+ },
1502
+ import: "frontmatter",
1503
+ base
1504
+ });
1505
+ return `create.docLazy("${name}", "${base}", ${headBlob}, ${docGlob})`;
1506
+ }
1507
+ return `create.doc("${name}", "${base}", ${docGlob})`;
1508
+ }
1509
+ function meta(name, collection) {
1510
+ const patterns = getGlobPatterns(collection);
1511
+ const base = getGlobBase(collection);
1512
+ return `create.meta("${name}", "${base}", ${generateGlob(patterns, {
1513
+ import: "default",
1514
+ base,
1515
+ query: {
1516
+ collection: name
1517
+ }
1518
+ })})`;
1519
+ }
1520
+ function generateGlob(patterns, options2) {
1521
+ patterns = mapGlobPatterns(patterns);
1522
+ if (runtime === "node" || runtime === "bun") {
1523
+ return generateGlobImport(patterns, options2);
1524
+ } else {
1525
+ return `import.meta.glob(${JSON.stringify(patterns)}, ${JSON.stringify(
1526
+ {
1527
+ ...options2,
1528
+ base: import_node_path10.default.relative(outDir, options2.base)
1529
+ },
1530
+ null,
1531
+ 2
1532
+ )})`;
1533
+ }
1534
+ }
1535
+ for (const [name, collection] of config.collections.entries()) {
1536
+ let body;
1537
+ if (collection.type === "docs") {
1538
+ body = docs(name, collection);
1539
+ } else if (collection.type === "meta") {
1540
+ body = meta(name, collection);
1541
+ } else {
1542
+ body = doc(name, collection);
1543
+ }
1544
+ lines.push("");
1545
+ lines.push(`export const ${name} = ${body};`);
1546
+ }
1547
+ return lines.join("\n");
1548
+ }
1549
+ function mapGlobPatterns(patterns) {
1550
+ return patterns.map(enforceRelative);
1551
+ }
1552
+ function enforceRelative(file) {
1553
+ if (file.startsWith("./")) return file;
1554
+ if (file.startsWith("/")) return `.${file}`;
1555
+ return `./${file}`;
1556
+ }
1557
+ function getGlobBase(collection) {
1558
+ let dir = collection.dir;
1559
+ if (Array.isArray(dir)) {
1560
+ if (dir.length !== 1)
1561
+ throw new Error(
1562
+ `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
1563
+ );
1564
+ dir = dir[0];
1565
+ }
1566
+ return enforceRelative(dir);
1567
+ }
1568
+ var import_node_path10;
1569
+ var init_vite = __esm({
1570
+ "src/plugins/vite.ts"() {
1571
+ "use strict";
1572
+ init_import_formatter();
1573
+ init_collections();
1574
+ init_glob_import();
1575
+ import_node_path10 = __toESM(require("path"), 1);
1576
+ }
1577
+ });
1578
+
1579
+ // src/vite/index.ts
1580
+ var vite_exports = {};
1581
+ __export(vite_exports, {
1582
+ default: () => mdx,
1583
+ postInstall: () => postInstall2
1584
+ });
1585
+ async function mdx(config, pluginOptions = {}) {
1586
+ const options = applyDefaults2(pluginOptions);
1587
+ const core = await createViteCore(options).init({
1588
+ config: buildConfig(config)
1589
+ });
1590
+ const mdxLoader = toVite(createMdxLoader(core.creatConfigLoader()));
1591
+ async function transformMeta(path16, query, value) {
1592
+ const isJson = path16.endsWith(".json");
1593
+ const parsed = (0, import_node_querystring2.parse)(query);
1594
+ const collection = parsed.collection ? core.getConfig().collections.get(parsed.collection) : void 0;
1595
+ if (!collection) return null;
1596
+ let schema;
1597
+ switch (collection.type) {
1598
+ case "meta":
1599
+ schema = collection.schema;
1600
+ break;
1601
+ case "docs":
1602
+ schema = collection.meta.schema;
1603
+ break;
1604
+ }
1605
+ if (!schema) return null;
1606
+ let data;
1607
+ try {
1608
+ data = isJson ? JSON.parse(value) : (0, import_js_yaml3.load)(value);
1609
+ } catch {
1610
+ return null;
1611
+ }
1612
+ const out = await validate(
1613
+ schema,
1614
+ data,
1615
+ { path: path16, source: value },
1616
+ `invalid data in ${path16}`
1617
+ );
1618
+ return {
1619
+ code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
1620
+ map: null
1621
+ };
1622
+ }
1623
+ return {
1624
+ name: "fumadocs-mdx",
1625
+ // needed, otherwise other plugins will be executed before our `transform`.
1626
+ enforce: "pre",
1627
+ config(config2) {
1628
+ if (!options.updateViteConfig) return config2;
1629
+ return (0, import_vite.mergeConfig)(config2, {
1630
+ optimizeDeps: {
1631
+ exclude: FumadocsDeps
1632
+ },
1633
+ resolve: {
1634
+ noExternal: FumadocsDeps,
1635
+ dedupe: FumadocsDeps
1636
+ }
1637
+ });
1638
+ },
1639
+ async buildStart() {
1640
+ await core.emitAndWrite();
1641
+ },
1642
+ async configureServer(server) {
1643
+ await core.initServer({
1644
+ watcher: server.watcher
1645
+ });
1646
+ },
1647
+ async transform(value, id) {
1648
+ const [file, query = ""] = id.split("?");
1649
+ const ext = path15.extname(file);
1650
+ try {
1651
+ if ([".yaml", ".json"].includes(ext))
1652
+ return await transformMeta(file, query, value);
1653
+ if ([".md", ".mdx"].includes(ext))
1654
+ return await mdxLoader.call(this, file, query, value);
1655
+ } catch (e) {
1656
+ if (e instanceof ValidationError) {
1657
+ throw new Error(e.toStringFormatted());
1658
+ }
1659
+ throw e;
1660
+ }
1661
+ }
1662
+ };
1663
+ }
1664
+ async function postInstall2(configPath = findConfigFile(), pluginOptions = {}) {
1665
+ const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_load(), load_exports));
1666
+ const options = applyDefaults2(pluginOptions);
1667
+ const core = await createViteCore(options).init({
1668
+ config: loadConfig2(configPath, options.outDir, true)
1669
+ });
1670
+ await core.emitAndWrite();
1671
+ }
1672
+ function createViteCore({
1673
+ configPath,
1674
+ outDir,
1675
+ generateIndexFile
1676
+ }) {
1677
+ return createCore(
1678
+ {
1679
+ environment: "vite",
1680
+ configPath,
1681
+ outDir
1682
+ },
1683
+ [
1684
+ generateIndexFile !== false && vite(typeof generateIndexFile === "object" ? generateIndexFile : {})
1685
+ ]
1686
+ );
1687
+ }
1688
+ function applyDefaults2(options) {
1689
+ return {
1690
+ updateViteConfig: options.updateViteConfig ?? true,
1691
+ generateIndexFile: options.generateIndexFile ?? true,
1692
+ configPath: options.configPath ?? "source.config.ts",
1693
+ outDir: options.outDir ?? ".source"
1694
+ };
1695
+ }
1696
+ var import_vite, import_node_querystring2, path15, import_js_yaml3, FumadocsDeps;
1697
+ var init_vite2 = __esm({
1698
+ "src/vite/index.ts"() {
1699
+ "use strict";
1700
+ import_vite = require("vite");
1701
+ init_build();
1702
+ import_node_querystring2 = require("querystring");
1703
+ init_validation();
1704
+ path15 = __toESM(require("path"), 1);
1705
+ import_js_yaml3 = require("js-yaml");
1706
+ init_mdx();
1707
+ init_config();
1708
+ init_adapter();
1709
+ init_vite();
1710
+ init_core();
1711
+ FumadocsDeps = ["fumadocs-core", "fumadocs-ui", "fumadocs-openapi"];
1712
+ }
1713
+ });
1714
+
1715
+ // src/bin.ts
1716
+ var import_node_fs = require("fs");
1717
+ async function start() {
1718
+ const [configPath] = process.argv.slice(2);
1719
+ const isNext = (0, import_node_fs.existsSync)("next.config.js") || (0, import_node_fs.existsSync)("next.config.mjs") || (0, import_node_fs.existsSync)("next.config.ts");
1720
+ if (isNext) {
1721
+ const { postInstall: postInstall3 } = await Promise.resolve().then(() => (init_next2(), next_exports));
1722
+ await postInstall3(configPath);
1723
+ } else {
1724
+ const { postInstall: postInstall3 } = await Promise.resolve().then(() => (init_vite2(), vite_exports));
1725
+ await postInstall3(configPath);
1726
+ }
1727
+ }
1728
+ void start();