fumadocs-mdx 13.0.8 → 14.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 (111) hide show
  1. package/dist/bin.cjs +985 -893
  2. package/dist/bin.js +3 -3
  3. package/dist/build-mdx-6UAK5FF5.js +8 -0
  4. package/dist/bun/index.cjs +613 -471
  5. package/dist/bun/index.d.cts +9 -2
  6. package/dist/bun/index.d.ts +9 -2
  7. package/dist/bun/index.js +15 -14
  8. package/dist/chunk-4JSFLXXT.js +8 -0
  9. package/dist/chunk-5OBUOALK.js +141 -0
  10. package/dist/{chunk-2E2JCOSO.js → chunk-6NISOLQ6.js} +16 -44
  11. package/dist/chunk-7UKSZSPY.js +331 -0
  12. package/dist/chunk-BEBCWQC7.js +224 -0
  13. package/dist/chunk-E5DJTSIM.js +86 -0
  14. package/dist/{chunk-K5ZLPEIQ.js → chunk-FBLMK4RS.js} +9 -6
  15. package/dist/chunk-IQGEFL2B.js +17 -0
  16. package/dist/{chunk-5FTSWCB4.js → chunk-K6HCOGOX.js} +9 -11
  17. package/dist/{chunk-QXHN25N3.js → chunk-MTTISKQJ.js} +6 -6
  18. package/dist/{chunk-3J3WL7WN.js → chunk-SLY7WXTX.js} +71 -58
  19. package/dist/chunk-TYJDYTKH.js +85 -0
  20. package/dist/chunk-WBIHDYMN.js +126 -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 +7 -1
  24. package/dist/config/index.d.ts +7 -1
  25. package/dist/config/index.js +5 -5
  26. package/dist/core-B9ZoS6sA.d.ts +341 -0
  27. package/dist/core-DTuP23zu.d.cts +341 -0
  28. package/dist/index-BD8Woo4m.d.cts +8 -0
  29. package/dist/index-CNOvhtOn.d.ts +8 -0
  30. package/dist/index.d.cts +38 -56
  31. package/dist/index.d.ts +38 -56
  32. package/dist/load-from-file-5HUQN36V.js +8 -0
  33. package/dist/next/index.cjs +763 -473
  34. package/dist/next/index.d.cts +16 -1
  35. package/dist/next/index.d.ts +16 -1
  36. package/dist/next/index.js +80 -281
  37. package/dist/node/loader.cjs +764 -627
  38. package/dist/node/loader.js +10 -11
  39. package/dist/plugins/index-file.cjs +495 -0
  40. package/dist/plugins/index-file.d.cts +14 -0
  41. package/dist/plugins/index-file.d.ts +14 -0
  42. package/dist/plugins/index-file.js +8 -0
  43. package/dist/plugins/json-schema.d.cts +9 -2
  44. package/dist/plugins/json-schema.d.ts +9 -2
  45. package/dist/plugins/last-modified.cjs +110 -0
  46. package/dist/plugins/last-modified.d.cts +37 -0
  47. package/dist/plugins/last-modified.d.ts +37 -0
  48. package/dist/plugins/last-modified.js +74 -0
  49. package/dist/runtime/browser.cjs +93 -0
  50. package/dist/runtime/browser.d.cts +53 -0
  51. package/dist/runtime/browser.d.ts +53 -0
  52. package/dist/runtime/browser.js +67 -0
  53. package/dist/runtime/dynamic.cjs +1023 -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 +79 -0
  57. package/dist/runtime/server.cjs +176 -0
  58. package/dist/runtime/server.d.cts +14 -0
  59. package/dist/runtime/server.d.ts +14 -0
  60. package/dist/runtime/server.js +8 -0
  61. package/dist/runtime/types.cjs +18 -0
  62. package/dist/runtime/types.d.cts +61 -0
  63. package/dist/runtime/types.d.ts +61 -0
  64. package/dist/runtime/types.js +0 -0
  65. package/dist/vite/index.cjs +984 -621
  66. package/dist/vite/index.d.cts +17 -22
  67. package/dist/vite/index.d.ts +17 -22
  68. package/dist/vite/index.js +32 -222
  69. package/dist/webpack/mdx.cjs +647 -514
  70. package/dist/webpack/mdx.d.cts +15 -1
  71. package/dist/webpack/mdx.d.ts +15 -1
  72. package/dist/webpack/mdx.js +12 -17
  73. package/dist/webpack/meta.cjs +360 -231
  74. package/dist/webpack/meta.d.cts +15 -1
  75. package/dist/webpack/meta.d.ts +15 -1
  76. package/dist/webpack/meta.js +13 -15
  77. package/package.json +15 -32
  78. package/dist/build-mdx-BjXOmv0b.d.cts +0 -53
  79. package/dist/build-mdx-CY5UldCO.d.ts +0 -53
  80. package/dist/chunk-2AQRQXSO.js +0 -119
  81. package/dist/chunk-CXA4JO4Z.js +0 -45
  82. package/dist/chunk-DMJ6I4C3.js +0 -76
  83. package/dist/chunk-FSZMKRVH.js +0 -80
  84. package/dist/chunk-II3H5ZVZ.js +0 -77
  85. package/dist/chunk-KILFIBVW.js +0 -75
  86. package/dist/chunk-NVRDCY6Z.js +0 -30
  87. package/dist/chunk-VUEZTR2H.js +0 -26
  88. package/dist/core-DB7TdlyC.d.cts +0 -234
  89. package/dist/core-DB7TdlyC.d.ts +0 -234
  90. package/dist/index-D7s7kCc2.d.cts +0 -7
  91. package/dist/index-D7s7kCc2.d.ts +0 -7
  92. package/dist/load-from-file-AVYOFOI7.js +0 -7
  93. package/dist/preset-ZMP6U62C.js +0 -6
  94. package/dist/runtime/next/async.cjs +0 -760
  95. package/dist/runtime/next/async.d.cts +0 -19
  96. package/dist/runtime/next/async.d.ts +0 -19
  97. package/dist/runtime/next/async.js +0 -86
  98. package/dist/runtime/next/index.cjs +0 -136
  99. package/dist/runtime/next/index.d.cts +0 -33
  100. package/dist/runtime/next/index.d.ts +0 -33
  101. package/dist/runtime/next/index.js +0 -11
  102. package/dist/runtime/vite/browser.cjs +0 -107
  103. package/dist/runtime/vite/browser.d.cts +0 -59
  104. package/dist/runtime/vite/browser.d.ts +0 -59
  105. package/dist/runtime/vite/browser.js +0 -11
  106. package/dist/runtime/vite/server.cjs +0 -243
  107. package/dist/runtime/vite/server.d.cts +0 -30
  108. package/dist/runtime/vite/server.d.ts +0 -30
  109. package/dist/runtime/vite/server.js +0 -111
  110. package/dist/types-Bnh9n7mj.d.cts +0 -45
  111. 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"]
@@ -226,8 +227,9 @@ var load_from_file_exports = {};
226
227
  __export(load_from_file_exports, {
227
228
  loadConfig: () => loadConfig
228
229
  });
229
- async function compileConfig(configPath, outDir) {
230
+ async function compileConfig(core2) {
230
231
  const { build } = await import("esbuild");
232
+ const { configPath, outDir } = core2.getOptions();
231
233
  const transformed = await build({
232
234
  entryPoints: [{ in: configPath, out: "source.config" }],
233
235
  bundle: true,
@@ -246,20 +248,19 @@ async function compileConfig(configPath, outDir) {
246
248
  throw new Error("failed to compile configuration file");
247
249
  }
248
250
  }
249
- async function loadConfig(configPath, outDir, build = false) {
250
- if (build) await compileConfig(configPath, outDir);
251
- const url = (0, import_node_url2.pathToFileURL)(path3.resolve(outDir, "source.config.mjs"));
251
+ async function loadConfig(core2, build = false) {
252
+ if (build) await compileConfig(core2);
253
+ const url = (0, import_node_url2.pathToFileURL)(core2.getCompiledConfigPath());
252
254
  url.searchParams.set("hash", Date.now().toString());
253
255
  const config = import(url.href).then(
254
256
  (loaded) => buildConfig(loaded)
255
257
  );
256
258
  return await config;
257
259
  }
258
- var path3, import_node_url2;
260
+ var import_node_url2;
259
261
  var init_load_from_file = __esm({
260
262
  "src/config/load-from-file.ts"() {
261
263
  "use strict";
262
- path3 = __toESM(require("path"), 1);
263
264
  import_node_url2 = require("url");
264
265
  init_build();
265
266
  }
@@ -278,7 +279,6 @@ var import_promises = __toESM(require("fs/promises"), 1);
278
279
  var import_node_querystring = require("querystring");
279
280
 
280
281
  // src/utils/validation.ts
281
- var import_picocolors = __toESM(require("picocolors"), 1);
282
282
  var ValidationError = class extends Error {
283
283
  constructor(message, issues) {
284
284
  super(
@@ -288,12 +288,13 @@ ${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
288
288
  this.title = message;
289
289
  this.issues = issues;
290
290
  }
291
- toStringFormatted() {
291
+ async toStringFormatted() {
292
+ const picocolors = await import("picocolors");
292
293
  return [
293
- import_picocolors.default.bold(`[MDX] ${this.title}:`),
294
+ picocolors.bold(`[MDX] ${this.title}:`),
294
295
  ...this.issues.map(
295
- (issue) => import_picocolors.default.redBright(
296
- `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
296
+ (issue) => picocolors.redBright(
297
+ `- ${picocolors.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
297
298
  )
298
299
  )
299
300
  ].join("\n");
@@ -337,7 +338,7 @@ function toWebpack(loader2) {
337
338
  }
338
339
  } catch (error) {
339
340
  if (error instanceof ValidationError) {
340
- return callback(new Error(error.toStringFormatted()));
341
+ return callback(new Error(await error.toStringFormatted()));
341
342
  }
342
343
  if (!(error instanceof Error)) throw error;
343
344
  const fpath = import_node_path.default.relative(this.context, this.resourcePath);
@@ -347,99 +348,30 @@ function toWebpack(loader2) {
347
348
  };
348
349
  }
349
350
 
350
- // src/core.ts
351
- var import_node_path2 = __toESM(require("path"), 1);
352
- var import_promises2 = __toESM(require("fs/promises"), 1);
353
- function createCore(options, defaultPlugins = []) {
354
- let config;
355
- let plugins2;
356
- return {
357
- _options: options,
358
- getPluginContext() {
359
- return {
360
- core: this,
361
- ...options
362
- };
363
- },
364
- /**
365
- * Convenient cache store, reset when config changes
366
- */
367
- cache: /* @__PURE__ */ new Map(),
368
- async init({ config: newConfig }) {
369
- config = await newConfig;
370
- this.cache.clear();
371
- plugins2 = [];
372
- for await (const option of [
373
- ...defaultPlugins,
374
- ...config.global.plugins ?? []
375
- ]) {
376
- if (!option) continue;
377
- if (Array.isArray(option)) plugins2.push(...option);
378
- else plugins2.push(option);
379
- }
380
- for (const plugin of plugins2) {
381
- const out = await plugin.config?.call(this.getPluginContext(), config);
382
- if (out) config = out;
383
- }
384
- return this;
385
- },
386
- getConfig() {
387
- return config;
388
- },
389
- async initServer(server) {
390
- for (const plugin of plugins2) {
391
- await plugin.configureServer?.call(this.getPluginContext(), server);
392
- }
393
- },
394
- async emitAndWrite({
395
- filterPlugin = () => true
396
- } = {}) {
397
- const start = performance.now();
398
- const out = await Promise.all(
399
- plugins2.map((plugin) => {
400
- if (!filterPlugin(plugin) || !plugin.emit) return [];
401
- return plugin.emit.call(this.getPluginContext());
402
- })
403
- );
404
- await Promise.all(
405
- out.flat().map(async (entry) => {
406
- const file = import_node_path2.default.join(options.outDir, entry.path);
407
- await import_promises2.default.mkdir(import_node_path2.default.dirname(file), { recursive: true });
408
- await import_promises2.default.writeFile(file, entry.content);
409
- })
410
- );
411
- console.log(`[MDX] generated files in ${performance.now() - start}ms`);
412
- }
413
- };
414
- }
415
-
416
351
  // src/loaders/config.ts
417
- var import_promises3 = __toESM(require("fs/promises"), 1);
352
+ var import_promises2 = __toESM(require("fs/promises"), 1);
418
353
  function createStandaloneConfigLoader({
419
- core,
354
+ core: core2,
420
355
  buildConfig: buildConfig2,
421
356
  mode
422
357
  }) {
423
358
  let loaded;
424
359
  async function getConfigHash() {
425
360
  if (mode === "production") return "static";
426
- const stats = await import_promises3.default.stat(core._options.configPath).catch(() => {
361
+ const stats = await import_promises2.default.stat(core2.getOptions().configPath).catch(() => {
427
362
  throw new Error("Cannot find config file");
428
363
  });
429
364
  return stats.mtime.getTime().toString();
430
365
  }
431
366
  async function newConfig() {
432
367
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_load_from_file(), load_from_file_exports));
433
- await core.init({
434
- config: loadConfig2(
435
- core._options.configPath,
436
- core._options.outDir,
437
- buildConfig2
438
- )
368
+ await core2.init({
369
+ config: loadConfig2(core2, buildConfig2)
439
370
  });
440
- return core.getConfig();
371
+ return core2.getConfig();
441
372
  }
442
373
  return {
374
+ core: core2,
443
375
  async getConfig() {
444
376
  const hash = await getConfigHash();
445
377
  if (loaded && loaded.hash === hash) return loaded.config;
@@ -463,90 +395,287 @@ var metaLoaderGlob = /\.(json|yaml)(\?.+?)?$/;
463
395
  var querySchema = import_zod.z.object({
464
396
  collection: import_zod.z.string().optional()
465
397
  }).loose();
466
- function createMetaLoader(configLoader, resolve2 = {}) {
467
- const { json: resolveJson = "js", yaml: resolveYaml = "js" } = resolve2;
468
- function stringifyOutput(isJson, data) {
469
- if (isJson) {
470
- return resolveJson === "json" ? JSON.stringify(data) : `export default ${JSON.stringify(data)}`;
471
- } else {
472
- return resolveYaml === "yaml" ? (0, import_js_yaml.dump)(data) : `export default ${JSON.stringify(data)}`;
398
+ function createMetaLoader(configLoader, resolve = {}) {
399
+ const { json: resolveJson = "js", yaml: resolveYaml = "js" } = resolve;
400
+ function parse2(filePath, source) {
401
+ try {
402
+ if (filePath.endsWith(".json")) return JSON.parse(source);
403
+ if (filePath.endsWith(".yaml")) return (0, import_js_yaml.load)(source);
404
+ } catch (e) {
405
+ throw new Error(`invalid data in ${filePath}`, { cause: e });
473
406
  }
407
+ throw new Error("Unknown file type " + filePath);
474
408
  }
475
- return {
476
- test: metaLoaderGlob,
477
- async load({ filePath, query, getSource }) {
478
- const parsed = querySchema.parse(query);
479
- const collection = parsed.collection ? (await configLoader.getConfig()).getCollection(parsed.collection) : void 0;
480
- if (!collection) return null;
481
- const isJson = filePath.endsWith(".json");
482
- const source = await getSource();
483
- let data;
484
- try {
485
- data = isJson ? JSON.parse(source) : (0, import_js_yaml.load)(source);
486
- } catch (e) {
487
- throw new Error(`invalid data in ${filePath}`, { cause: e });
488
- }
489
- let schema;
409
+ function onMeta(source, { filePath, query }) {
410
+ const parsed = querySchema.safeParse(query);
411
+ if (!parsed.success || !parsed.data.collection) return null;
412
+ const collectionName = parsed.data.collection;
413
+ return async () => {
414
+ const config = await configLoader.getConfig();
415
+ const collection = config.getCollection(collectionName);
416
+ let metaCollection;
490
417
  switch (collection?.type) {
491
418
  case "meta":
492
- schema = collection.schema;
419
+ metaCollection = collection;
493
420
  break;
494
421
  case "docs":
495
- schema = collection.meta.schema;
422
+ metaCollection = collection.meta;
496
423
  break;
497
424
  }
498
- if (schema) {
499
- data = await validate(
500
- schema,
501
- data,
502
- { path: filePath, source },
503
- `invalid data in ${filePath}`
504
- );
425
+ const data = parse2(filePath, source);
426
+ if (!metaCollection) return data;
427
+ return configLoader.core.transformMeta(
428
+ {
429
+ collection: metaCollection,
430
+ filePath,
431
+ source
432
+ },
433
+ data
434
+ );
435
+ };
436
+ }
437
+ return {
438
+ test: metaLoaderGlob,
439
+ async load(input) {
440
+ const result = onMeta(await input.getSource(), input);
441
+ if (result === null) return null;
442
+ const data = await result();
443
+ if (input.filePath.endsWith(".json")) {
444
+ return {
445
+ code: resolveJson === "json" ? JSON.stringify(data) : `export default ${JSON.stringify(data)}`
446
+ };
447
+ } else {
448
+ return {
449
+ code: resolveYaml === "yaml" ? (0, import_js_yaml.dump)(data) : `export default ${JSON.stringify(data)}`
450
+ };
505
451
  }
506
- return {
507
- code: stringifyOutput(isJson, data)
508
- };
509
452
  },
510
453
  bun: {
511
- loadSync(source, { filePath }) {
512
- const isJson = filePath.endsWith(".json");
513
- let data;
514
- try {
515
- data = isJson ? JSON.parse(source) : (0, import_js_yaml.load)(source);
516
- } catch (e) {
517
- throw new Error(`invalid data in ${filePath}`, { cause: e });
518
- }
519
- return {
454
+ load(source, input) {
455
+ const result = onMeta(source, input);
456
+ if (result === null)
457
+ return {
458
+ loader: "object",
459
+ exports: parse2(input.filePath, source)
460
+ };
461
+ return result().then((data) => ({
520
462
  loader: "object",
521
- exports: data
522
- };
463
+ exports: { default: data }
464
+ }));
523
465
  }
524
466
  }
525
467
  };
526
468
  }
527
469
 
470
+ // src/core.ts
471
+ var import_node_path3 = __toESM(require("path"), 1);
472
+ var import_promises3 = __toESM(require("fs/promises"), 1);
473
+
474
+ // src/utils/codegen.ts
475
+ var import_node_path2 = __toESM(require("path"), 1);
476
+ var import_tinyglobby = require("tinyglobby");
477
+ function ident(code, tab = 1) {
478
+ return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
479
+ }
480
+
481
+ // src/core.ts
482
+ async function getPlugins(pluginOptions) {
483
+ const plugins = [];
484
+ for await (const option of pluginOptions) {
485
+ if (!option) continue;
486
+ if (Array.isArray(option)) plugins.push(...await getPlugins(option));
487
+ else plugins.push(option);
488
+ }
489
+ return plugins;
490
+ }
491
+ function createCore(options, defaultPlugins = []) {
492
+ let config;
493
+ let plugins;
494
+ async function transformMetadata({
495
+ collection,
496
+ filePath,
497
+ source
498
+ }, data) {
499
+ if (collection.schema) {
500
+ data = await validate(
501
+ collection.schema,
502
+ data,
503
+ { path: filePath, source },
504
+ collection.type === "doc" ? `invalid frontmatter in ${filePath}` : `invalid data in ${filePath}`
505
+ );
506
+ }
507
+ return data;
508
+ }
509
+ const core2 = {
510
+ /**
511
+ * Convenient cache store, reset when config changes
512
+ */
513
+ cache: /* @__PURE__ */ new Map(),
514
+ async init({ config: newConfig }) {
515
+ config = await newConfig;
516
+ this.cache.clear();
517
+ plugins = await getPlugins([
518
+ postprocessPlugin(),
519
+ ...defaultPlugins,
520
+ ...config.global.plugins ?? []
521
+ ]);
522
+ for (const plugin of plugins) {
523
+ const out = await plugin.config?.call(pluginContext, config);
524
+ if (out) config = out;
525
+ }
526
+ },
527
+ getOptions() {
528
+ return options;
529
+ },
530
+ getConfig() {
531
+ return config;
532
+ },
533
+ /**
534
+ * The file path of compiled config file, the file may not exist (e.g. on Vite, or still compiling)
535
+ */
536
+ getCompiledConfigPath() {
537
+ return import_node_path3.default.join(options.outDir, "source.config.mjs");
538
+ },
539
+ getPlugins() {
540
+ return plugins;
541
+ },
542
+ getPluginContext() {
543
+ return pluginContext;
544
+ },
545
+ async initServer(server) {
546
+ for (const plugin of plugins) {
547
+ await plugin.configureServer?.call(pluginContext, server);
548
+ }
549
+ },
550
+ async emit({ filterPlugin = () => true } = {}) {
551
+ return (await Promise.all(
552
+ plugins.map((plugin) => {
553
+ if (!filterPlugin(plugin) || !plugin.emit) return [];
554
+ return plugin.emit.call(pluginContext);
555
+ })
556
+ )).flat();
557
+ },
558
+ async emitAndWrite(emitOptions) {
559
+ const start = performance.now();
560
+ const out = await this.emit(emitOptions);
561
+ await Promise.all(
562
+ out.map(async (entry) => {
563
+ const file = import_node_path3.default.join(options.outDir, entry.path);
564
+ await import_promises3.default.mkdir(import_node_path3.default.dirname(file), { recursive: true });
565
+ await import_promises3.default.writeFile(file, entry.content);
566
+ })
567
+ );
568
+ console.log(`[MDX] generated files in ${performance.now() - start}ms`);
569
+ },
570
+ async transformMeta(options2, data) {
571
+ const ctx = {
572
+ ...pluginContext,
573
+ ...options2
574
+ };
575
+ data = await transformMetadata(options2, data);
576
+ for (const plugin of plugins) {
577
+ if (plugin.meta?.transform)
578
+ data = await plugin.meta.transform.call(ctx, data) ?? data;
579
+ }
580
+ return data;
581
+ },
582
+ async transformFrontmatter(options2, data) {
583
+ const ctx = {
584
+ ...pluginContext,
585
+ ...options2
586
+ };
587
+ data = await transformMetadata(options2, data);
588
+ for (const plugin of plugins) {
589
+ if (plugin.doc?.frontmatter)
590
+ data = await plugin.doc.frontmatter.call(ctx, data) ?? data;
591
+ }
592
+ return data;
593
+ },
594
+ async transformVFile(options2, file) {
595
+ const ctx = {
596
+ ...pluginContext,
597
+ ...options2
598
+ };
599
+ for (const plugin of plugins) {
600
+ if (plugin.doc?.vfile)
601
+ file = await plugin.doc.vfile.call(ctx, file) ?? file;
602
+ }
603
+ return file;
604
+ }
605
+ };
606
+ const pluginContext = {
607
+ core: core2,
608
+ ...options
609
+ };
610
+ return core2;
611
+ }
612
+ function postprocessPlugin() {
613
+ const LinkReferenceTypes = `{
614
+ /**
615
+ * extracted references (e.g. hrefs, paths), useful for analyzing relationships between pages.
616
+ */
617
+ extractedReferences?: import('fumadocs-mdx').ExtractedReference[];
618
+ }`;
619
+ return {
620
+ "index-file": {
621
+ generateTypeConfig() {
622
+ const lines = [];
623
+ lines.push("{");
624
+ lines.push(" DocData: {");
625
+ for (const collection of this.core.getConfig().collectionList) {
626
+ let postprocessOptions;
627
+ switch (collection.type) {
628
+ case "doc":
629
+ postprocessOptions = collection.postprocess;
630
+ break;
631
+ case "docs":
632
+ postprocessOptions = collection.docs.postprocess;
633
+ break;
634
+ }
635
+ if (postprocessOptions?.extractLinkReferences) {
636
+ lines.push(ident(`${collection.name}: ${LinkReferenceTypes},`, 2));
637
+ }
638
+ }
639
+ lines.push(" }");
640
+ lines.push("}");
641
+ return lines.join("\n");
642
+ },
643
+ serverOptions(options) {
644
+ options.doc ??= {};
645
+ options.doc.passthroughs ??= [];
646
+ options.doc.passthroughs.push("extractedReferences");
647
+ }
648
+ }
649
+ };
650
+ }
651
+
652
+ // src/webpack/index.ts
653
+ var core;
654
+ function getCore(options) {
655
+ return core ??= createCore({
656
+ environment: "webpack",
657
+ outDir: options.outDir,
658
+ configPath: options.configPath
659
+ });
660
+ }
661
+
528
662
  // src/webpack/meta.ts
529
663
  var instance;
530
664
  async function loader(source, callback) {
531
- const { isDev, outDir, configPath } = this.getOptions();
665
+ const options = this.getOptions();
532
666
  this.cacheable(true);
533
- this.addDependency(configPath);
667
+ this.addDependency(options.compiledConfigPath);
534
668
  if (!instance) {
535
- const core = createCore({
536
- environment: "webpack",
537
- outDir,
538
- configPath
539
- });
540
669
  instance = toWebpack(
541
670
  createMetaLoader(
542
671
  createStandaloneConfigLoader({
543
- core,
672
+ core: getCore(options),
544
673
  buildConfig: false,
545
- mode: isDev ? "dev" : "production"
674
+ mode: options.isDev ? "dev" : "production"
546
675
  }),
547
676
  {
548
677
  json: "json",
549
- yaml: "yaml"
678
+ yaml: "js"
550
679
  }
551
680
  )
552
681
  );