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"]
@@ -226,12 +227,12 @@ 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");
231
232
  const transformed = await build({
232
- entryPoints: [{ in: configPath, out: "source.config" }],
233
+ entryPoints: [{ in: core2._options.configPath, out: "source.config" }],
233
234
  bundle: true,
234
- outdir: outDir,
235
+ outdir: core2._options.outDir,
235
236
  target: "node20",
236
237
  write: true,
237
238
  platform: "node",
@@ -246,20 +247,19 @@ async function compileConfig(configPath, outDir) {
246
247
  throw new Error("failed to compile configuration file");
247
248
  }
248
249
  }
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"));
250
+ async function loadConfig(core2, build = false) {
251
+ if (build) await compileConfig(core2);
252
+ const url = (0, import_node_url2.pathToFileURL)(core2.getCompiledConfigPath());
252
253
  url.searchParams.set("hash", Date.now().toString());
253
254
  const config = import(url.href).then(
254
255
  (loaded) => buildConfig(loaded)
255
256
  );
256
257
  return await config;
257
258
  }
258
- var path3, import_node_url2;
259
+ var import_node_url2;
259
260
  var init_load_from_file = __esm({
260
261
  "src/config/load-from-file.ts"() {
261
262
  "use strict";
262
- path3 = __toESM(require("path"), 1);
263
263
  import_node_url2 = require("url");
264
264
  init_build();
265
265
  }
@@ -278,7 +278,6 @@ var import_promises = __toESM(require("fs/promises"), 1);
278
278
  var import_node_querystring = require("querystring");
279
279
 
280
280
  // src/utils/validation.ts
281
- var import_picocolors = __toESM(require("picocolors"), 1);
282
281
  var ValidationError = class extends Error {
283
282
  constructor(message, issues) {
284
283
  super(
@@ -288,12 +287,13 @@ ${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
288
287
  this.title = message;
289
288
  this.issues = issues;
290
289
  }
291
- toStringFormatted() {
290
+ async toStringFormatted() {
291
+ const picocolors = await import("picocolors");
292
292
  return [
293
- import_picocolors.default.bold(`[MDX] ${this.title}:`),
293
+ picocolors.bold(`[MDX] ${this.title}:`),
294
294
  ...this.issues.map(
295
- (issue) => import_picocolors.default.redBright(
296
- `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
295
+ (issue) => picocolors.redBright(
296
+ `- ${picocolors.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
297
297
  )
298
298
  )
299
299
  ].join("\n");
@@ -337,7 +337,7 @@ function toWebpack(loader2) {
337
337
  }
338
338
  } catch (error) {
339
339
  if (error instanceof ValidationError) {
340
- return callback(new Error(error.toStringFormatted()));
340
+ return callback(new Error(await error.toStringFormatted()));
341
341
  }
342
342
  if (!(error instanceof Error)) throw error;
343
343
  const fpath = import_node_path.default.relative(this.context, this.resourcePath);
@@ -347,99 +347,30 @@ function toWebpack(loader2) {
347
347
  };
348
348
  }
349
349
 
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
350
  // src/loaders/config.ts
417
- var import_promises3 = __toESM(require("fs/promises"), 1);
351
+ var import_promises2 = __toESM(require("fs/promises"), 1);
418
352
  function createStandaloneConfigLoader({
419
- core,
353
+ core: core2,
420
354
  buildConfig: buildConfig2,
421
355
  mode
422
356
  }) {
423
357
  let loaded;
424
358
  async function getConfigHash() {
425
359
  if (mode === "production") return "static";
426
- const stats = await import_promises3.default.stat(core._options.configPath).catch(() => {
360
+ const stats = await import_promises2.default.stat(core2._options.configPath).catch(() => {
427
361
  throw new Error("Cannot find config file");
428
362
  });
429
363
  return stats.mtime.getTime().toString();
430
364
  }
431
365
  async function newConfig() {
432
366
  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
- )
367
+ await core2.init({
368
+ config: loadConfig2(core2, buildConfig2)
439
369
  });
440
- return core.getConfig();
370
+ return core2.getConfig();
441
371
  }
442
372
  return {
373
+ core: core2,
443
374
  async getConfig() {
444
375
  const hash = await getConfigHash();
445
376
  if (loaded && loaded.hash === hash) return loaded.config;
@@ -463,90 +394,253 @@ var metaLoaderGlob = /\.(json|yaml)(\?.+?)?$/;
463
394
  var querySchema = import_zod.z.object({
464
395
  collection: import_zod.z.string().optional()
465
396
  }).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)}`;
397
+ function createMetaLoader(configLoader, resolve = {}) {
398
+ const { json: resolveJson = "js", yaml: resolveYaml = "js" } = resolve;
399
+ function parse2(filePath, source) {
400
+ try {
401
+ if (filePath.endsWith(".json")) return JSON.parse(source);
402
+ if (filePath.endsWith(".yaml")) return (0, import_js_yaml.load)(source);
403
+ } catch (e) {
404
+ throw new Error(`invalid data in ${filePath}`, { cause: e });
473
405
  }
406
+ throw new Error("Unknown file type " + filePath);
474
407
  }
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;
408
+ function onMeta(source, { filePath, query }) {
409
+ const parsed = querySchema.safeParse(query);
410
+ if (!parsed.success || !parsed.data.collection) return null;
411
+ const collectionName = parsed.data.collection;
412
+ return async () => {
413
+ const config = await configLoader.getConfig();
414
+ const collection = config.getCollection(collectionName);
415
+ let metaCollection;
490
416
  switch (collection?.type) {
491
417
  case "meta":
492
- schema = collection.schema;
418
+ metaCollection = collection;
493
419
  break;
494
420
  case "docs":
495
- schema = collection.meta.schema;
421
+ metaCollection = collection.meta;
496
422
  break;
497
423
  }
498
- if (schema) {
499
- data = await validate(
500
- schema,
501
- data,
502
- { path: filePath, source },
503
- `invalid data in ${filePath}`
504
- );
424
+ const data = parse2(filePath, source);
425
+ if (!metaCollection) return data;
426
+ return configLoader.core.transformMeta(
427
+ {
428
+ collection: metaCollection,
429
+ filePath,
430
+ source
431
+ },
432
+ data
433
+ );
434
+ };
435
+ }
436
+ return {
437
+ test: metaLoaderGlob,
438
+ async load(input) {
439
+ const result = onMeta(await input.getSource(), input);
440
+ if (result === null) return null;
441
+ const data = await result();
442
+ if (input.filePath.endsWith(".json")) {
443
+ return {
444
+ code: resolveJson === "json" ? JSON.stringify(data) : `export default ${JSON.stringify(data)}`
445
+ };
446
+ } else {
447
+ return {
448
+ code: resolveYaml === "yaml" ? (0, import_js_yaml.dump)(data) : `export default ${JSON.stringify(data)}`
449
+ };
505
450
  }
506
- return {
507
- code: stringifyOutput(isJson, data)
508
- };
509
451
  },
510
452
  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 {
453
+ load(source, input) {
454
+ const result = onMeta(source, input);
455
+ if (result === null)
456
+ return {
457
+ loader: "object",
458
+ exports: parse2(input.filePath, source)
459
+ };
460
+ return result().then((data) => ({
520
461
  loader: "object",
521
- exports: data
522
- };
462
+ exports: { default: data }
463
+ }));
464
+ }
465
+ }
466
+ };
467
+ }
468
+
469
+ // src/core.ts
470
+ var import_node_path3 = __toESM(require("path"), 1);
471
+ var import_promises4 = __toESM(require("fs/promises"), 1);
472
+
473
+ // src/utils/codegen/cache.ts
474
+ var import_lru_cache = require("lru-cache");
475
+ var import_promises3 = __toESM(require("fs/promises"), 1);
476
+ var import_node_path2 = __toESM(require("path"), 1);
477
+ var map = new import_lru_cache.LRUCache({
478
+ max: 100
479
+ });
480
+ function toFullPath(file) {
481
+ if (import_node_path2.default.isAbsolute(file)) {
482
+ return import_node_path2.default.relative(process.cwd(), file);
483
+ }
484
+ return file;
485
+ }
486
+ function removeFileCache(file) {
487
+ map.delete(toFullPath(file));
488
+ }
489
+
490
+ // src/core.ts
491
+ async function getPlugins(pluginOptions) {
492
+ const plugins = [];
493
+ for await (const option of pluginOptions) {
494
+ if (!option) continue;
495
+ if (Array.isArray(option)) plugins.push(...await getPlugins(option));
496
+ else plugins.push(option);
497
+ }
498
+ return plugins;
499
+ }
500
+ function createCore(options, defaultPlugins = []) {
501
+ let config;
502
+ let plugins;
503
+ async function transformMetadata({
504
+ collection,
505
+ filePath,
506
+ source
507
+ }, data) {
508
+ if (collection.schema) {
509
+ data = await validate(
510
+ collection.schema,
511
+ data,
512
+ { path: filePath, source },
513
+ collection.type === "doc" ? `invalid frontmatter in ${filePath}` : `invalid data in ${filePath}`
514
+ );
515
+ }
516
+ return data;
517
+ }
518
+ const core2 = {
519
+ _options: options,
520
+ /**
521
+ * Convenient cache store, reset when config changes
522
+ */
523
+ cache: /* @__PURE__ */ new Map(),
524
+ async init({ config: newConfig }) {
525
+ config = await newConfig;
526
+ this.cache.clear();
527
+ plugins = await getPlugins([
528
+ ...defaultPlugins,
529
+ ...config.global.plugins ?? []
530
+ ]);
531
+ for (const plugin of plugins) {
532
+ const out = await plugin.config?.call(pluginContext, config);
533
+ if (out) config = out;
534
+ }
535
+ return this;
536
+ },
537
+ getConfig() {
538
+ return config;
539
+ },
540
+ /**
541
+ * The file path of compiled config file, the file may not exist (e.g. on Vite, or still compiling)
542
+ */
543
+ getCompiledConfigPath() {
544
+ return import_node_path3.default.join(options.outDir, "source.config.mjs");
545
+ },
546
+ async initServer(server) {
547
+ server.watcher?.on("all", async (event, file) => {
548
+ if (event === "change") removeFileCache(file);
549
+ });
550
+ for (const plugin of plugins) {
551
+ await plugin.configureServer?.call(pluginContext, server);
523
552
  }
553
+ },
554
+ async emit({ filterPlugin = () => true } = {}) {
555
+ return (await Promise.all(
556
+ plugins.map((plugin) => {
557
+ if (!filterPlugin(plugin) || !plugin.emit) return [];
558
+ return plugin.emit.call(pluginContext);
559
+ })
560
+ )).flat();
561
+ },
562
+ async emitAndWrite(emitOptions) {
563
+ const start = performance.now();
564
+ const out = await this.emit(emitOptions);
565
+ await Promise.all(
566
+ out.map(async (entry) => {
567
+ const file = import_node_path3.default.join(options.outDir, entry.path);
568
+ await import_promises4.default.mkdir(import_node_path3.default.dirname(file), { recursive: true });
569
+ await import_promises4.default.writeFile(file, entry.content);
570
+ })
571
+ );
572
+ console.log(`[MDX] generated files in ${performance.now() - start}ms`);
573
+ },
574
+ async transformMeta(options2, data) {
575
+ const ctx = {
576
+ ...pluginContext,
577
+ ...options2
578
+ };
579
+ data = await transformMetadata(options2, data);
580
+ for (const plugin of plugins) {
581
+ if (plugin.meta?.transform)
582
+ data = await plugin.meta.transform.call(ctx, data) ?? data;
583
+ }
584
+ return data;
585
+ },
586
+ async transformFrontmatter(options2, data) {
587
+ const ctx = {
588
+ ...pluginContext,
589
+ ...options2
590
+ };
591
+ data = await transformMetadata(options2, data);
592
+ for (const plugin of plugins) {
593
+ if (plugin.doc?.frontmatter)
594
+ data = await plugin.doc.frontmatter.call(ctx, data) ?? data;
595
+ }
596
+ return data;
597
+ },
598
+ async transformVFile(options2, file) {
599
+ const ctx = {
600
+ ...pluginContext,
601
+ ...options2
602
+ };
603
+ for (const plugin of plugins) {
604
+ if (plugin.doc?.vfile)
605
+ file = await plugin.doc.vfile.call(ctx, file) ?? file;
606
+ }
607
+ return file;
524
608
  }
525
609
  };
610
+ const pluginContext = {
611
+ core: core2,
612
+ ...options
613
+ };
614
+ return core2;
615
+ }
616
+
617
+ // src/webpack/index.ts
618
+ var core;
619
+ function getCore(options) {
620
+ return core ??= createCore({
621
+ environment: "webpack",
622
+ outDir: options.outDir,
623
+ configPath: options.configPath
624
+ });
526
625
  }
527
626
 
528
627
  // src/webpack/meta.ts
529
628
  var instance;
530
629
  async function loader(source, callback) {
531
- const { isDev, outDir, configPath } = this.getOptions();
630
+ const options = this.getOptions();
532
631
  this.cacheable(true);
533
- this.addDependency(configPath);
632
+ this.addDependency(options.compiledConfigPath);
534
633
  if (!instance) {
535
- const core = createCore({
536
- environment: "webpack",
537
- outDir,
538
- configPath
539
- });
540
634
  instance = toWebpack(
541
635
  createMetaLoader(
542
636
  createStandaloneConfigLoader({
543
- core,
637
+ core: getCore(options),
544
638
  buildConfig: false,
545
- mode: isDev ? "dev" : "production"
639
+ mode: options.isDev ? "dev" : "production"
546
640
  }),
547
641
  {
548
642
  json: "json",
549
- yaml: "yaml"
643
+ yaml: "js"
550
644
  }
551
645
  )
552
646
  );