fumadocs-mdx 11.9.0 → 11.10.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.
- package/dist/{runtime/vite.d.ts → browser-B2G8uAF2.d.cts} +9 -35
- package/dist/{runtime/vite.d.cts → browser-DrH7tKRi.d.ts} +9 -35
- package/dist/bun/index.cjs +667 -0
- package/dist/bun/index.d.cts +8 -0
- package/dist/bun/index.d.ts +8 -0
- package/dist/bun/index.js +50 -0
- package/dist/{chunk-766EAFX6.js → chunk-2HKRTQYP.js} +64 -0
- package/dist/chunk-46UPKP5R.js +77 -0
- package/dist/chunk-5XJM5RPV.js +149 -0
- package/dist/chunk-NVX3U5YE.js +82 -0
- 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.ts → define-BH4bnHQl.d.cts} +6 -0
- package/dist/{define-DnJzAZrj.d.cts → define-BH4bnHQl.d.ts} +6 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/loader-mdx.cjs +345 -265
- package/dist/loader-mdx.js +11 -80
- package/dist/next/index.js +4 -6
- 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 +23 -0
- package/dist/runtime/async.d.cts +2 -2
- package/dist/runtime/async.d.ts +2 -2
- package/dist/runtime/vite/browser.cjs +103 -0
- package/dist/runtime/vite/browser.d.cts +11 -0
- package/dist/runtime/vite/browser.d.ts +11 -0
- package/dist/runtime/vite/browser.js +10 -0
- package/dist/runtime/{vite.cjs → vite/server.cjs} +77 -63
- package/dist/runtime/vite/server.d.cts +41 -0
- package/dist/runtime/vite/server.d.ts +41 -0
- package/dist/runtime/{vite.js → vite/server.js} +10 -64
- 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 +356 -282
- package/dist/vite/index.js +12 -78
- package/package.json +21 -11
- package/dist/chunk-GX3THK2Q.js +0 -66
- package/dist/chunk-UCY7OBZG.js +0 -12
package/dist/vite/index.cjs
CHANGED
|
@@ -255,14 +255,183 @@ function buildConfig(config) {
|
|
|
255
255
|
};
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
-
// src/
|
|
259
|
-
var
|
|
258
|
+
// src/vite/index.ts
|
|
259
|
+
var import_node_querystring2 = require("querystring");
|
|
260
260
|
|
|
261
|
-
// src/
|
|
262
|
-
var
|
|
263
|
-
var
|
|
264
|
-
|
|
265
|
-
|
|
261
|
+
// src/utils/validation.ts
|
|
262
|
+
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
263
|
+
var ValidationError = class extends Error {
|
|
264
|
+
constructor(message, issues) {
|
|
265
|
+
super(
|
|
266
|
+
`${message}:
|
|
267
|
+
${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
|
|
268
|
+
);
|
|
269
|
+
this.title = message;
|
|
270
|
+
this.issues = issues;
|
|
271
|
+
}
|
|
272
|
+
toStringFormatted() {
|
|
273
|
+
return [
|
|
274
|
+
import_picocolors.default.bold(`[MDX] ${this.title}:`),
|
|
275
|
+
...this.issues.map(
|
|
276
|
+
(issue) => import_picocolors.default.redBright(
|
|
277
|
+
`- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
|
|
278
|
+
)
|
|
279
|
+
)
|
|
280
|
+
].join("\n");
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
async function validate(schema, data, context, errorMessage) {
|
|
284
|
+
if (typeof schema === "function" && !("~standard" in schema)) {
|
|
285
|
+
schema = schema(context);
|
|
286
|
+
}
|
|
287
|
+
if ("~standard" in schema) {
|
|
288
|
+
const result = await schema["~standard"].validate(
|
|
289
|
+
data
|
|
290
|
+
);
|
|
291
|
+
if (result.issues) {
|
|
292
|
+
throw new ValidationError(errorMessage, result.issues);
|
|
293
|
+
}
|
|
294
|
+
return result.value;
|
|
295
|
+
}
|
|
296
|
+
return data;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// src/vite/index.ts
|
|
300
|
+
var fs5 = __toESM(require("fs/promises"), 1);
|
|
301
|
+
var path7 = __toESM(require("path"), 1);
|
|
302
|
+
var import_js_yaml2 = require("js-yaml");
|
|
303
|
+
|
|
304
|
+
// src/utils/import-formatter.ts
|
|
305
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
306
|
+
function toImportPath(file, config) {
|
|
307
|
+
const ext = import_node_path.default.extname(file);
|
|
308
|
+
let filename;
|
|
309
|
+
if (ext === ".ts" && config.jsExtension) {
|
|
310
|
+
filename = file.substring(0, file.length - ext.length) + ".js";
|
|
311
|
+
} else if (ext === ".ts") {
|
|
312
|
+
filename = file.substring(0, file.length - ext.length);
|
|
313
|
+
} else {
|
|
314
|
+
filename = file;
|
|
315
|
+
}
|
|
316
|
+
let importPath;
|
|
317
|
+
if ("relativeTo" in config) {
|
|
318
|
+
importPath = import_node_path.default.relative(config.relativeTo, filename);
|
|
319
|
+
if (!import_node_path.default.isAbsolute(importPath) && !importPath.startsWith(".")) {
|
|
320
|
+
importPath = `./${importPath}`;
|
|
321
|
+
}
|
|
322
|
+
} else {
|
|
323
|
+
importPath = import_node_path.default.resolve(filename);
|
|
324
|
+
}
|
|
325
|
+
return importPath.replaceAll(import_node_path.default.sep, "/");
|
|
326
|
+
}
|
|
327
|
+
function ident(code, tab = 1) {
|
|
328
|
+
return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// src/vite/generate-glob.ts
|
|
332
|
+
function generateGlob(name, patterns, globOptions) {
|
|
333
|
+
const options = {
|
|
334
|
+
...globOptions,
|
|
335
|
+
query: {
|
|
336
|
+
...globOptions?.query,
|
|
337
|
+
collection: name
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
return `import.meta.glob(${JSON.stringify(mapGlobPatterns(patterns))}, ${JSON.stringify(options, null, 2)})`;
|
|
341
|
+
}
|
|
342
|
+
function mapGlobPatterns(patterns) {
|
|
343
|
+
return patterns.map(enforceRelative);
|
|
344
|
+
}
|
|
345
|
+
function enforceRelative(file) {
|
|
346
|
+
if (file.startsWith("./")) return file;
|
|
347
|
+
if (file.startsWith("/")) return `.${file}`;
|
|
348
|
+
return `./${file}`;
|
|
349
|
+
}
|
|
350
|
+
function getGlobBase(collection) {
|
|
351
|
+
let dir = collection.dir;
|
|
352
|
+
if (Array.isArray(dir)) {
|
|
353
|
+
if (dir.length !== 1)
|
|
354
|
+
throw new Error(
|
|
355
|
+
`[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
|
|
356
|
+
);
|
|
357
|
+
dir = dir[0];
|
|
358
|
+
}
|
|
359
|
+
return enforceRelative(dir);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// src/utils/collections.ts
|
|
363
|
+
function getSupportedFormats(collection) {
|
|
364
|
+
return {
|
|
365
|
+
doc: ["mdx", "md"],
|
|
366
|
+
meta: ["json", "yaml"]
|
|
367
|
+
}[collection.type];
|
|
368
|
+
}
|
|
369
|
+
function getGlobPatterns(collection) {
|
|
370
|
+
if (collection.files) return collection.files;
|
|
371
|
+
return [`**/*.{${getSupportedFormats(collection).join(",")}}`];
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// src/vite/generate.ts
|
|
375
|
+
function docs(name, collection) {
|
|
376
|
+
const obj = [
|
|
377
|
+
ident(`doc: ${doc(name, collection.docs)}`),
|
|
378
|
+
ident(`meta: ${meta(name, collection.meta)}`)
|
|
379
|
+
].join(",\n");
|
|
380
|
+
return `{
|
|
381
|
+
${obj}
|
|
382
|
+
}`;
|
|
383
|
+
}
|
|
384
|
+
function doc(name, collection) {
|
|
385
|
+
const patterns = getGlobPatterns(collection);
|
|
386
|
+
const base = getGlobBase(collection);
|
|
387
|
+
const docGlob = generateGlob(name, patterns, {
|
|
388
|
+
base
|
|
389
|
+
});
|
|
390
|
+
if (collection.async) {
|
|
391
|
+
const headBlob = generateGlob(name, patterns, {
|
|
392
|
+
query: {
|
|
393
|
+
only: "frontmatter"
|
|
394
|
+
},
|
|
395
|
+
import: "frontmatter",
|
|
396
|
+
base
|
|
397
|
+
});
|
|
398
|
+
return `create.docLazy("${name}", "${base}", ${headBlob}, ${docGlob})`;
|
|
399
|
+
}
|
|
400
|
+
return `create.doc("${name}", "${base}", ${docGlob})`;
|
|
401
|
+
}
|
|
402
|
+
function meta(name, collection) {
|
|
403
|
+
const patterns = getGlobPatterns(collection);
|
|
404
|
+
const base = getGlobBase(collection);
|
|
405
|
+
return `create.meta("${name}", "${base}", ${generateGlob(name, patterns, {
|
|
406
|
+
import: "default",
|
|
407
|
+
base
|
|
408
|
+
})})`;
|
|
409
|
+
}
|
|
410
|
+
function entry(configPath, config, outDir, jsExtension) {
|
|
411
|
+
const lines = [
|
|
412
|
+
'/// <reference types="vite/client" />',
|
|
413
|
+
`import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
|
|
414
|
+
`import type * as Config from '${toImportPath(configPath, {
|
|
415
|
+
relativeTo: outDir,
|
|
416
|
+
jsExtension
|
|
417
|
+
})}';`,
|
|
418
|
+
"",
|
|
419
|
+
`export const create = fromConfig<typeof Config>();`
|
|
420
|
+
];
|
|
421
|
+
for (const [name, collection] of config.collections.entries()) {
|
|
422
|
+
let body;
|
|
423
|
+
if (collection.type === "docs") {
|
|
424
|
+
body = docs(name, collection);
|
|
425
|
+
} else if (collection.type === "meta") {
|
|
426
|
+
body = meta(name, collection);
|
|
427
|
+
} else {
|
|
428
|
+
body = doc(name, collection);
|
|
429
|
+
}
|
|
430
|
+
lines.push("");
|
|
431
|
+
lines.push(`export const ${name} = ${body};`);
|
|
432
|
+
}
|
|
433
|
+
return lines.join("\n");
|
|
434
|
+
}
|
|
266
435
|
|
|
267
436
|
// src/utils/fuma-matter.ts
|
|
268
437
|
var import_js_yaml = require("js-yaml");
|
|
@@ -280,7 +449,46 @@ function fumaMatter(input) {
|
|
|
280
449
|
return output;
|
|
281
450
|
}
|
|
282
451
|
|
|
452
|
+
// src/utils/git-timestamp.ts
|
|
453
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
454
|
+
var import_tinyexec = require("tinyexec");
|
|
455
|
+
var cache = /* @__PURE__ */ new Map();
|
|
456
|
+
async function getGitTimestamp(file) {
|
|
457
|
+
const cached = cache.get(file);
|
|
458
|
+
if (cached) return cached;
|
|
459
|
+
try {
|
|
460
|
+
const out = await (0, import_tinyexec.x)(
|
|
461
|
+
"git",
|
|
462
|
+
["log", "-1", '--pretty="%ai"', import_node_path2.default.relative(process.cwd(), file)],
|
|
463
|
+
{
|
|
464
|
+
throwOnError: true
|
|
465
|
+
}
|
|
466
|
+
);
|
|
467
|
+
const time = new Date(out.stdout);
|
|
468
|
+
cache.set(file, time);
|
|
469
|
+
return time;
|
|
470
|
+
} catch {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// src/utils/count-lines.ts
|
|
476
|
+
function countLines(s) {
|
|
477
|
+
let num = 0;
|
|
478
|
+
for (const c of s) {
|
|
479
|
+
if (c === "\n") num++;
|
|
480
|
+
}
|
|
481
|
+
return num;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// src/utils/build-mdx.ts
|
|
485
|
+
var import_mdx = require("@mdx-js/mdx");
|
|
486
|
+
|
|
283
487
|
// src/mdx-plugins/remark-include.ts
|
|
488
|
+
var import_unified = require("unified");
|
|
489
|
+
var import_unist_util_visit2 = require("unist-util-visit");
|
|
490
|
+
var path3 = __toESM(require("path"), 1);
|
|
491
|
+
var fs = __toESM(require("fs/promises"), 1);
|
|
284
492
|
var import_remark_parse = __toESM(require("remark-parse"), 1);
|
|
285
493
|
var import_remark_mdx = __toESM(require("remark-mdx"), 1);
|
|
286
494
|
var import_mdx_plugins = require("fumadocs-core/mdx-plugins");
|
|
@@ -335,7 +543,7 @@ ${e instanceof Error ? e.message : String(e)}`,
|
|
|
335
543
|
{ cause: e }
|
|
336
544
|
);
|
|
337
545
|
}
|
|
338
|
-
const ext =
|
|
546
|
+
const ext = path3.extname(file);
|
|
339
547
|
data._compiler?.addDependency(file);
|
|
340
548
|
if (params.lang || ext !== ".md" && ext !== ".mdx") {
|
|
341
549
|
const lang = params.lang ?? ext.slice(1);
|
|
@@ -361,7 +569,7 @@ ${e instanceof Error ? e.message : String(e)}`,
|
|
|
361
569
|
);
|
|
362
570
|
parsed = extracted;
|
|
363
571
|
}
|
|
364
|
-
await update(parsed,
|
|
572
|
+
await update(parsed, path3.dirname(file), data);
|
|
365
573
|
return parsed;
|
|
366
574
|
}
|
|
367
575
|
async function update(tree, directory, data) {
|
|
@@ -381,7 +589,7 @@ ${e instanceof Error ? e.message : String(e)}`,
|
|
|
381
589
|
}
|
|
382
590
|
}
|
|
383
591
|
const { file: relativePath, section } = parseSpecifier(specifier);
|
|
384
|
-
const file =
|
|
592
|
+
const file = path3.resolve(
|
|
385
593
|
"cwd" in params ? process.cwd() : directory,
|
|
386
594
|
relativePath
|
|
387
595
|
);
|
|
@@ -399,7 +607,7 @@ ${e instanceof Error ? e.message : String(e)}`,
|
|
|
399
607
|
await Promise.all(queue);
|
|
400
608
|
}
|
|
401
609
|
return async (tree, file) => {
|
|
402
|
-
await update(tree,
|
|
610
|
+
await update(tree, path3.dirname(file.path), file.data);
|
|
403
611
|
};
|
|
404
612
|
}
|
|
405
613
|
function getDefaultProcessor(format) {
|
|
@@ -409,12 +617,12 @@ function getDefaultProcessor(format) {
|
|
|
409
617
|
}
|
|
410
618
|
|
|
411
619
|
// src/utils/build-mdx.ts
|
|
412
|
-
var
|
|
620
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
413
621
|
async function buildMDX(cacheKey, source, options) {
|
|
414
622
|
const { filePath, frontmatter, data, _compiler, ...rest } = options;
|
|
415
623
|
function getProcessor(format) {
|
|
416
624
|
const key = `${cacheKey}:${format}`;
|
|
417
|
-
let processor =
|
|
625
|
+
let processor = cache2.get(key);
|
|
418
626
|
if (!processor) {
|
|
419
627
|
processor = (0, import_mdx.createProcessor)({
|
|
420
628
|
outputFormat: "program",
|
|
@@ -422,7 +630,7 @@ async function buildMDX(cacheKey, source, options) {
|
|
|
422
630
|
remarkPlugins: [remarkInclude, ...rest.remarkPlugins ?? []],
|
|
423
631
|
format
|
|
424
632
|
});
|
|
425
|
-
|
|
633
|
+
cache2.set(key, processor);
|
|
426
634
|
}
|
|
427
635
|
return processor;
|
|
428
636
|
}
|
|
@@ -440,262 +648,40 @@ async function buildMDX(cacheKey, source, options) {
|
|
|
440
648
|
});
|
|
441
649
|
}
|
|
442
650
|
|
|
443
|
-
// src/
|
|
444
|
-
var import_node_querystring = require("querystring");
|
|
445
|
-
|
|
446
|
-
// src/utils/count-lines.ts
|
|
447
|
-
function countLines(s) {
|
|
448
|
-
let num = 0;
|
|
449
|
-
for (const c of s) {
|
|
450
|
-
if (c === "\n") num++;
|
|
451
|
-
}
|
|
452
|
-
return num;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// src/utils/validation.ts
|
|
456
|
-
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
457
|
-
var ValidationError = class extends Error {
|
|
458
|
-
constructor(message, issues) {
|
|
459
|
-
super(
|
|
460
|
-
`${message}:
|
|
461
|
-
${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
|
|
462
|
-
);
|
|
463
|
-
this.title = message;
|
|
464
|
-
this.issues = issues;
|
|
465
|
-
}
|
|
466
|
-
toStringFormatted() {
|
|
467
|
-
return [
|
|
468
|
-
import_picocolors.default.bold(`[MDX] ${this.title}:`),
|
|
469
|
-
...this.issues.map(
|
|
470
|
-
(issue) => import_picocolors.default.redBright(
|
|
471
|
-
`- ${import_picocolors.default.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
|
|
472
|
-
)
|
|
473
|
-
)
|
|
474
|
-
].join("\n");
|
|
475
|
-
}
|
|
476
|
-
};
|
|
477
|
-
async function validate(schema, data, context, errorMessage) {
|
|
478
|
-
if (typeof schema === "function" && !("~standard" in schema)) {
|
|
479
|
-
schema = schema(context);
|
|
480
|
-
}
|
|
481
|
-
if ("~standard" in schema) {
|
|
482
|
-
const result = await schema["~standard"].validate(
|
|
483
|
-
data
|
|
484
|
-
);
|
|
485
|
-
if (result.issues) {
|
|
486
|
-
throw new ValidationError(errorMessage, result.issues);
|
|
487
|
-
}
|
|
488
|
-
return result.value;
|
|
489
|
-
}
|
|
490
|
-
return data;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
// src/vite/index.ts
|
|
651
|
+
// src/loaders/mdx.ts
|
|
494
652
|
var import_zod = require("zod");
|
|
495
|
-
var
|
|
496
|
-
var
|
|
497
|
-
var
|
|
498
|
-
|
|
499
|
-
// src/utils/git-timestamp.ts
|
|
500
|
-
var import_node_path = __toESM(require("path"), 1);
|
|
501
|
-
var import_tinyexec = require("tinyexec");
|
|
502
|
-
var cache2 = /* @__PURE__ */ new Map();
|
|
503
|
-
async function getGitTimestamp(file) {
|
|
504
|
-
const cached = cache2.get(file);
|
|
505
|
-
if (cached) return cached;
|
|
506
|
-
try {
|
|
507
|
-
const out = await (0, import_tinyexec.x)(
|
|
508
|
-
"git",
|
|
509
|
-
["log", "-1", '--pretty="%ai"', import_node_path.default.relative(process.cwd(), file)],
|
|
510
|
-
{
|
|
511
|
-
throwOnError: true
|
|
512
|
-
}
|
|
513
|
-
);
|
|
514
|
-
const time = new Date(out.stdout);
|
|
515
|
-
cache2.set(file, time);
|
|
516
|
-
return time;
|
|
517
|
-
} 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);
|
|
542
|
-
}
|
|
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
|
-
}
|
|
548
|
-
|
|
549
|
-
// src/vite/generate-glob.ts
|
|
550
|
-
function generateGlob(name, patterns, globOptions) {
|
|
551
|
-
const options = {
|
|
552
|
-
...globOptions,
|
|
553
|
-
query: {
|
|
554
|
-
...globOptions?.query,
|
|
555
|
-
collection: name
|
|
556
|
-
}
|
|
557
|
-
};
|
|
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
|
-
}
|
|
563
|
-
function enforceRelative(file) {
|
|
564
|
-
if (file.startsWith("./")) return file;
|
|
565
|
-
if (file.startsWith("/")) return `.${file}`;
|
|
566
|
-
return `./${file}`;
|
|
567
|
-
}
|
|
568
|
-
function getGlobBase(collection) {
|
|
569
|
-
let dir = collection.dir;
|
|
570
|
-
if (Array.isArray(dir)) {
|
|
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];
|
|
576
|
-
}
|
|
577
|
-
return enforceRelative(dir);
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// src/utils/collections.ts
|
|
581
|
-
function getSupportedFormats(collection) {
|
|
582
|
-
return {
|
|
583
|
-
doc: ["mdx", "md"],
|
|
584
|
-
meta: ["json", "yaml"]
|
|
585
|
-
}[collection.type];
|
|
586
|
-
}
|
|
587
|
-
function getGlobPatterns(collection) {
|
|
588
|
-
if (collection.files) return collection.files;
|
|
589
|
-
return [`**/*.{${getSupportedFormats(collection).join(",")}}`];
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
// src/vite/generate.ts
|
|
593
|
-
function docs(name, collection) {
|
|
594
|
-
const obj = [
|
|
595
|
-
ident(`doc: ${doc(name, collection.docs)}`),
|
|
596
|
-
ident(`meta: ${meta(name, collection.meta)}`)
|
|
597
|
-
].join(",\n");
|
|
598
|
-
return `{
|
|
599
|
-
${obj}
|
|
600
|
-
}`;
|
|
601
|
-
}
|
|
602
|
-
function doc(name, collection) {
|
|
603
|
-
const patterns = getGlobPatterns(collection);
|
|
604
|
-
const base = getGlobBase(collection);
|
|
605
|
-
const docGlob = generateGlob(name, patterns, {
|
|
606
|
-
base
|
|
607
|
-
});
|
|
608
|
-
if (collection.async) {
|
|
609
|
-
const headBlob = generateGlob(name, patterns, {
|
|
610
|
-
query: {
|
|
611
|
-
only: "frontmatter"
|
|
612
|
-
},
|
|
613
|
-
import: "frontmatter",
|
|
614
|
-
base
|
|
615
|
-
});
|
|
616
|
-
return `create.docLazy("${name}", "${base}", ${headBlob}, ${docGlob})`;
|
|
617
|
-
}
|
|
618
|
-
return `create.doc("${name}", "${base}", ${docGlob})`;
|
|
619
|
-
}
|
|
620
|
-
function meta(name, collection) {
|
|
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
|
-
})})`;
|
|
627
|
-
}
|
|
628
|
-
function entry(configPath, config, outDir, jsExtension) {
|
|
629
|
-
const lines = [
|
|
630
|
-
'/// <reference types="vite/client" />',
|
|
631
|
-
`import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
|
|
632
|
-
`import type * as Config from '${toImportPath(configPath, {
|
|
633
|
-
relativeTo: outDir,
|
|
634
|
-
jsExtension
|
|
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};`);
|
|
650
|
-
}
|
|
651
|
-
return lines.join("\n");
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
// src/vite/index.ts
|
|
655
|
-
var FumadocsDeps = ["fumadocs-core", "fumadocs-ui", "fumadocs-openapi"];
|
|
653
|
+
var import_promises = __toESM(require("fs/promises"), 1);
|
|
654
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
655
|
+
var import_node_crypto = require("crypto");
|
|
656
656
|
var querySchema = import_zod.z.object({
|
|
657
657
|
only: import_zod.z.literal(["frontmatter", "all"]).default("all"),
|
|
658
|
-
collection: import_zod.z.string().optional()
|
|
658
|
+
collection: import_zod.z.string().optional(),
|
|
659
|
+
hash: import_zod.z.string().describe(
|
|
660
|
+
"the hash of config, used for revalidation on Turbopack/Webpack."
|
|
661
|
+
).optional()
|
|
659
662
|
}).loose();
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
case "docs":
|
|
674
|
-
schema = collection.meta.schema;
|
|
675
|
-
break;
|
|
676
|
-
}
|
|
677
|
-
if (!schema) return null;
|
|
678
|
-
let data;
|
|
679
|
-
try {
|
|
680
|
-
data = isJson ? JSON.parse(value) : (0, import_js_yaml2.load)(value);
|
|
681
|
-
} catch {
|
|
682
|
-
return null;
|
|
683
|
-
}
|
|
684
|
-
const out = await validate(
|
|
685
|
-
schema,
|
|
686
|
-
data,
|
|
687
|
-
{ path: path5, source: value },
|
|
688
|
-
`invalid data in ${path5}`
|
|
689
|
-
);
|
|
690
|
-
return {
|
|
691
|
-
code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
|
|
692
|
-
map: null
|
|
693
|
-
};
|
|
694
|
-
}
|
|
695
|
-
async function transformContent(file, query, value) {
|
|
663
|
+
var cacheEntry = import_zod.z.object({
|
|
664
|
+
code: import_zod.z.string(),
|
|
665
|
+
map: import_zod.z.any().optional(),
|
|
666
|
+
hash: import_zod.z.string().optional()
|
|
667
|
+
});
|
|
668
|
+
function createMdxLoader(configLoader) {
|
|
669
|
+
return async ({
|
|
670
|
+
source: value,
|
|
671
|
+
development: isDevelopment,
|
|
672
|
+
query,
|
|
673
|
+
compiler,
|
|
674
|
+
filePath
|
|
675
|
+
}) => {
|
|
696
676
|
const matter = fumaMatter(value);
|
|
697
|
-
const
|
|
698
|
-
const
|
|
677
|
+
const parsed = querySchema.parse(query);
|
|
678
|
+
const loaded = await configLoader.getConfig(parsed.hash);
|
|
679
|
+
const cacheDir = isDevelopment ? void 0 : loaded.global.experimentalBuildCache;
|
|
680
|
+
const cacheKey = `${parsed.hash}_${parsed.collection ?? "global"}_${generateCacheHash(filePath)}`;
|
|
681
|
+
if (cacheDir) {
|
|
682
|
+
const cached = await import_promises.default.readFile(import_node_path3.default.join(cacheDir, cacheKey)).then((content) => cacheEntry.parse(JSON.parse(content.toString()))).catch(() => null);
|
|
683
|
+
if (cached && cached.hash === generateCacheHash(value)) return cached;
|
|
684
|
+
}
|
|
699
685
|
const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
|
|
700
686
|
let schema;
|
|
701
687
|
let mdxOptions;
|
|
@@ -715,9 +701,9 @@ function mdx(config, options = {}) {
|
|
|
715
701
|
matter.data,
|
|
716
702
|
{
|
|
717
703
|
source: value,
|
|
718
|
-
path:
|
|
704
|
+
path: filePath
|
|
719
705
|
},
|
|
720
|
-
`invalid frontmatter in ${
|
|
706
|
+
`invalid frontmatter in ${filePath}`
|
|
721
707
|
);
|
|
722
708
|
}
|
|
723
709
|
if (parsed.only === "frontmatter") {
|
|
@@ -728,30 +714,118 @@ function mdx(config, options = {}) {
|
|
|
728
714
|
}
|
|
729
715
|
const data = {};
|
|
730
716
|
if (loaded.global.lastModifiedTime === "git") {
|
|
731
|
-
data.lastModified = (await getGitTimestamp(
|
|
717
|
+
data.lastModified = (await getGitTimestamp(filePath))?.getTime();
|
|
732
718
|
}
|
|
733
|
-
mdxOptions ??= await loaded.getDefaultMDXOptions();
|
|
734
719
|
const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
|
|
735
720
|
const compiled = await buildMDX(
|
|
736
|
-
parsed.collection ?? "global"
|
|
721
|
+
`${parsed.hash ?? ""}:${parsed.collection ?? "global"}`,
|
|
737
722
|
"\n".repeat(lineOffset) + matter.content,
|
|
738
723
|
{
|
|
739
724
|
development: isDevelopment,
|
|
740
|
-
...mdxOptions,
|
|
725
|
+
...mdxOptions ?? await loaded.getDefaultMDXOptions(),
|
|
741
726
|
data,
|
|
742
|
-
filePath
|
|
727
|
+
filePath,
|
|
743
728
|
frontmatter: matter.data,
|
|
744
|
-
_compiler:
|
|
745
|
-
addDependency: (file2) => {
|
|
746
|
-
this.addWatchFile(file2);
|
|
747
|
-
}
|
|
748
|
-
}
|
|
729
|
+
_compiler: compiler
|
|
749
730
|
}
|
|
750
731
|
);
|
|
751
|
-
|
|
732
|
+
const out = {
|
|
752
733
|
code: String(compiled.value),
|
|
753
734
|
map: compiled.map
|
|
754
735
|
};
|
|
736
|
+
if (cacheDir) {
|
|
737
|
+
await import_promises.default.mkdir(cacheDir, { recursive: true });
|
|
738
|
+
await import_promises.default.writeFile(
|
|
739
|
+
import_node_path3.default.join(cacheDir, cacheKey),
|
|
740
|
+
JSON.stringify({
|
|
741
|
+
...out,
|
|
742
|
+
hash: generateCacheHash(value)
|
|
743
|
+
})
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
return out;
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
function generateCacheHash(input) {
|
|
750
|
+
return (0, import_node_crypto.createHash)("md5").update(input).digest("hex");
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// src/utils/config.ts
|
|
754
|
+
var fs3 = __toESM(require("fs/promises"), 1);
|
|
755
|
+
var path5 = __toESM(require("path"), 1);
|
|
756
|
+
var import_node_url = require("url");
|
|
757
|
+
|
|
758
|
+
// src/loaders/config-loader.ts
|
|
759
|
+
function resolvedConfig(loaded) {
|
|
760
|
+
return {
|
|
761
|
+
getConfig() {
|
|
762
|
+
return loaded;
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// src/loaders/adapter.ts
|
|
768
|
+
var import_node_url2 = require("url");
|
|
769
|
+
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
770
|
+
var import_node_querystring = require("querystring");
|
|
771
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
772
|
+
function toVite(loader) {
|
|
773
|
+
return async function(file, query, value) {
|
|
774
|
+
const result = await loader({
|
|
775
|
+
filePath: file,
|
|
776
|
+
query: (0, import_node_querystring.parse)(query),
|
|
777
|
+
source: value,
|
|
778
|
+
development: this.environment.mode === "dev",
|
|
779
|
+
compiler: {
|
|
780
|
+
addDependency: (file2) => {
|
|
781
|
+
this.addWatchFile(file2);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
return {
|
|
786
|
+
code: result.code,
|
|
787
|
+
map: result.map
|
|
788
|
+
};
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// src/vite/index.ts
|
|
793
|
+
var FumadocsDeps = ["fumadocs-core", "fumadocs-ui", "fumadocs-openapi"];
|
|
794
|
+
function mdx(config, options = {}) {
|
|
795
|
+
const { generateIndexFile = true, configPath = "source.config.ts" } = options;
|
|
796
|
+
const loaded = buildConfig(config);
|
|
797
|
+
const mdxLoader = toVite(createMdxLoader(resolvedConfig(loaded)));
|
|
798
|
+
async function transformMeta(path8, query, value) {
|
|
799
|
+
const isJson = path8.endsWith(".json");
|
|
800
|
+
const parsed = (0, import_node_querystring2.parse)(query);
|
|
801
|
+
const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
|
|
802
|
+
if (!collection) return null;
|
|
803
|
+
let schema;
|
|
804
|
+
switch (collection.type) {
|
|
805
|
+
case "meta":
|
|
806
|
+
schema = collection.schema;
|
|
807
|
+
break;
|
|
808
|
+
case "docs":
|
|
809
|
+
schema = collection.meta.schema;
|
|
810
|
+
break;
|
|
811
|
+
}
|
|
812
|
+
if (!schema) return null;
|
|
813
|
+
let data;
|
|
814
|
+
try {
|
|
815
|
+
data = isJson ? JSON.parse(value) : (0, import_js_yaml2.load)(value);
|
|
816
|
+
} catch {
|
|
817
|
+
return null;
|
|
818
|
+
}
|
|
819
|
+
const out = await validate(
|
|
820
|
+
schema,
|
|
821
|
+
data,
|
|
822
|
+
{ path: path8, source: value },
|
|
823
|
+
`invalid data in ${path8}`
|
|
824
|
+
);
|
|
825
|
+
return {
|
|
826
|
+
code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
|
|
827
|
+
map: null
|
|
828
|
+
};
|
|
755
829
|
}
|
|
756
830
|
return {
|
|
757
831
|
name: "fumadocs-mdx",
|
|
@@ -773,8 +847,8 @@ function mdx(config, options = {}) {
|
|
|
773
847
|
console.log("[Fumadocs MDX] Generating index files");
|
|
774
848
|
const outDir = process.cwd();
|
|
775
849
|
const outFile = "source.generated.ts";
|
|
776
|
-
await
|
|
777
|
-
|
|
850
|
+
await fs5.writeFile(
|
|
851
|
+
path7.join(outDir, outFile),
|
|
778
852
|
entry(
|
|
779
853
|
configPath,
|
|
780
854
|
loaded,
|
|
@@ -785,12 +859,12 @@ function mdx(config, options = {}) {
|
|
|
785
859
|
},
|
|
786
860
|
async transform(value, id) {
|
|
787
861
|
const [file, query = ""] = id.split("?");
|
|
788
|
-
const ext =
|
|
862
|
+
const ext = path7.extname(file);
|
|
789
863
|
try {
|
|
790
864
|
if ([".yaml", ".json"].includes(ext))
|
|
791
865
|
return await transformMeta(file, query, value);
|
|
792
866
|
if ([".md", ".mdx"].includes(ext))
|
|
793
|
-
return await
|
|
867
|
+
return await mdxLoader.call(this, file, query, value);
|
|
794
868
|
} catch (e) {
|
|
795
869
|
if (e instanceof ValidationError) {
|
|
796
870
|
throw new Error(e.toStringFormatted());
|