fumadocs-mdx 11.6.5 → 11.6.6

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.
@@ -55,8 +55,32 @@ async function getConfigHash(configPath) {
55
55
  throw new Error("Cannot find config file");
56
56
  }
57
57
 
58
+ // src/utils/git-timestamp.ts
59
+ import path2 from "path";
60
+ import { x } from "tinyexec";
61
+ var cache2 = /* @__PURE__ */ new Map();
62
+ async function getGitTimestamp(file) {
63
+ const cached = cache2.get(file);
64
+ if (cached) return cached;
65
+ try {
66
+ const out = await x(
67
+ "git",
68
+ ["log", "-1", '--pretty="%ai"', path2.relative(process.cwd(), file)],
69
+ {
70
+ throwOnError: true
71
+ }
72
+ );
73
+ const time = new Date(out.stdout);
74
+ cache2.set(file, time);
75
+ return time;
76
+ } catch {
77
+ return;
78
+ }
79
+ }
80
+
58
81
  export {
59
82
  findConfigFile,
60
83
  loadConfig,
61
- getConfigHash
84
+ getConfigHash,
85
+ getGitTimestamp
62
86
  };
@@ -22,22 +22,20 @@ var ValidationError = class extends Error {
22
22
  super(message);
23
23
  this.issues = issues;
24
24
  }
25
- print() {
26
- console.error(
27
- [
28
- `[MDX] ${this.message}:`,
29
- ...this.issues.map(
30
- (issue) => picocolors.redBright(
31
- `- ${picocolors.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
32
- )
33
- )
34
- ].join("\n")
35
- );
36
- }
37
25
  toString() {
38
26
  return `${this.message}:
39
27
  ${this.issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`;
40
28
  }
29
+ toStringFormatted() {
30
+ return [
31
+ picocolors.bold(`[MDX] ${this.message}:`),
32
+ ...this.issues.map(
33
+ (issue) => picocolors.redBright(
34
+ `- ${picocolors.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
35
+ )
36
+ )
37
+ ].join("\n");
38
+ }
41
39
  };
42
40
  async function validate(schema, data, context, errorMessage) {
43
41
  if (typeof schema === "function" && !("~standard" in schema)) {
@@ -99,7 +99,7 @@ function getDefaultMDXOptions({
99
99
  (v) => [
100
100
  rehypeCodeOptions !== false && [plugins.rehypeCode, rehypeCodeOptions],
101
101
  ...v,
102
- [plugins.rehypeToc]
102
+ plugins.rehypeToc
103
103
  ],
104
104
  mdxOptions.rehypePlugins
105
105
  );
@@ -198,7 +198,7 @@ function getDefaultMDXOptions({
198
198
  (v) => [
199
199
  rehypeCodeOptions !== false && [plugins.rehypeCode, rehypeCodeOptions],
200
200
  ...v,
201
- [plugins.rehypeToc]
201
+ plugins.rehypeToc
202
202
  ],
203
203
  mdxOptions.rehypePlugins
204
204
  );
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  frontmatterSchema,
3
3
  metaSchema
4
- } from "../chunk-2ZOW45YZ.js";
4
+ } from "../chunk-OTM6WYMS.js";
5
5
  import {
6
6
  remarkInclude
7
7
  } from "../chunk-3UUEUK4M.js";
8
8
  import {
9
9
  getDefaultMDXOptions
10
- } from "../chunk-7UCWBLFI.js";
10
+ } from "../chunk-VC3Y6FLZ.js";
11
11
 
12
12
  // src/config/define.ts
13
13
  function defineCollections(options) {
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { PageData, MetaData, Source, VirtualFile } from 'fumadocs-core/source';
2
2
  import { B as BaseCollectionEntry } from './define-uoePrCQ_.cjs';
3
- import { R as Runtime } from './types-Cph8Ml_K.cjs';
3
+ import { R as Runtime } from './types-BsJd_P5O.cjs';
4
4
  import '@mdx-js/mdx';
5
5
  import 'mdx/types';
6
6
  import 'fumadocs-core/mdx-plugins';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { PageData, MetaData, Source, VirtualFile } from 'fumadocs-core/source';
2
2
  import { B as BaseCollectionEntry } from './define-uoePrCQ_.js';
3
- import { R as Runtime } from './types-BvEsyMKj.js';
3
+ import { R as Runtime } from './types-BYJBKH4G.js';
4
4
  import '@mdx-js/mdx';
5
5
  import 'mdx/types';
6
6
  import 'fumadocs-core/mdx-plugins';
@@ -138,7 +138,7 @@ function getDefaultMDXOptions({
138
138
  (v) => [
139
139
  rehypeCodeOptions !== false && [plugins.rehypeCode, rehypeCodeOptions],
140
140
  ...v,
141
- [plugins.rehypeToc]
141
+ plugins.rehypeToc
142
142
  ],
143
143
  mdxOptions.rehypePlugins
144
144
  );
@@ -332,7 +332,7 @@ function remarkInclude() {
332
332
 
333
333
  // src/utils/build-mdx.ts
334
334
  var cache2 = /* @__PURE__ */ new Map();
335
- async function buildMDX(cacheKey, source, options = {}) {
335
+ async function buildMDX(cacheKey, source, options) {
336
336
  const { filePath, frontmatter, data, ...rest } = options;
337
337
  let format = options.format;
338
338
  if (!format && filePath) {
@@ -364,30 +364,25 @@ async function buildMDX(cacheKey, source, options = {}) {
364
364
 
365
365
  // src/utils/git-timestamp.ts
366
366
  var import_node_path = __toESM(require("path"), 1);
367
- var import_node_fs = __toESM(require("fs"), 1);
368
- var import_cross_spawn = require("cross-spawn");
367
+ var import_tinyexec = require("tinyexec");
369
368
  var cache3 = /* @__PURE__ */ new Map();
370
- function getGitTimestamp(file) {
371
- const cachedTimestamp = cache3.get(file);
372
- if (cachedTimestamp) return Promise.resolve(cachedTimestamp);
373
- return new Promise((resolve3, reject) => {
374
- const cwd = import_node_path.default.dirname(file);
375
- if (!import_node_fs.default.existsSync(cwd)) {
376
- resolve3(void 0);
377
- return;
378
- }
379
- const fileName = import_node_path.default.basename(file);
380
- const child = (0, import_cross_spawn.spawn)("git", ["log", "-1", '--pretty="%ai"', fileName], {
381
- cwd
382
- });
383
- let output;
384
- child.stdout.on("data", (d) => output = new Date(String(d)));
385
- child.on("close", () => {
386
- if (output) cache3.set(file, output);
387
- resolve3(output);
388
- });
389
- child.on("error", reject);
390
- });
369
+ async function getGitTimestamp(file) {
370
+ const cached = cache3.get(file);
371
+ if (cached) return cached;
372
+ try {
373
+ const out = await (0, import_tinyexec.x)(
374
+ "git",
375
+ ["log", "-1", '--pretty="%ai"', import_node_path.default.relative(process.cwd(), file)],
376
+ {
377
+ throwOnError: true
378
+ }
379
+ );
380
+ const time = new Date(out.stdout);
381
+ cache3.set(file, time);
382
+ return time;
383
+ } catch {
384
+ return;
385
+ }
391
386
  }
392
387
 
393
388
  // src/utils/schema.ts
@@ -414,22 +409,20 @@ var ValidationError = class extends Error {
414
409
  super(message);
415
410
  this.issues = issues;
416
411
  }
417
- print() {
418
- console.error(
419
- [
420
- `[MDX] ${this.message}:`,
421
- ...this.issues.map(
422
- (issue) => import_picocolors.default.redBright(
423
- `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
424
- )
425
- )
426
- ].join("\n")
427
- );
428
- }
429
412
  toString() {
430
413
  return `${this.message}:
431
414
  ${this.issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`;
432
415
  }
416
+ toStringFormatted() {
417
+ return [
418
+ import_picocolors.default.bold(`[MDX] ${this.message}:`),
419
+ ...this.issues.map(
420
+ (issue) => import_picocolors.default.redBright(
421
+ `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
422
+ )
423
+ )
424
+ ].join("\n");
425
+ }
433
426
  };
434
427
  async function validate(schema, data, context, errorMessage) {
435
428
  if (typeof schema === "function" && !("~standard" in schema)) {
@@ -448,56 +441,48 @@ async function validate(schema, data, context, errorMessage) {
448
441
  }
449
442
 
450
443
  // src/loader-mdx.ts
451
- function parseQuery(query) {
452
- let collection;
453
- let hash;
454
- const parsed = (0, import_node_querystring.parse)(query.slice(1));
455
- if (parsed.collection && typeof parsed.collection === "string")
456
- collection = parsed.collection;
457
- if (parsed.hash && typeof parsed.hash === "string") hash = parsed.hash;
458
- return { collection, hash };
459
- }
460
444
  async function loader(source, callback) {
461
445
  this.cacheable(true);
462
446
  const context = this.context;
463
447
  const filePath = this.resourcePath;
464
- const { _ctx } = this.getOptions();
448
+ const { configPath } = this.getOptions();
465
449
  const matter2 = (0, import_gray_matter2.default)(source);
466
450
  const {
467
- hash: configHash = await getConfigHash(_ctx.configPath),
451
+ hash: configHash = await getConfigHash(configPath),
468
452
  collection: collectionId
469
- } = parseQuery(this.resourceQuery);
470
- const config = await loadConfig(_ctx.configPath, configHash);
453
+ } = (0, import_node_querystring.parse)(this.resourceQuery.slice(1));
454
+ const config = await loadConfig(configPath, configHash);
471
455
  let collection = collectionId !== void 0 ? config.collections.get(collectionId) : void 0;
472
456
  if (collection && collection.type === "docs") collection = collection.docs;
473
457
  if (collection && collection.type !== "doc") {
474
458
  collection = void 0;
475
459
  }
476
- let mdxOptions = collection?.mdxOptions;
477
- if (!mdxOptions) {
478
- const { getDefaultMDXOptions: getDefaultMDXOptions2 } = await Promise.resolve().then(() => (init_mdx_options(), mdx_options_exports));
479
- config._mdx_loader ??= {};
480
- const extendedOptions = config.global?.mdxOptions;
481
- config._mdx_loader.cachedProcessorOptions ??= typeof extendedOptions === "function" ? getDefaultMDXOptions2(await extendedOptions()) : getDefaultMDXOptions2(extendedOptions ?? {});
482
- mdxOptions = config._mdx_loader.cachedProcessorOptions;
483
- }
460
+ const mdxOptions = collection?.mdxOptions ?? await loadDefaultOptions(config);
484
461
  if (collection?.schema) {
485
- matter2.data = await validate(
486
- collection.schema,
487
- matter2.data,
488
- {
489
- source,
490
- path: filePath
491
- },
492
- `invalid frontmatter in ${filePath}`
493
- );
462
+ try {
463
+ matter2.data = await validate(
464
+ collection.schema,
465
+ matter2.data,
466
+ {
467
+ source,
468
+ path: filePath
469
+ },
470
+ `invalid frontmatter in ${filePath}`
471
+ );
472
+ } catch (e) {
473
+ if (e instanceof ValidationError) {
474
+ return callback(new Error(e.toStringFormatted()));
475
+ }
476
+ return callback(e);
477
+ }
494
478
  }
495
479
  let timestamp;
496
- if (config.global?.lastModifiedTime === "git")
480
+ if (config.global?.lastModifiedTime === "git") {
497
481
  timestamp = (await getGitTimestamp(filePath))?.getTime();
482
+ }
498
483
  try {
499
484
  const lineOffset = "\n".repeat(
500
- this.mode === "development" ? lines(source) - lines(matter2.content) : 0
485
+ this.mode === "development" ? lines(matter2.matter) : 0
501
486
  );
502
487
  const file = await buildMDX(
503
488
  `${configHash}:${collectionId ?? "global"}`,
@@ -521,6 +506,16 @@ async function loader(source, callback) {
521
506
  callback(error);
522
507
  }
523
508
  }
509
+ async function loadDefaultOptions(config) {
510
+ const input = config.global?.mdxOptions;
511
+ config._mdx_loader ??= {};
512
+ const mdxLoader = config._mdx_loader;
513
+ if (!mdxLoader.cachedOptions) {
514
+ const { getDefaultMDXOptions: getDefaultMDXOptions2 } = await Promise.resolve().then(() => (init_mdx_options(), mdx_options_exports));
515
+ mdxLoader.cachedOptions = typeof input === "function" ? getDefaultMDXOptions2(await input()) : getDefaultMDXOptions2(input ?? {});
516
+ }
517
+ return mdxLoader.cachedOptions;
518
+ }
524
519
  function lines(s) {
525
520
  let num = 0;
526
521
  for (const c of s) {
@@ -1,12 +1,7 @@
1
1
  import { LoaderContext } from 'webpack';
2
2
 
3
3
  interface Options {
4
- /**
5
- * @internal
6
- */
7
- _ctx: {
8
- configPath: string;
9
- };
4
+ configPath: string;
10
5
  }
11
6
  /**
12
7
  * Load MDX/markdown files
@@ -1,12 +1,7 @@
1
1
  import { LoaderContext } from 'webpack';
2
2
 
3
3
  interface Options {
4
- /**
5
- * @internal
6
- */
7
- _ctx: {
8
- configPath: string;
9
- };
4
+ configPath: string;
10
5
  }
11
6
  /**
12
7
  * Load MDX/markdown files
@@ -1,24 +1,26 @@
1
1
  import {
2
2
  getConfigHash,
3
+ getGitTimestamp,
3
4
  loadConfig
4
- } from "./chunk-LC4HO353.js";
5
+ } from "./chunk-GWITJLOZ.js";
5
6
  import {
7
+ ValidationError,
6
8
  validate
7
- } from "./chunk-2ZOW45YZ.js";
9
+ } from "./chunk-OTM6WYMS.js";
8
10
  import {
9
11
  remarkInclude
10
12
  } from "./chunk-3UUEUK4M.js";
11
13
  import "./chunk-DRVUBK5B.js";
12
14
 
13
15
  // src/loader-mdx.ts
14
- import * as path2 from "path";
16
+ import * as path from "path";
15
17
  import { parse } from "querystring";
16
18
  import grayMatter from "gray-matter";
17
19
 
18
20
  // src/utils/build-mdx.ts
19
21
  import { createProcessor } from "@mdx-js/mdx";
20
22
  var cache = /* @__PURE__ */ new Map();
21
- async function buildMDX(cacheKey, source, options = {}) {
23
+ async function buildMDX(cacheKey, source, options) {
22
24
  const { filePath, frontmatter, data, ...rest } = options;
23
25
  let format = options.format;
24
26
  if (!format && filePath) {
@@ -48,85 +50,49 @@ async function buildMDX(cacheKey, source, options = {}) {
48
50
  });
49
51
  }
50
52
 
51
- // src/utils/git-timestamp.ts
52
- import path from "path";
53
- import fs from "fs";
54
- import { spawn } from "cross-spawn";
55
- var cache2 = /* @__PURE__ */ new Map();
56
- function getGitTimestamp(file) {
57
- const cachedTimestamp = cache2.get(file);
58
- if (cachedTimestamp) return Promise.resolve(cachedTimestamp);
59
- return new Promise((resolve, reject) => {
60
- const cwd = path.dirname(file);
61
- if (!fs.existsSync(cwd)) {
62
- resolve(void 0);
63
- return;
64
- }
65
- const fileName = path.basename(file);
66
- const child = spawn("git", ["log", "-1", '--pretty="%ai"', fileName], {
67
- cwd
68
- });
69
- let output;
70
- child.stdout.on("data", (d) => output = new Date(String(d)));
71
- child.on("close", () => {
72
- if (output) cache2.set(file, output);
73
- resolve(output);
74
- });
75
- child.on("error", reject);
76
- });
77
- }
78
-
79
53
  // src/loader-mdx.ts
80
- function parseQuery(query) {
81
- let collection;
82
- let hash;
83
- const parsed = parse(query.slice(1));
84
- if (parsed.collection && typeof parsed.collection === "string")
85
- collection = parsed.collection;
86
- if (parsed.hash && typeof parsed.hash === "string") hash = parsed.hash;
87
- return { collection, hash };
88
- }
89
54
  async function loader(source, callback) {
90
55
  this.cacheable(true);
91
56
  const context = this.context;
92
57
  const filePath = this.resourcePath;
93
- const { _ctx } = this.getOptions();
58
+ const { configPath } = this.getOptions();
94
59
  const matter = grayMatter(source);
95
60
  const {
96
- hash: configHash = await getConfigHash(_ctx.configPath),
61
+ hash: configHash = await getConfigHash(configPath),
97
62
  collection: collectionId
98
- } = parseQuery(this.resourceQuery);
99
- const config = await loadConfig(_ctx.configPath, configHash);
63
+ } = parse(this.resourceQuery.slice(1));
64
+ const config = await loadConfig(configPath, configHash);
100
65
  let collection = collectionId !== void 0 ? config.collections.get(collectionId) : void 0;
101
66
  if (collection && collection.type === "docs") collection = collection.docs;
102
67
  if (collection && collection.type !== "doc") {
103
68
  collection = void 0;
104
69
  }
105
- let mdxOptions = collection?.mdxOptions;
106
- if (!mdxOptions) {
107
- const { getDefaultMDXOptions } = await import("./mdx-options-7J2A6BUA.js");
108
- config._mdx_loader ??= {};
109
- const extendedOptions = config.global?.mdxOptions;
110
- config._mdx_loader.cachedProcessorOptions ??= typeof extendedOptions === "function" ? getDefaultMDXOptions(await extendedOptions()) : getDefaultMDXOptions(extendedOptions ?? {});
111
- mdxOptions = config._mdx_loader.cachedProcessorOptions;
112
- }
70
+ const mdxOptions = collection?.mdxOptions ?? await loadDefaultOptions(config);
113
71
  if (collection?.schema) {
114
- matter.data = await validate(
115
- collection.schema,
116
- matter.data,
117
- {
118
- source,
119
- path: filePath
120
- },
121
- `invalid frontmatter in ${filePath}`
122
- );
72
+ try {
73
+ matter.data = await validate(
74
+ collection.schema,
75
+ matter.data,
76
+ {
77
+ source,
78
+ path: filePath
79
+ },
80
+ `invalid frontmatter in ${filePath}`
81
+ );
82
+ } catch (e) {
83
+ if (e instanceof ValidationError) {
84
+ return callback(new Error(e.toStringFormatted()));
85
+ }
86
+ return callback(e);
87
+ }
123
88
  }
124
89
  let timestamp;
125
- if (config.global?.lastModifiedTime === "git")
90
+ if (config.global?.lastModifiedTime === "git") {
126
91
  timestamp = (await getGitTimestamp(filePath))?.getTime();
92
+ }
127
93
  try {
128
94
  const lineOffset = "\n".repeat(
129
- this.mode === "development" ? lines(source) - lines(matter.content) : 0
95
+ this.mode === "development" ? lines(matter.matter) : 0
130
96
  );
131
97
  const file = await buildMDX(
132
98
  `${configHash}:${collectionId ?? "global"}`,
@@ -145,11 +111,21 @@ async function loader(source, callback) {
145
111
  callback(void 0, String(file.value), file.map ?? void 0);
146
112
  } catch (error) {
147
113
  if (!(error instanceof Error)) throw error;
148
- const fpath = path2.relative(context, filePath);
114
+ const fpath = path.relative(context, filePath);
149
115
  error.message = `${fpath}:${error.name}: ${error.message}`;
150
116
  callback(error);
151
117
  }
152
118
  }
119
+ async function loadDefaultOptions(config) {
120
+ const input = config.global?.mdxOptions;
121
+ config._mdx_loader ??= {};
122
+ const mdxLoader = config._mdx_loader;
123
+ if (!mdxLoader.cachedOptions) {
124
+ const { getDefaultMDXOptions } = await import("./mdx-options-YGL3EP3M.js");
125
+ mdxLoader.cachedOptions = typeof input === "function" ? getDefaultMDXOptions(await input()) : getDefaultMDXOptions(input ?? {});
126
+ }
127
+ return mdxLoader.cachedOptions;
128
+ }
153
129
  function lines(s) {
154
130
  let num = 0;
155
131
  for (const c of s) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getDefaultMDXOptions
3
- } from "./chunk-7UCWBLFI.js";
3
+ } from "./chunk-VC3Y6FLZ.js";
4
4
  export {
5
5
  getDefaultMDXOptions
6
6
  };
@@ -70,7 +70,7 @@ __export(next_exports, {
70
70
  module.exports = __toCommonJS(next_exports);
71
71
 
72
72
  // src/next/create.ts
73
- var import_node_path2 = __toESM(require("path"), 1);
73
+ var import_node_path3 = __toESM(require("path"), 1);
74
74
 
75
75
  // src/utils/config.ts
76
76
  var fs = __toESM(require("fs/promises"), 1);
@@ -164,11 +164,11 @@ async function getConfigHash(configPath) {
164
164
  }
165
165
 
166
166
  // src/map/index.ts
167
- var path3 = __toESM(require("path"), 1);
167
+ var path4 = __toESM(require("path"), 1);
168
168
  var fs3 = __toESM(require("fs/promises"), 1);
169
169
 
170
170
  // src/map/generate.ts
171
- var path2 = __toESM(require("path"), 1);
171
+ var path3 = __toESM(require("path"), 1);
172
172
  var fs2 = __toESM(require("fs/promises"), 1);
173
173
  var import_tinyglobby = require("tinyglobby");
174
174
 
@@ -176,8 +176,8 @@ var import_tinyglobby = require("tinyglobby");
176
176
  var import_node_path = require("path");
177
177
  var docTypes = [".mdx", ".md"];
178
178
  var metaTypes = [".json", ".yaml"];
179
- function getTypeFromPath(path6) {
180
- const ext = (0, import_node_path.extname)(path6);
179
+ function getTypeFromPath(path7) {
180
+ const ext = (0, import_node_path.extname)(path7);
181
181
  if (docTypes.includes(ext)) return "doc";
182
182
  if (metaTypes.includes(ext)) return "meta";
183
183
  }
@@ -206,22 +206,20 @@ var ValidationError = class extends Error {
206
206
  super(message);
207
207
  this.issues = issues;
208
208
  }
209
- print() {
210
- console.error(
211
- [
212
- `[MDX] ${this.message}:`,
213
- ...this.issues.map(
214
- (issue) => import_picocolors.default.redBright(
215
- `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
216
- )
217
- )
218
- ].join("\n")
219
- );
220
- }
221
209
  toString() {
222
210
  return `${this.message}:
223
211
  ${this.issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`;
224
212
  }
213
+ toStringFormatted() {
214
+ return [
215
+ import_picocolors.default.bold(`[MDX] ${this.message}:`),
216
+ ...this.issues.map(
217
+ (issue) => import_picocolors.default.redBright(
218
+ `- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
219
+ )
220
+ )
221
+ ].join("\n");
222
+ }
225
223
  };
226
224
  async function validate(schema, data, context, errorMessage) {
227
225
  if (typeof schema === "function" && !("~standard" in schema)) {
@@ -245,16 +243,16 @@ var map = new import_lru_cache.LRUCache({
245
243
  max: 200
246
244
  });
247
245
  var fileCache = {
248
- read(namespace, path6) {
249
- return map.get(`${namespace}.${path6}`);
246
+ read(namespace, path7) {
247
+ return map.get(`${namespace}.${path7}`);
250
248
  },
251
- write(namespace, path6, data) {
252
- map.set(`${namespace}.${path6}`, data);
249
+ write(namespace, path7, data) {
250
+ map.set(`${namespace}.${path7}`, data);
253
251
  },
254
- removeCache(path6) {
252
+ removeCache(path7) {
255
253
  for (const key of map.keys()) {
256
254
  const keyPath = key.slice(key.indexOf(".") + 1);
257
- if (keyPath === path6) map.delete(key);
255
+ if (keyPath === path7) map.delete(key);
258
256
  }
259
257
  }
260
258
  };
@@ -262,13 +260,38 @@ var fileCache = {
262
260
  // src/map/generate.ts
263
261
  var import_gray_matter = __toESM(require("gray-matter"), 1);
264
262
  var import_js_yaml = require("js-yaml");
263
+
264
+ // src/utils/git-timestamp.ts
265
+ var import_node_path2 = __toESM(require("path"), 1);
266
+ var import_tinyexec = require("tinyexec");
267
+ var cache2 = /* @__PURE__ */ new Map();
268
+ async function getGitTimestamp(file) {
269
+ const cached = cache2.get(file);
270
+ if (cached) return cached;
271
+ try {
272
+ const out = await (0, import_tinyexec.x)(
273
+ "git",
274
+ ["log", "-1", '--pretty="%ai"', import_node_path2.default.relative(process.cwd(), file)],
275
+ {
276
+ throwOnError: true
277
+ }
278
+ );
279
+ const time = new Date(out.stdout);
280
+ cache2.set(file, time);
281
+ return time;
282
+ } catch {
283
+ return;
284
+ }
285
+ }
286
+
287
+ // src/map/generate.ts
265
288
  async function readFileWithCache(file) {
266
289
  const cached = fileCache.read("read-file", file);
267
290
  if (cached) return cached;
268
291
  return (await fs2.readFile(file)).toString();
269
292
  }
270
293
  async function generateJS(configPath, config, outputPath, configHash) {
271
- const outDir2 = path2.dirname(outputPath);
294
+ const outDir2 = path3.dirname(outputPath);
272
295
  let asyncInit = false;
273
296
  const lines = [
274
297
  getImportCode({
@@ -344,8 +367,13 @@ async function generateJS(configPath, config, outputPath, configHash) {
344
367
  `invalid frontmatter in ${file.absolutePath}`
345
368
  );
346
369
  }
370
+ let lastModified;
371
+ if (config.global?.lastModifiedTime === "git") {
372
+ lastModified = await getGitTimestamp(file.absolutePath);
373
+ }
347
374
  return JSON.stringify({
348
375
  info: file,
376
+ lastModified,
349
377
  data: parsed.data,
350
378
  content: parsed.content
351
379
  });
@@ -387,13 +415,13 @@ async function getCollectionFiles(collection) {
387
415
  await Promise.all(
388
416
  dirs.map(async (dir) => {
389
417
  const result = await (0, import_tinyglobby.glob)(collection.files ?? "**/*", {
390
- cwd: path2.resolve(dir),
418
+ cwd: path3.resolve(dir),
391
419
  absolute: true
392
420
  });
393
421
  for (const item of result) {
394
422
  if (getTypeFromPath(item) !== collection.type) continue;
395
423
  files.set(item, {
396
- path: path2.relative(dir, item),
424
+ path: path3.relative(dir, item),
397
425
  absolutePath: item
398
426
  });
399
427
  }
@@ -415,18 +443,18 @@ function getImportCode(info) {
415
443
  return `import ${specifier}`;
416
444
  }
417
445
  function toImportPath(file, dir) {
418
- const ext = path2.extname(file);
419
- let importPath = path2.relative(
446
+ const ext = path3.extname(file);
447
+ let importPath = path3.relative(
420
448
  dir,
421
449
  ext === ".ts" ? file.substring(0, file.length - ext.length) : file
422
450
  );
423
- if (!path2.isAbsolute(importPath) && !importPath.startsWith(".")) {
451
+ if (!path3.isAbsolute(importPath) && !importPath.startsWith(".")) {
424
452
  importPath = `./${importPath}`;
425
453
  }
426
- return importPath.replaceAll(path2.sep, "/");
454
+ return importPath.replaceAll(path3.sep, "/");
427
455
  }
428
456
  function parseMetaEntry(file, content) {
429
- const extname3 = path2.extname(file);
457
+ const extname3 = path3.extname(file);
430
458
  try {
431
459
  if (extname3 === ".json") return JSON.parse(content);
432
460
  if (extname3 === ".yaml") return (0, import_js_yaml.load)(content);
@@ -442,7 +470,7 @@ function parseMetaEntry(file, content) {
442
470
  async function start(dev, configPath, outDir2) {
443
471
  let configHash = await getConfigHash(configPath);
444
472
  let config = await loadConfig(configPath, configHash, true);
445
- const outPath = path3.resolve(outDir2, `index.ts`);
473
+ const outPath = path4.resolve(outDir2, `index.ts`);
446
474
  async function updateMapFile() {
447
475
  const start2 = performance.now();
448
476
  try {
@@ -452,7 +480,7 @@ async function start(dev, configPath, outDir2) {
452
480
  );
453
481
  } catch (err) {
454
482
  if (err instanceof ValidationError) {
455
- err.print();
483
+ console.error(err.toStringFormatted());
456
484
  } else {
457
485
  console.error(err);
458
486
  }
@@ -468,7 +496,7 @@ async function start(dev, configPath, outDir2) {
468
496
  });
469
497
  instance.on("all", (event, file) => {
470
498
  if (typeof file !== "string") return;
471
- const absolutePath = path3.resolve(file);
499
+ const absolutePath = path4.resolve(file);
472
500
  const onUpdate = async () => {
473
501
  const isConfigFile = absolutePath === configPath;
474
502
  if (isConfigFile) {
@@ -488,7 +516,7 @@ async function start(dev, configPath, outDir2) {
488
516
  }
489
517
 
490
518
  // src/next/create.ts
491
- var outDir = import_node_path2.default.resolve(".source");
519
+ var outDir = import_node_path3.default.resolve(".source");
492
520
  var defaultPageExtensions = ["mdx", "md", "jsx", "js", "tsx", "ts"];
493
521
  function createMDX({
494
522
  configPath = findConfigFile()
@@ -501,9 +529,7 @@ function createMDX({
501
529
  }
502
530
  return (nextConfig = {}) => {
503
531
  const mdxLoaderOptions = {
504
- _ctx: {
505
- configPath
506
- }
532
+ configPath
507
533
  };
508
534
  return {
509
535
  ...nextConfig,
@@ -546,14 +572,14 @@ function createMDX({
546
572
  }
547
573
 
548
574
  // src/postinstall.ts
549
- var path5 = __toESM(require("path"), 1);
575
+ var path6 = __toESM(require("path"), 1);
550
576
  var fs4 = __toESM(require("fs/promises"), 1);
551
577
  async function postInstall(configPath = findConfigFile()) {
552
- const jsOut = path5.resolve(".source/index.ts");
578
+ const jsOut = path6.resolve(".source/index.ts");
553
579
  const hash = await getConfigHash(configPath);
554
580
  const config = await loadConfig(configPath, hash, true);
555
- await fs4.rm(path5.dirname(jsOut), { recursive: true });
556
- await fs4.mkdir(path5.dirname(jsOut), { recursive: true });
581
+ await fs4.rm(path6.dirname(jsOut), { recursive: true });
582
+ await fs4.mkdir(path6.dirname(jsOut), { recursive: true });
557
583
  await fs4.writeFile(jsOut, await generateJS(configPath, config, jsOut, hash));
558
584
  console.log("[MDX] types generated");
559
585
  }
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  findConfigFile,
3
3
  getConfigHash,
4
+ getGitTimestamp,
4
5
  loadConfig
5
- } from "../chunk-LC4HO353.js";
6
+ } from "../chunk-GWITJLOZ.js";
6
7
  import {
7
8
  ValidationError,
8
9
  validate
9
- } from "../chunk-2ZOW45YZ.js";
10
+ } from "../chunk-OTM6WYMS.js";
10
11
  import "../chunk-DRVUBK5B.js";
11
12
 
12
13
  // src/next/create.ts
@@ -136,8 +137,13 @@ async function generateJS(configPath, config, outputPath, configHash) {
136
137
  `invalid frontmatter in ${file.absolutePath}`
137
138
  );
138
139
  }
140
+ let lastModified;
141
+ if (config.global?.lastModifiedTime === "git") {
142
+ lastModified = await getGitTimestamp(file.absolutePath);
143
+ }
139
144
  return JSON.stringify({
140
145
  info: file,
146
+ lastModified,
141
147
  data: parsed.data,
142
148
  content: parsed.content
143
149
  });
@@ -244,7 +250,7 @@ async function start(dev, configPath, outDir2) {
244
250
  );
245
251
  } catch (err) {
246
252
  if (err instanceof ValidationError) {
247
- err.print();
253
+ console.error(err.toStringFormatted());
248
254
  } else {
249
255
  console.error(err);
250
256
  }
@@ -293,9 +299,7 @@ function createMDX({
293
299
  }
294
300
  return (nextConfig = {}) => {
295
301
  const mdxLoaderOptions = {
296
- _ctx: {
297
- configPath
298
- }
302
+ configPath
299
303
  };
300
304
  return {
301
305
  ...nextConfig,
@@ -223,10 +223,14 @@ async function initCompiler(config, collection) {
223
223
  mdxOptions = col.docs?.mdxOptions;
224
224
  if (!mdxOptions) {
225
225
  config._mdx_async ??= {};
226
- config._mdx_async.cachedMdxOptions ??= typeof config.global?.mdxOptions === "function" ? await config.global.mdxOptions() : config.global?.mdxOptions ?? {};
227
- mdxOptions = config._mdx_async.cachedMdxOptions;
226
+ const async = config._mdx_async;
227
+ const globalConfig = config.global;
228
+ if (globalConfig && !async.cachedMdxOptions) {
229
+ async.cachedMdxOptions = typeof globalConfig.mdxOptions === "function" ? await globalConfig.mdxOptions() : globalConfig.mdxOptions;
230
+ }
231
+ mdxOptions = async.cachedMdxOptions;
228
232
  }
229
- const remarkPlugins = mdxOptions.remarkPlugins ?? [];
233
+ const remarkPlugins = mdxOptions?.remarkPlugins ?? [];
230
234
  return (0, import_mdx_remote.createCompiler)({
231
235
  ...mdxOptions,
232
236
  remarkPlugins: (v) => typeof remarkPlugins === "function" ? [remarkInclude, ...remarkPlugins(v), import_mdx_plugins.remarkStructure] : [remarkInclude, ...v, ...remarkPlugins, import_mdx_plugins.remarkStructure]
@@ -235,7 +239,7 @@ async function initCompiler(config, collection) {
235
239
  var _runtimeAsync = {
236
240
  doc(files, collection, config) {
237
241
  const init = initCompiler(config, collection);
238
- return files.map(({ info: file, data, content }) => {
242
+ return files.map(({ info: file, data, content, lastModified }) => {
239
243
  return {
240
244
  ...data,
241
245
  _file: file,
@@ -249,6 +253,7 @@ var _runtimeAsync = {
249
253
  return {
250
254
  body: out.body,
251
255
  toc: out.toc,
256
+ lastModified,
252
257
  structuredData: out.vfile.data.structuredData,
253
258
  _exports: out.exports ?? {}
254
259
  };
@@ -1,4 +1,4 @@
1
- import { L as LoadedConfig, a as RuntimeAsync } from '../types-Cph8Ml_K.cjs';
1
+ import { L as LoadedConfig, a as RuntimeAsync } from '../types-BsJd_P5O.cjs';
2
2
  import '../define-uoePrCQ_.cjs';
3
3
  import '@mdx-js/mdx';
4
4
  import 'mdx/types';
@@ -1,4 +1,4 @@
1
- import { L as LoadedConfig, a as RuntimeAsync } from '../types-BvEsyMKj.js';
1
+ import { L as LoadedConfig, a as RuntimeAsync } from '../types-BYJBKH4G.js';
2
2
  import '../define-uoePrCQ_.js';
3
3
  import '@mdx-js/mdx';
4
4
  import 'mdx/types';
@@ -22,10 +22,14 @@ async function initCompiler(config, collection) {
22
22
  mdxOptions = col.docs?.mdxOptions;
23
23
  if (!mdxOptions) {
24
24
  config._mdx_async ??= {};
25
- config._mdx_async.cachedMdxOptions ??= typeof config.global?.mdxOptions === "function" ? await config.global.mdxOptions() : config.global?.mdxOptions ?? {};
26
- mdxOptions = config._mdx_async.cachedMdxOptions;
25
+ const async = config._mdx_async;
26
+ const globalConfig = config.global;
27
+ if (globalConfig && !async.cachedMdxOptions) {
28
+ async.cachedMdxOptions = typeof globalConfig.mdxOptions === "function" ? await globalConfig.mdxOptions() : globalConfig.mdxOptions;
29
+ }
30
+ mdxOptions = async.cachedMdxOptions;
27
31
  }
28
- const remarkPlugins = mdxOptions.remarkPlugins ?? [];
32
+ const remarkPlugins = mdxOptions?.remarkPlugins ?? [];
29
33
  return createCompiler({
30
34
  ...mdxOptions,
31
35
  remarkPlugins: (v) => typeof remarkPlugins === "function" ? [remarkInclude, ...remarkPlugins(v), remarkStructure] : [remarkInclude, ...v, ...remarkPlugins, remarkStructure]
@@ -34,7 +38,7 @@ async function initCompiler(config, collection) {
34
38
  var _runtimeAsync = {
35
39
  doc(files, collection, config) {
36
40
  const init = initCompiler(config, collection);
37
- return files.map(({ info: file, data, content }) => {
41
+ return files.map(({ info: file, data, content, lastModified }) => {
38
42
  return {
39
43
  ...data,
40
44
  _file: file,
@@ -48,6 +52,7 @@ var _runtimeAsync = {
48
52
  return {
49
53
  body: out.body,
50
54
  toc: out.toc,
55
+ lastModified,
51
56
  structuredData: out.vfile.data.structuredData,
52
57
  _exports: out.exports ?? {}
53
58
  };
@@ -8,7 +8,7 @@ interface LoadedConfig {
8
8
  collections: Map<string, DocCollection | MetaCollection | DocsCollection>;
9
9
  global?: GlobalConfig;
10
10
  _mdx_loader?: {
11
- cachedProcessorOptions?: ProcessorOptions;
11
+ cachedOptions?: ProcessorOptions;
12
12
  };
13
13
  _mdx_async?: {
14
14
  cachedMdxOptions?: MDXOptions;
@@ -23,6 +23,7 @@ interface AsyncRuntimeFile {
23
23
  info: FileInfo;
24
24
  data: Record<string, unknown>;
25
25
  content: string;
26
+ lastModified?: Date;
26
27
  }
27
28
  type DocOut<Schema extends StandardSchemaV1> = Override<MarkdownProps & {
28
29
  /**
@@ -8,7 +8,7 @@ interface LoadedConfig {
8
8
  collections: Map<string, DocCollection | MetaCollection | DocsCollection>;
9
9
  global?: GlobalConfig;
10
10
  _mdx_loader?: {
11
- cachedProcessorOptions?: ProcessorOptions;
11
+ cachedOptions?: ProcessorOptions;
12
12
  };
13
13
  _mdx_async?: {
14
14
  cachedMdxOptions?: MDXOptions;
@@ -23,6 +23,7 @@ interface AsyncRuntimeFile {
23
23
  info: FileInfo;
24
24
  data: Record<string, unknown>;
25
25
  content: string;
26
+ lastModified?: Date;
26
27
  }
27
28
  type DocOut<Schema extends StandardSchemaV1> = Override<MarkdownProps & {
28
29
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-mdx",
3
- "version": "11.6.5",
3
+ "version": "11.6.6",
4
4
  "description": "The built-in source for Fumadocs",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -45,23 +45,22 @@
45
45
  "@mdx-js/mdx": "^3.1.0",
46
46
  "@standard-schema/spec": "^1.0.0",
47
47
  "chokidar": "^4.0.3",
48
- "cross-spawn": "^7.0.6",
49
48
  "esbuild": "^0.25.4",
50
49
  "estree-util-value-to-estree": "^3.4.0",
51
50
  "gray-matter": "^4.0.3",
52
51
  "js-yaml": "^4.1.0",
53
52
  "lru-cache": "^11.1.0",
54
53
  "picocolors": "^1.1.1",
54
+ "tinyexec": "^1.0.1",
55
55
  "tinyglobby": "^0.2.13",
56
56
  "unist-util-visit": "^5.0.0",
57
- "zod": "^3.25.7"
57
+ "zod": "^3.25.28"
58
58
  },
59
59
  "devDependencies": {
60
- "@types/cross-spawn": "^6.0.6",
61
60
  "@types/js-yaml": "^4.0.9",
62
61
  "@types/mdast": "^4.0.3",
63
62
  "@types/mdx": "^2.0.13",
64
- "@types/react": "^19.1.4",
63
+ "@types/react": "^19.1.5",
65
64
  "mdast-util-mdx-jsx": "^3.2.0",
66
65
  "next": "^15.3.2",
67
66
  "unified": "^11.0.5",
@@ -69,7 +68,7 @@
69
68
  "webpack": "^5.99.9",
70
69
  "@fumadocs/mdx-remote": "1.3.2",
71
70
  "eslint-config-custom": "0.0.0",
72
- "fumadocs-core": "15.3.4",
71
+ "fumadocs-core": "15.4.0",
73
72
  "tsconfig": "0.0.0"
74
73
  },
75
74
  "peerDependencies": {