fumadocs-mdx 11.9.1 → 11.10.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.
- package/dist/bin.cjs +1063 -0
- package/dist/bin.d.cts +1 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +16 -0
- package/dist/{browser-CyU2Yl7A.d.cts → browser-B2G8uAF2.d.cts} +1 -1
- package/dist/{browser-DEsQvNRx.d.ts → browser-DrH7tKRi.d.ts} +1 -1
- package/dist/bun/index.cjs +669 -0
- package/dist/bun/index.d.cts +8 -0
- package/dist/bun/index.d.ts +8 -0
- package/dist/bun/index.js +53 -0
- package/dist/chunk-6Y5JDZHD.js +65 -0
- package/dist/chunk-CNKI574E.js +82 -0
- package/dist/{chunk-GX3THK2Q.js → chunk-IQAEAI4P.js} +25 -25
- package/dist/chunk-QJCCVMBJ.js +151 -0
- package/dist/{chunk-NUDEC6C5.js → chunk-UOOPSLFY.js} +1 -1
- package/dist/{chunk-COQ4VMK2.js → chunk-XXSKWWMB.js} +28 -61
- package/dist/config/index.d.cts +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/zod-3.d.cts +1 -1
- package/dist/config/zod-3.d.ts +1 -1
- package/dist/{define-DnJzAZrj.d.cts → define-BH4bnHQl.d.cts} +6 -0
- package/dist/{define-DnJzAZrj.d.ts → define-BH4bnHQl.d.ts} +6 -0
- package/dist/loader-mdx.cjs +345 -265
- package/dist/loader-mdx.js +12 -80
- package/dist/next/index.cjs +15 -130
- package/dist/next/index.js +15 -33
- package/dist/node/loader.cjs +748 -0
- package/dist/node/loader.d.cts +5 -0
- package/dist/node/loader.d.ts +5 -0
- package/dist/node/loader.js +24 -0
- package/dist/postinstall-XV4WSHZP.js +9 -0
- package/dist/runtime/{async.cjs → next/async.cjs} +4 -4
- package/dist/runtime/{async.d.cts → next/async.d.cts} +3 -3
- package/dist/runtime/{async.d.ts → next/async.d.ts} +3 -3
- package/dist/runtime/{async.js → next/async.js} +6 -6
- package/dist/{index.cjs → runtime/next/index.cjs} +4 -6
- package/dist/{index.d.cts → runtime/next/index.d.cts} +3 -3
- package/dist/{index.d.ts → runtime/next/index.d.ts} +3 -3
- package/dist/{index.js → runtime/next/index.js} +1 -1
- package/dist/runtime/vite/browser.d.cts +2 -2
- package/dist/runtime/vite/browser.d.ts +2 -2
- package/dist/runtime/vite/server.d.cts +3 -3
- package/dist/runtime/vite/server.d.ts +3 -3
- package/dist/{types-WSHJKA8L.d.ts → types-DN9KrG7R.d.ts} +1 -1
- package/dist/{types-BmVgoqsr.d.cts → types-DT83Ijs6.d.cts} +1 -1
- package/dist/vite/index.cjs +440 -276
- package/dist/vite/index.d.cts +4 -1
- package/dist/vite/index.d.ts +4 -1
- package/dist/vite/index.js +19 -81
- package/package.json +24 -17
- package/bin.js +0 -5
- package/dist/chunk-UCY7OBZG.js +0 -12
package/dist/vite/index.cjs
CHANGED
|
@@ -200,7 +200,8 @@ var init_mdx_options = __esm({
|
|
|
200
200
|
// src/vite/index.ts
|
|
201
201
|
var vite_exports = {};
|
|
202
202
|
__export(vite_exports, {
|
|
203
|
-
default: () => mdx
|
|
203
|
+
default: () => mdx,
|
|
204
|
+
postInstall: () => postInstall
|
|
204
205
|
});
|
|
205
206
|
module.exports = __toCommonJS(vite_exports);
|
|
206
207
|
var import_vite = require("vite");
|
|
@@ -255,14 +256,183 @@ function buildConfig(config) {
|
|
|
255
256
|
};
|
|
256
257
|
}
|
|
257
258
|
|
|
258
|
-
// src/
|
|
259
|
-
var
|
|
259
|
+
// src/vite/index.ts
|
|
260
|
+
var import_node_querystring2 = require("querystring");
|
|
260
261
|
|
|
261
|
-
// src/
|
|
262
|
-
var
|
|
263
|
-
var
|
|
264
|
-
|
|
265
|
-
|
|
262
|
+
// src/utils/validation.ts
|
|
263
|
+
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
264
|
+
var ValidationError = class extends Error {
|
|
265
|
+
constructor(message, issues) {
|
|
266
|
+
super(
|
|
267
|
+
`${message}:
|
|
268
|
+
${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
|
|
269
|
+
);
|
|
270
|
+
this.title = message;
|
|
271
|
+
this.issues = issues;
|
|
272
|
+
}
|
|
273
|
+
toStringFormatted() {
|
|
274
|
+
return [
|
|
275
|
+
import_picocolors.default.bold(`[MDX] ${this.title}:`),
|
|
276
|
+
...this.issues.map(
|
|
277
|
+
(issue) => import_picocolors.default.redBright(
|
|
278
|
+
`- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
|
|
279
|
+
)
|
|
280
|
+
)
|
|
281
|
+
].join("\n");
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
async function validate(schema, data, context, errorMessage) {
|
|
285
|
+
if (typeof schema === "function" && !("~standard" in schema)) {
|
|
286
|
+
schema = schema(context);
|
|
287
|
+
}
|
|
288
|
+
if ("~standard" in schema) {
|
|
289
|
+
const result = await schema["~standard"].validate(
|
|
290
|
+
data
|
|
291
|
+
);
|
|
292
|
+
if (result.issues) {
|
|
293
|
+
throw new ValidationError(errorMessage, result.issues);
|
|
294
|
+
}
|
|
295
|
+
return result.value;
|
|
296
|
+
}
|
|
297
|
+
return data;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// src/vite/index.ts
|
|
301
|
+
var fs6 = __toESM(require("fs/promises"), 1);
|
|
302
|
+
var path8 = __toESM(require("path"), 1);
|
|
303
|
+
var import_js_yaml2 = require("js-yaml");
|
|
304
|
+
|
|
305
|
+
// src/utils/import-formatter.ts
|
|
306
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
307
|
+
function toImportPath(file, config) {
|
|
308
|
+
const ext = import_node_path.default.extname(file);
|
|
309
|
+
let filename;
|
|
310
|
+
if (ext === ".ts" && config.jsExtension) {
|
|
311
|
+
filename = file.substring(0, file.length - ext.length) + ".js";
|
|
312
|
+
} else if (ext === ".ts") {
|
|
313
|
+
filename = file.substring(0, file.length - ext.length);
|
|
314
|
+
} else {
|
|
315
|
+
filename = file;
|
|
316
|
+
}
|
|
317
|
+
let importPath;
|
|
318
|
+
if ("relativeTo" in config) {
|
|
319
|
+
importPath = import_node_path.default.relative(config.relativeTo, filename);
|
|
320
|
+
if (!import_node_path.default.isAbsolute(importPath) && !importPath.startsWith(".")) {
|
|
321
|
+
importPath = `./${importPath}`;
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
importPath = import_node_path.default.resolve(filename);
|
|
325
|
+
}
|
|
326
|
+
return importPath.replaceAll(import_node_path.default.sep, "/");
|
|
327
|
+
}
|
|
328
|
+
function ident(code, tab = 1) {
|
|
329
|
+
return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// src/vite/generate-glob.ts
|
|
333
|
+
function generateGlob(name, patterns, globOptions) {
|
|
334
|
+
const options = {
|
|
335
|
+
...globOptions,
|
|
336
|
+
query: {
|
|
337
|
+
...globOptions?.query,
|
|
338
|
+
collection: name
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
return `import.meta.glob(${JSON.stringify(mapGlobPatterns(patterns))}, ${JSON.stringify(options, null, 2)})`;
|
|
342
|
+
}
|
|
343
|
+
function mapGlobPatterns(patterns) {
|
|
344
|
+
return patterns.map(enforceRelative);
|
|
345
|
+
}
|
|
346
|
+
function enforceRelative(file) {
|
|
347
|
+
if (file.startsWith("./")) return file;
|
|
348
|
+
if (file.startsWith("/")) return `.${file}`;
|
|
349
|
+
return `./${file}`;
|
|
350
|
+
}
|
|
351
|
+
function getGlobBase(collection) {
|
|
352
|
+
let dir = collection.dir;
|
|
353
|
+
if (Array.isArray(dir)) {
|
|
354
|
+
if (dir.length !== 1)
|
|
355
|
+
throw new Error(
|
|
356
|
+
`[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
|
|
357
|
+
);
|
|
358
|
+
dir = dir[0];
|
|
359
|
+
}
|
|
360
|
+
return enforceRelative(dir);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// src/utils/collections.ts
|
|
364
|
+
function getSupportedFormats(collection) {
|
|
365
|
+
return {
|
|
366
|
+
doc: ["mdx", "md"],
|
|
367
|
+
meta: ["json", "yaml"]
|
|
368
|
+
}[collection.type];
|
|
369
|
+
}
|
|
370
|
+
function getGlobPatterns(collection) {
|
|
371
|
+
if (collection.files) return collection.files;
|
|
372
|
+
return [`**/*.{${getSupportedFormats(collection).join(",")}}`];
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/vite/generate.ts
|
|
376
|
+
function docs(name, collection) {
|
|
377
|
+
const obj = [
|
|
378
|
+
ident(`doc: ${doc(name, collection.docs)}`),
|
|
379
|
+
ident(`meta: ${meta(name, collection.meta)}`)
|
|
380
|
+
].join(",\n");
|
|
381
|
+
return `{
|
|
382
|
+
${obj}
|
|
383
|
+
}`;
|
|
384
|
+
}
|
|
385
|
+
function doc(name, collection) {
|
|
386
|
+
const patterns = getGlobPatterns(collection);
|
|
387
|
+
const base = getGlobBase(collection);
|
|
388
|
+
const docGlob = generateGlob(name, patterns, {
|
|
389
|
+
base
|
|
390
|
+
});
|
|
391
|
+
if (collection.async) {
|
|
392
|
+
const headBlob = generateGlob(name, patterns, {
|
|
393
|
+
query: {
|
|
394
|
+
only: "frontmatter"
|
|
395
|
+
},
|
|
396
|
+
import: "frontmatter",
|
|
397
|
+
base
|
|
398
|
+
});
|
|
399
|
+
return `create.docLazy("${name}", "${base}", ${headBlob}, ${docGlob})`;
|
|
400
|
+
}
|
|
401
|
+
return `create.doc("${name}", "${base}", ${docGlob})`;
|
|
402
|
+
}
|
|
403
|
+
function meta(name, collection) {
|
|
404
|
+
const patterns = getGlobPatterns(collection);
|
|
405
|
+
const base = getGlobBase(collection);
|
|
406
|
+
return `create.meta("${name}", "${base}", ${generateGlob(name, patterns, {
|
|
407
|
+
import: "default",
|
|
408
|
+
base
|
|
409
|
+
})})`;
|
|
410
|
+
}
|
|
411
|
+
function entry(configPath, config, outDir, jsExtension) {
|
|
412
|
+
const lines = [
|
|
413
|
+
'/// <reference types="vite/client" />',
|
|
414
|
+
`import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
|
|
415
|
+
`import type * as Config from '${toImportPath(configPath, {
|
|
416
|
+
relativeTo: outDir,
|
|
417
|
+
jsExtension
|
|
418
|
+
})}';`,
|
|
419
|
+
"",
|
|
420
|
+
`export const create = fromConfig<typeof Config>();`
|
|
421
|
+
];
|
|
422
|
+
for (const [name, collection] of config.collections.entries()) {
|
|
423
|
+
let body;
|
|
424
|
+
if (collection.type === "docs") {
|
|
425
|
+
body = docs(name, collection);
|
|
426
|
+
} else if (collection.type === "meta") {
|
|
427
|
+
body = meta(name, collection);
|
|
428
|
+
} else {
|
|
429
|
+
body = doc(name, collection);
|
|
430
|
+
}
|
|
431
|
+
lines.push("");
|
|
432
|
+
lines.push(`export const ${name} = ${body};`);
|
|
433
|
+
}
|
|
434
|
+
return lines.join("\n");
|
|
435
|
+
}
|
|
266
436
|
|
|
267
437
|
// src/utils/fuma-matter.ts
|
|
268
438
|
var import_js_yaml = require("js-yaml");
|
|
@@ -280,7 +450,46 @@ function fumaMatter(input) {
|
|
|
280
450
|
return output;
|
|
281
451
|
}
|
|
282
452
|
|
|
453
|
+
// src/utils/git-timestamp.ts
|
|
454
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
455
|
+
var import_tinyexec = require("tinyexec");
|
|
456
|
+
var cache = /* @__PURE__ */ new Map();
|
|
457
|
+
async function getGitTimestamp(file) {
|
|
458
|
+
const cached = cache.get(file);
|
|
459
|
+
if (cached) return cached;
|
|
460
|
+
try {
|
|
461
|
+
const out = await (0, import_tinyexec.x)(
|
|
462
|
+
"git",
|
|
463
|
+
["log", "-1", '--pretty="%ai"', import_node_path2.default.relative(process.cwd(), file)],
|
|
464
|
+
{
|
|
465
|
+
throwOnError: true
|
|
466
|
+
}
|
|
467
|
+
);
|
|
468
|
+
const time = new Date(out.stdout);
|
|
469
|
+
cache.set(file, time);
|
|
470
|
+
return time;
|
|
471
|
+
} catch {
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// src/utils/count-lines.ts
|
|
477
|
+
function countLines(s) {
|
|
478
|
+
let num = 0;
|
|
479
|
+
for (const c of s) {
|
|
480
|
+
if (c === "\n") num++;
|
|
481
|
+
}
|
|
482
|
+
return num;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// src/utils/build-mdx.ts
|
|
486
|
+
var import_mdx = require("@mdx-js/mdx");
|
|
487
|
+
|
|
283
488
|
// src/mdx-plugins/remark-include.ts
|
|
489
|
+
var import_unified = require("unified");
|
|
490
|
+
var import_unist_util_visit2 = require("unist-util-visit");
|
|
491
|
+
var path3 = __toESM(require("path"), 1);
|
|
492
|
+
var fs = __toESM(require("fs/promises"), 1);
|
|
284
493
|
var import_remark_parse = __toESM(require("remark-parse"), 1);
|
|
285
494
|
var import_remark_mdx = __toESM(require("remark-mdx"), 1);
|
|
286
495
|
var import_mdx_plugins = require("fumadocs-core/mdx-plugins");
|
|
@@ -335,7 +544,7 @@ ${e instanceof Error ? e.message : String(e)}`,
|
|
|
335
544
|
{ cause: e }
|
|
336
545
|
);
|
|
337
546
|
}
|
|
338
|
-
const ext =
|
|
547
|
+
const ext = path3.extname(file);
|
|
339
548
|
data._compiler?.addDependency(file);
|
|
340
549
|
if (params.lang || ext !== ".md" && ext !== ".mdx") {
|
|
341
550
|
const lang = params.lang ?? ext.slice(1);
|
|
@@ -361,7 +570,7 @@ ${e instanceof Error ? e.message : String(e)}`,
|
|
|
361
570
|
);
|
|
362
571
|
parsed = extracted;
|
|
363
572
|
}
|
|
364
|
-
await update(parsed,
|
|
573
|
+
await update(parsed, path3.dirname(file), data);
|
|
365
574
|
return parsed;
|
|
366
575
|
}
|
|
367
576
|
async function update(tree, directory, data) {
|
|
@@ -381,7 +590,7 @@ ${e instanceof Error ? e.message : String(e)}`,
|
|
|
381
590
|
}
|
|
382
591
|
}
|
|
383
592
|
const { file: relativePath, section } = parseSpecifier(specifier);
|
|
384
|
-
const file =
|
|
593
|
+
const file = path3.resolve(
|
|
385
594
|
"cwd" in params ? process.cwd() : directory,
|
|
386
595
|
relativePath
|
|
387
596
|
);
|
|
@@ -399,7 +608,7 @@ ${e instanceof Error ? e.message : String(e)}`,
|
|
|
399
608
|
await Promise.all(queue);
|
|
400
609
|
}
|
|
401
610
|
return async (tree, file) => {
|
|
402
|
-
await update(tree,
|
|
611
|
+
await update(tree, path3.dirname(file.path), file.data);
|
|
403
612
|
};
|
|
404
613
|
}
|
|
405
614
|
function getDefaultProcessor(format) {
|
|
@@ -409,12 +618,12 @@ function getDefaultProcessor(format) {
|
|
|
409
618
|
}
|
|
410
619
|
|
|
411
620
|
// src/utils/build-mdx.ts
|
|
412
|
-
var
|
|
621
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
413
622
|
async function buildMDX(cacheKey, source, options) {
|
|
414
623
|
const { filePath, frontmatter, data, _compiler, ...rest } = options;
|
|
415
624
|
function getProcessor(format) {
|
|
416
625
|
const key = `${cacheKey}:${format}`;
|
|
417
|
-
let processor =
|
|
626
|
+
let processor = cache2.get(key);
|
|
418
627
|
if (!processor) {
|
|
419
628
|
processor = (0, import_mdx.createProcessor)({
|
|
420
629
|
outputFormat: "program",
|
|
@@ -422,7 +631,7 @@ async function buildMDX(cacheKey, source, options) {
|
|
|
422
631
|
remarkPlugins: [remarkInclude, ...rest.remarkPlugins ?? []],
|
|
423
632
|
format
|
|
424
633
|
});
|
|
425
|
-
|
|
634
|
+
cache2.set(key, processor);
|
|
426
635
|
}
|
|
427
636
|
return processor;
|
|
428
637
|
}
|
|
@@ -440,229 +649,241 @@ async function buildMDX(cacheKey, source, options) {
|
|
|
440
649
|
});
|
|
441
650
|
}
|
|
442
651
|
|
|
443
|
-
// src/
|
|
444
|
-
var
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
652
|
+
// src/loaders/mdx.ts
|
|
653
|
+
var import_zod = require("zod");
|
|
654
|
+
var import_promises = __toESM(require("fs/promises"), 1);
|
|
655
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
656
|
+
var import_node_crypto = require("crypto");
|
|
657
|
+
var querySchema = import_zod.z.object({
|
|
658
|
+
only: import_zod.z.literal(["frontmatter", "all"]).default("all"),
|
|
659
|
+
collection: import_zod.z.string().optional(),
|
|
660
|
+
hash: import_zod.z.string().describe(
|
|
661
|
+
"the hash of config, used for revalidation on Turbopack/Webpack."
|
|
662
|
+
).optional()
|
|
663
|
+
}).loose();
|
|
664
|
+
var cacheEntry = import_zod.z.object({
|
|
665
|
+
code: import_zod.z.string(),
|
|
666
|
+
map: import_zod.z.any().optional(),
|
|
667
|
+
hash: import_zod.z.string().optional()
|
|
668
|
+
});
|
|
669
|
+
function createMdxLoader(configLoader) {
|
|
670
|
+
return async ({
|
|
671
|
+
source: value,
|
|
672
|
+
development: isDevelopment,
|
|
673
|
+
query,
|
|
674
|
+
compiler,
|
|
675
|
+
filePath
|
|
676
|
+
}) => {
|
|
677
|
+
const matter = fumaMatter(value);
|
|
678
|
+
const parsed = querySchema.parse(query);
|
|
679
|
+
const loaded = await configLoader.getConfig(parsed.hash);
|
|
680
|
+
const cacheDir = isDevelopment ? void 0 : loaded.global.experimentalBuildCache;
|
|
681
|
+
const cacheKey = `${parsed.hash}_${parsed.collection ?? "global"}_${generateCacheHash(filePath)}`;
|
|
682
|
+
if (cacheDir) {
|
|
683
|
+
const cached = await import_promises.default.readFile(import_node_path3.default.join(cacheDir, cacheKey)).then((content) => cacheEntry.parse(JSON.parse(content.toString()))).catch(() => null);
|
|
684
|
+
if (cached && cached.hash === generateCacheHash(value)) return cached;
|
|
685
|
+
}
|
|
686
|
+
const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
|
|
687
|
+
let schema;
|
|
688
|
+
let mdxOptions;
|
|
689
|
+
switch (collection?.type) {
|
|
690
|
+
case "doc":
|
|
691
|
+
mdxOptions = collection.mdxOptions;
|
|
692
|
+
schema = collection.schema;
|
|
693
|
+
break;
|
|
694
|
+
case "docs":
|
|
695
|
+
mdxOptions = collection.docs.mdxOptions;
|
|
696
|
+
schema = collection.docs.schema;
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
699
|
+
if (schema) {
|
|
700
|
+
matter.data = await validate(
|
|
701
|
+
schema,
|
|
702
|
+
matter.data,
|
|
703
|
+
{
|
|
704
|
+
source: value,
|
|
705
|
+
path: filePath
|
|
706
|
+
},
|
|
707
|
+
`invalid frontmatter in ${filePath}`
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
if (parsed.only === "frontmatter") {
|
|
711
|
+
return {
|
|
712
|
+
code: `export const frontmatter = ${JSON.stringify(matter.data)}`,
|
|
713
|
+
map: null
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
const data = {};
|
|
717
|
+
if (loaded.global.lastModifiedTime === "git") {
|
|
718
|
+
data.lastModified = (await getGitTimestamp(filePath))?.getTime();
|
|
719
|
+
}
|
|
720
|
+
const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
|
|
721
|
+
const compiled = await buildMDX(
|
|
722
|
+
`${parsed.hash ?? ""}:${parsed.collection ?? "global"}`,
|
|
723
|
+
"\n".repeat(lineOffset) + matter.content,
|
|
724
|
+
{
|
|
725
|
+
development: isDevelopment,
|
|
726
|
+
...mdxOptions ?? await loaded.getDefaultMDXOptions(),
|
|
727
|
+
data,
|
|
728
|
+
filePath,
|
|
729
|
+
frontmatter: matter.data,
|
|
730
|
+
_compiler: compiler
|
|
731
|
+
}
|
|
484
732
|
);
|
|
485
|
-
|
|
486
|
-
|
|
733
|
+
const out = {
|
|
734
|
+
code: String(compiled.value),
|
|
735
|
+
map: compiled.map
|
|
736
|
+
};
|
|
737
|
+
if (cacheDir) {
|
|
738
|
+
await import_promises.default.mkdir(cacheDir, { recursive: true });
|
|
739
|
+
await import_promises.default.writeFile(
|
|
740
|
+
import_node_path3.default.join(cacheDir, cacheKey),
|
|
741
|
+
JSON.stringify({
|
|
742
|
+
...out,
|
|
743
|
+
hash: generateCacheHash(value)
|
|
744
|
+
})
|
|
745
|
+
);
|
|
487
746
|
}
|
|
488
|
-
return
|
|
489
|
-
}
|
|
490
|
-
|
|
747
|
+
return out;
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
function generateCacheHash(input) {
|
|
751
|
+
return (0, import_node_crypto.createHash)("md5").update(input).digest("hex");
|
|
491
752
|
}
|
|
492
753
|
|
|
493
|
-
// src/
|
|
494
|
-
var
|
|
495
|
-
var
|
|
496
|
-
var
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
var
|
|
501
|
-
|
|
502
|
-
var cache2 = /* @__PURE__ */ new Map();
|
|
503
|
-
async function getGitTimestamp(file) {
|
|
504
|
-
const cached = cache2.get(file);
|
|
505
|
-
if (cached) return cached;
|
|
754
|
+
// src/utils/config.ts
|
|
755
|
+
var fs3 = __toESM(require("fs/promises"), 1);
|
|
756
|
+
var path5 = __toESM(require("path"), 1);
|
|
757
|
+
var import_node_url = require("url");
|
|
758
|
+
function findConfigFile() {
|
|
759
|
+
return path5.resolve("source.config.ts");
|
|
760
|
+
}
|
|
761
|
+
var cache3 = null;
|
|
762
|
+
async function isZod3() {
|
|
506
763
|
try {
|
|
507
|
-
const
|
|
508
|
-
"
|
|
509
|
-
["log", "-1", '--pretty="%ai"', import_node_path.default.relative(process.cwd(), file)],
|
|
510
|
-
{
|
|
511
|
-
throwOnError: true
|
|
512
|
-
}
|
|
764
|
+
const content = JSON.parse(
|
|
765
|
+
(await fs3.readFile("node_modules/zod/package.json")).toString()
|
|
513
766
|
);
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
return time;
|
|
767
|
+
const version = content.version;
|
|
768
|
+
return typeof version === "string" && version.startsWith("3.");
|
|
517
769
|
} catch {
|
|
518
|
-
return;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
// src/utils/import-formatter.ts
|
|
523
|
-
var import_node_path2 = __toESM(require("path"), 1);
|
|
524
|
-
function toImportPath(file, config) {
|
|
525
|
-
const ext = import_node_path2.default.extname(file);
|
|
526
|
-
let filename;
|
|
527
|
-
if (ext === ".ts" && config.jsExtension) {
|
|
528
|
-
filename = file.substring(0, file.length - ext.length) + ".js";
|
|
529
|
-
} else if (ext === ".ts") {
|
|
530
|
-
filename = file.substring(0, file.length - ext.length);
|
|
531
|
-
} else {
|
|
532
|
-
filename = file;
|
|
533
|
-
}
|
|
534
|
-
let importPath;
|
|
535
|
-
if ("relativeTo" in config) {
|
|
536
|
-
importPath = import_node_path2.default.relative(config.relativeTo, filename);
|
|
537
|
-
if (!import_node_path2.default.isAbsolute(importPath) && !importPath.startsWith(".")) {
|
|
538
|
-
importPath = `./${importPath}`;
|
|
539
|
-
}
|
|
540
|
-
} else {
|
|
541
|
-
importPath = import_node_path2.default.resolve(filename);
|
|
770
|
+
return false;
|
|
542
771
|
}
|
|
543
|
-
return importPath.replaceAll(import_node_path2.default.sep, "/");
|
|
544
|
-
}
|
|
545
|
-
function ident(code, tab = 1) {
|
|
546
|
-
return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
|
|
547
772
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
773
|
+
function createCompatZodPlugin() {
|
|
774
|
+
return {
|
|
775
|
+
name: "replace-zod-import",
|
|
776
|
+
async setup(build) {
|
|
777
|
+
const usingZod3 = await isZod3();
|
|
778
|
+
if (!usingZod3) return;
|
|
779
|
+
console.warn(
|
|
780
|
+
"[Fumadocs MDX] Noticed Zod v3 in your node_modules, we recommend upgrading to Zod v4 for better compatibility."
|
|
781
|
+
);
|
|
782
|
+
build.onResolve({ filter: /^fumadocs-mdx\/config$/ }, () => {
|
|
783
|
+
return {
|
|
784
|
+
path: "fumadocs-mdx/config/zod-3",
|
|
785
|
+
external: true
|
|
786
|
+
};
|
|
787
|
+
});
|
|
556
788
|
}
|
|
557
789
|
};
|
|
558
|
-
return `import.meta.glob(${JSON.stringify(mapGlobPatterns(patterns))}, ${JSON.stringify(options, null, 2)})`;
|
|
559
|
-
}
|
|
560
|
-
function mapGlobPatterns(patterns) {
|
|
561
|
-
return patterns.map(enforceRelative);
|
|
562
790
|
}
|
|
563
|
-
function
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
791
|
+
async function compileConfig(configPath, outDir) {
|
|
792
|
+
const { build } = await import("esbuild");
|
|
793
|
+
const transformed = await build({
|
|
794
|
+
entryPoints: [{ in: configPath, out: "source.config" }],
|
|
795
|
+
bundle: true,
|
|
796
|
+
outdir: outDir,
|
|
797
|
+
target: "node20",
|
|
798
|
+
write: true,
|
|
799
|
+
platform: "node",
|
|
800
|
+
format: "esm",
|
|
801
|
+
packages: "external",
|
|
802
|
+
plugins: [createCompatZodPlugin()],
|
|
803
|
+
outExtension: {
|
|
804
|
+
".js": ".mjs"
|
|
805
|
+
},
|
|
806
|
+
allowOverwrite: true
|
|
807
|
+
});
|
|
808
|
+
if (transformed.errors.length > 0) {
|
|
809
|
+
throw new Error("failed to compile configuration file");
|
|
810
|
+
}
|
|
567
811
|
}
|
|
568
|
-
function
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
if (dir.length !== 1)
|
|
572
|
-
throw new Error(
|
|
573
|
-
`[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
|
|
574
|
-
);
|
|
575
|
-
dir = dir[0];
|
|
812
|
+
async function loadConfig(configPath, outDir, hash, build = false) {
|
|
813
|
+
if (cache3 && cache3.hash === hash) {
|
|
814
|
+
return await cache3.config;
|
|
576
815
|
}
|
|
577
|
-
|
|
816
|
+
if (build) await compileConfig(configPath, outDir);
|
|
817
|
+
const url = (0, import_node_url.pathToFileURL)(path5.resolve(outDir, "source.config.mjs"));
|
|
818
|
+
const config = import(`${url.href}?hash=${hash}`).then((loaded) => {
|
|
819
|
+
return buildConfig(
|
|
820
|
+
// every call to `loadConfig` will cause the previous cache to be ignored
|
|
821
|
+
loaded
|
|
822
|
+
);
|
|
823
|
+
});
|
|
824
|
+
if (hash) cache3 = { config, hash };
|
|
825
|
+
return await config;
|
|
578
826
|
}
|
|
579
827
|
|
|
580
|
-
// src/
|
|
581
|
-
function
|
|
828
|
+
// src/loaders/config-loader.ts
|
|
829
|
+
function resolvedConfig(loaded) {
|
|
582
830
|
return {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
}
|
|
587
|
-
function getGlobPatterns(collection) {
|
|
588
|
-
if (collection.files) return collection.files;
|
|
589
|
-
return [`**/*.{${getSupportedFormats(collection).join(",")}}`];
|
|
831
|
+
getConfig() {
|
|
832
|
+
return loaded;
|
|
833
|
+
}
|
|
834
|
+
};
|
|
590
835
|
}
|
|
591
836
|
|
|
592
|
-
// src/
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
return
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
const headBlob = generateGlob(name, patterns, {
|
|
610
|
-
query: {
|
|
611
|
-
only: "frontmatter"
|
|
612
|
-
},
|
|
613
|
-
import: "frontmatter",
|
|
614
|
-
base
|
|
837
|
+
// src/loaders/adapter.ts
|
|
838
|
+
var import_node_url2 = require("url");
|
|
839
|
+
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
840
|
+
var import_node_querystring = require("querystring");
|
|
841
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
842
|
+
function toVite(loader) {
|
|
843
|
+
return async function(file, query, value) {
|
|
844
|
+
const result = await loader({
|
|
845
|
+
filePath: file,
|
|
846
|
+
query: (0, import_node_querystring.parse)(query),
|
|
847
|
+
source: value,
|
|
848
|
+
development: this.environment.mode === "dev",
|
|
849
|
+
compiler: {
|
|
850
|
+
addDependency: (file2) => {
|
|
851
|
+
this.addWatchFile(file2);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
615
854
|
});
|
|
616
|
-
return
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
const patterns = getGlobPatterns(collection);
|
|
622
|
-
const base = getGlobBase(collection);
|
|
623
|
-
return `create.meta("${name}", "${base}", ${generateGlob(name, patterns, {
|
|
624
|
-
import: "default",
|
|
625
|
-
base
|
|
626
|
-
})})`;
|
|
855
|
+
return {
|
|
856
|
+
code: result.code,
|
|
857
|
+
map: result.map
|
|
858
|
+
};
|
|
859
|
+
};
|
|
627
860
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
`export const create = fromConfig<typeof Config>();`
|
|
638
|
-
];
|
|
639
|
-
for (const [name, collection] of config.collections.entries()) {
|
|
640
|
-
let body;
|
|
641
|
-
if (collection.type === "docs") {
|
|
642
|
-
body = docs(name, collection);
|
|
643
|
-
} else if (collection.type === "meta") {
|
|
644
|
-
body = meta(name, collection);
|
|
645
|
-
} else {
|
|
646
|
-
body = doc(name, collection);
|
|
647
|
-
}
|
|
648
|
-
lines.push("");
|
|
649
|
-
lines.push(`export const ${name} = ${body};`);
|
|
861
|
+
|
|
862
|
+
// src/vite/postinstall.ts
|
|
863
|
+
var import_promises3 = __toESM(require("fs/promises"), 1);
|
|
864
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
865
|
+
async function postInstall(configPath = findConfigFile(), outDir, addJsExtension = false) {
|
|
866
|
+
const config = await loadConfig(configPath, "node_modules", void 0, true);
|
|
867
|
+
const outFile = "source.generated.ts";
|
|
868
|
+
if (outDir) {
|
|
869
|
+
await import_promises3.default.mkdir(outDir, { recursive: true });
|
|
650
870
|
}
|
|
651
|
-
|
|
871
|
+
await import_promises3.default.writeFile(
|
|
872
|
+
outDir ? import_node_path5.default.join(outDir, outFile) : outFile,
|
|
873
|
+
entry(configPath, config, outDir ?? process.cwd(), addJsExtension)
|
|
874
|
+
);
|
|
875
|
+
console.log("[MDX] types generated");
|
|
652
876
|
}
|
|
653
877
|
|
|
654
878
|
// src/vite/index.ts
|
|
655
879
|
var FumadocsDeps = ["fumadocs-core", "fumadocs-ui", "fumadocs-openapi"];
|
|
656
|
-
var querySchema = import_zod.z.object({
|
|
657
|
-
only: import_zod.z.literal(["frontmatter", "all"]).default("all"),
|
|
658
|
-
collection: import_zod.z.string().optional()
|
|
659
|
-
}).loose();
|
|
660
880
|
function mdx(config, options = {}) {
|
|
661
881
|
const { generateIndexFile = true, configPath = "source.config.ts" } = options;
|
|
662
882
|
const loaded = buildConfig(config);
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
const
|
|
883
|
+
const mdxLoader = toVite(createMdxLoader(resolvedConfig(loaded)));
|
|
884
|
+
async function transformMeta(path9, query, value) {
|
|
885
|
+
const isJson = path9.endsWith(".json");
|
|
886
|
+
const parsed = (0, import_node_querystring2.parse)(query);
|
|
666
887
|
const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
|
|
667
888
|
if (!collection) return null;
|
|
668
889
|
let schema;
|
|
@@ -684,75 +905,14 @@ function mdx(config, options = {}) {
|
|
|
684
905
|
const out = await validate(
|
|
685
906
|
schema,
|
|
686
907
|
data,
|
|
687
|
-
{ path:
|
|
688
|
-
`invalid data in ${
|
|
908
|
+
{ path: path9, source: value },
|
|
909
|
+
`invalid data in ${path9}`
|
|
689
910
|
);
|
|
690
911
|
return {
|
|
691
912
|
code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
|
|
692
913
|
map: null
|
|
693
914
|
};
|
|
694
915
|
}
|
|
695
|
-
async function transformContent(file, query, value) {
|
|
696
|
-
const matter = fumaMatter(value);
|
|
697
|
-
const isDevelopment = this.environment.mode === "dev";
|
|
698
|
-
const parsed = querySchema.parse((0, import_node_querystring.parse)(query));
|
|
699
|
-
const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
|
|
700
|
-
let schema;
|
|
701
|
-
let mdxOptions;
|
|
702
|
-
switch (collection?.type) {
|
|
703
|
-
case "doc":
|
|
704
|
-
mdxOptions = collection.mdxOptions;
|
|
705
|
-
schema = collection.schema;
|
|
706
|
-
break;
|
|
707
|
-
case "docs":
|
|
708
|
-
mdxOptions = collection.docs.mdxOptions;
|
|
709
|
-
schema = collection.docs.schema;
|
|
710
|
-
break;
|
|
711
|
-
}
|
|
712
|
-
if (schema) {
|
|
713
|
-
matter.data = await validate(
|
|
714
|
-
schema,
|
|
715
|
-
matter.data,
|
|
716
|
-
{
|
|
717
|
-
source: value,
|
|
718
|
-
path: file
|
|
719
|
-
},
|
|
720
|
-
`invalid frontmatter in ${file}`
|
|
721
|
-
);
|
|
722
|
-
}
|
|
723
|
-
if (parsed.only === "frontmatter") {
|
|
724
|
-
return {
|
|
725
|
-
code: `export const frontmatter = ${JSON.stringify(matter.data)}`,
|
|
726
|
-
map: null
|
|
727
|
-
};
|
|
728
|
-
}
|
|
729
|
-
const data = {};
|
|
730
|
-
if (loaded.global.lastModifiedTime === "git") {
|
|
731
|
-
data.lastModified = (await getGitTimestamp(file))?.getTime();
|
|
732
|
-
}
|
|
733
|
-
mdxOptions ??= await loaded.getDefaultMDXOptions();
|
|
734
|
-
const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
|
|
735
|
-
const compiled = await buildMDX(
|
|
736
|
-
parsed.collection ?? "global",
|
|
737
|
-
"\n".repeat(lineOffset) + matter.content,
|
|
738
|
-
{
|
|
739
|
-
development: isDevelopment,
|
|
740
|
-
...mdxOptions,
|
|
741
|
-
data,
|
|
742
|
-
filePath: file,
|
|
743
|
-
frontmatter: matter.data,
|
|
744
|
-
_compiler: {
|
|
745
|
-
addDependency: (file2) => {
|
|
746
|
-
this.addWatchFile(file2);
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
);
|
|
751
|
-
return {
|
|
752
|
-
code: String(compiled.value),
|
|
753
|
-
map: compiled.map
|
|
754
|
-
};
|
|
755
|
-
}
|
|
756
916
|
return {
|
|
757
917
|
name: "fumadocs-mdx",
|
|
758
918
|
// needed, otherwise other plugins will be executed before our `transform`.
|
|
@@ -773,8 +933,8 @@ function mdx(config, options = {}) {
|
|
|
773
933
|
console.log("[Fumadocs MDX] Generating index files");
|
|
774
934
|
const outDir = process.cwd();
|
|
775
935
|
const outFile = "source.generated.ts";
|
|
776
|
-
await
|
|
777
|
-
|
|
936
|
+
await fs6.writeFile(
|
|
937
|
+
path8.join(outDir, outFile),
|
|
778
938
|
entry(
|
|
779
939
|
configPath,
|
|
780
940
|
loaded,
|
|
@@ -785,12 +945,12 @@ function mdx(config, options = {}) {
|
|
|
785
945
|
},
|
|
786
946
|
async transform(value, id) {
|
|
787
947
|
const [file, query = ""] = id.split("?");
|
|
788
|
-
const ext =
|
|
948
|
+
const ext = path8.extname(file);
|
|
789
949
|
try {
|
|
790
950
|
if ([".yaml", ".json"].includes(ext))
|
|
791
951
|
return await transformMeta(file, query, value);
|
|
792
952
|
if ([".md", ".mdx"].includes(ext))
|
|
793
|
-
return await
|
|
953
|
+
return await mdxLoader.call(this, file, query, value);
|
|
794
954
|
} catch (e) {
|
|
795
955
|
if (e instanceof ValidationError) {
|
|
796
956
|
throw new Error(e.toStringFormatted());
|
|
@@ -800,3 +960,7 @@ function mdx(config, options = {}) {
|
|
|
800
960
|
}
|
|
801
961
|
};
|
|
802
962
|
}
|
|
963
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
964
|
+
0 && (module.exports = {
|
|
965
|
+
postInstall
|
|
966
|
+
});
|