fumadocs-mdx 11.7.1 → 11.7.3

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.
@@ -1,6 +1,6 @@
1
1
  import { StandardSchemaV1 } from '@standard-schema/spec';
2
2
  import { Source, PageData, MetaData } from 'fumadocs-core/source';
3
- import { D as DocCollection, M as MetaCollection, a as DocsCollection, G as GlobalConfig } from './define-CCrinVBZ.cjs';
3
+ import { a as DocCollection, M as MetaCollection, b as DocsCollection, G as GlobalConfig } from './define-E6TRBwBQ.cjs';
4
4
  import { ProcessorOptions } from '@mdx-js/mdx';
5
5
  import { FC } from 'react';
6
6
  import { MDXProps } from 'mdx/types';
@@ -9,7 +9,7 @@ import { TableOfContents } from 'fumadocs-core/server';
9
9
 
10
10
  interface LoadedConfig {
11
11
  collections: Map<string, DocCollection | MetaCollection | DocsCollection>;
12
- global?: GlobalConfig;
12
+ global: GlobalConfig;
13
13
  getDefaultMDXOptions(): Promise<ProcessorOptions>;
14
14
  }
15
15
 
@@ -168,7 +168,7 @@ module.exports = __toCommonJS(vite_exports);
168
168
  // src/config/build.ts
169
169
  function buildConfig(config) {
170
170
  const collections = /* @__PURE__ */ new Map();
171
- let globalConfig;
171
+ let globalConfig = {};
172
172
  for (const [k, v] of Object.entries(config)) {
173
173
  if (!v) {
174
174
  continue;
@@ -183,34 +183,30 @@ function buildConfig(config) {
183
183
  continue;
184
184
  }
185
185
  }
186
- if (k === "default") {
186
+ if (k === "default" && v) {
187
187
  globalConfig = v;
188
188
  continue;
189
189
  }
190
- return [
191
- `Unknown export "${k}", you can only export collections from source configuration file.`,
192
- null
193
- ];
190
+ throw new Error(
191
+ `Unknown export "${k}", you can only export collections from source configuration file.`
192
+ );
194
193
  }
195
194
  let cachedMdxOptions;
196
- return [
197
- null,
198
- {
199
- global: globalConfig,
200
- collections,
201
- async getDefaultMDXOptions() {
202
- if (cachedMdxOptions) return cachedMdxOptions;
203
- const input = this.global?.mdxOptions;
204
- async function uncached() {
205
- const options = typeof input === "function" ? await input() : input;
206
- const { getDefaultMDXOptions: getDefaultMDXOptions2 } = await Promise.resolve().then(() => (init_mdx_options(), mdx_options_exports));
207
- if (options?.preset === "minimal") return options;
208
- return getDefaultMDXOptions2(options ?? {});
209
- }
210
- return cachedMdxOptions = uncached();
195
+ return {
196
+ global: globalConfig,
197
+ collections,
198
+ async getDefaultMDXOptions() {
199
+ if (cachedMdxOptions) return cachedMdxOptions;
200
+ const input = this.global.mdxOptions;
201
+ async function uncached() {
202
+ const options = typeof input === "function" ? await input() : input;
203
+ const { getDefaultMDXOptions: getDefaultMDXOptions2 } = await Promise.resolve().then(() => (init_mdx_options(), mdx_options_exports));
204
+ if (options?.preset === "minimal") return options;
205
+ return getDefaultMDXOptions2(options ?? {});
211
206
  }
207
+ return cachedMdxOptions = uncached();
212
208
  }
213
- ];
209
+ };
214
210
  }
215
211
 
216
212
  // src/utils/build-mdx.ts
@@ -430,8 +426,8 @@ function ident(code, tab = 1) {
430
426
  }
431
427
 
432
428
  // src/vite/index.ts
433
- var import_promises = __toESM(require("fs/promises"), 1);
434
- var import_node_path2 = __toESM(require("path"), 1);
429
+ var fs2 = __toESM(require("fs/promises"), 1);
430
+ var path4 = __toESM(require("path"), 1);
435
431
  var import_js_yaml2 = require("js-yaml");
436
432
 
437
433
  // src/utils/collections.ts
@@ -446,14 +442,163 @@ function getGlobPatterns(collection) {
446
442
  return [`**/*.{${getSupportedFormats(collection).join(",")}}`];
447
443
  }
448
444
 
445
+ // src/vite/generate-glob.ts
446
+ function generateGlob(name, collection) {
447
+ const patterns = mapGlobPatterns(getGlobPatterns(collection));
448
+ const options = {
449
+ query: {
450
+ collection: name
451
+ },
452
+ base: getGlobBase(collection)
453
+ };
454
+ if (collection.type === "meta") {
455
+ options.import = "default";
456
+ }
457
+ return `import.meta.glob(${JSON.stringify(patterns)}, ${JSON.stringify(options, null, 2)})`;
458
+ }
459
+ function mapGlobPatterns(patterns) {
460
+ return patterns.map((file) => {
461
+ if (file.startsWith("./")) return file;
462
+ if (file.startsWith("/")) return `.${file}`;
463
+ return `./${file}`;
464
+ });
465
+ }
466
+ function getGlobBase(collection) {
467
+ let dir = collection.dir;
468
+ if (Array.isArray(dir)) {
469
+ if (dir.length !== 1)
470
+ throw new Error(
471
+ `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
472
+ );
473
+ dir = dir[0];
474
+ }
475
+ if (!dir.startsWith("./") && !dir.startsWith("/")) {
476
+ return "/" + dir;
477
+ }
478
+ return dir;
479
+ }
480
+
481
+ // src/utils/git-timestamp.ts
482
+ var import_node_path2 = __toESM(require("path"), 1);
483
+ var import_tinyexec = require("tinyexec");
484
+ var cache2 = /* @__PURE__ */ new Map();
485
+ async function getGitTimestamp(file) {
486
+ const cached = cache2.get(file);
487
+ if (cached) return cached;
488
+ try {
489
+ const out = await (0, import_tinyexec.x)(
490
+ "git",
491
+ ["log", "-1", '--pretty="%ai"', import_node_path2.default.relative(process.cwd(), file)],
492
+ {
493
+ throwOnError: true
494
+ }
495
+ );
496
+ const time = new Date(out.stdout);
497
+ cache2.set(file, time);
498
+ return time;
499
+ } catch {
500
+ return;
501
+ }
502
+ }
503
+
449
504
  // src/vite/index.ts
450
- var fileRegex = /\.(md|mdx)$/;
451
505
  var onlySchema = import_zod2.z.literal(["frontmatter", "all"]);
452
506
  function mdx(config, options = {}) {
453
507
  const { generateIndexFile = true, configPath = "source.config.ts" } = options;
454
- const [err, loaded] = buildConfig(config);
455
- if (err || !loaded) {
456
- throw new Error(err);
508
+ const loaded = buildConfig(config);
509
+ async function transformMeta(path5, query, value) {
510
+ const isJson = path5.endsWith(".json");
511
+ const parsed = (0, import_node_querystring.parse)(query);
512
+ const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
513
+ if (!collection) return null;
514
+ let schema;
515
+ switch (collection.type) {
516
+ case "meta":
517
+ schema = collection.schema;
518
+ break;
519
+ case "docs":
520
+ schema = collection.meta.schema;
521
+ break;
522
+ }
523
+ if (!schema) return null;
524
+ let data;
525
+ try {
526
+ data = isJson ? JSON.parse(value) : (0, import_js_yaml2.load)(value);
527
+ } catch {
528
+ return null;
529
+ }
530
+ const out = await validate(
531
+ schema,
532
+ data,
533
+ { path: path5, source: value },
534
+ `invalid data in ${path5}`
535
+ );
536
+ return {
537
+ code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
538
+ map: null
539
+ };
540
+ }
541
+ async function transformContent(file, query, value) {
542
+ const matter = fumaMatter(value);
543
+ const isDevelopment = this.environment.mode === "dev";
544
+ const parsed = (0, import_node_querystring.parse)(query);
545
+ const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
546
+ const only = parsed.only ? onlySchema.parse(parsed.only) : "all";
547
+ let schema;
548
+ let mdxOptions;
549
+ switch (collection?.type) {
550
+ case "doc":
551
+ mdxOptions = collection.mdxOptions;
552
+ schema = collection.schema;
553
+ break;
554
+ case "docs":
555
+ mdxOptions = collection.docs.mdxOptions;
556
+ schema = collection.docs.schema;
557
+ break;
558
+ }
559
+ if (schema) {
560
+ matter.data = await validate(
561
+ schema,
562
+ matter.data,
563
+ {
564
+ source: value,
565
+ path: file
566
+ },
567
+ `invalid frontmatter in ${file}`
568
+ );
569
+ }
570
+ if (only === "frontmatter") {
571
+ return {
572
+ code: `export const frontmatter = ${JSON.stringify(matter.data)}`,
573
+ map: null
574
+ };
575
+ }
576
+ const data = {};
577
+ if (loaded.global.lastModifiedTime === "git") {
578
+ data.lastModified = (await getGitTimestamp(file))?.getTime();
579
+ }
580
+ mdxOptions ??= await loaded.getDefaultMDXOptions();
581
+ const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
582
+ const compiled = await buildMDX(
583
+ parsed.collection ?? "global",
584
+ "\n".repeat(lineOffset) + matter.content,
585
+ {
586
+ development: isDevelopment,
587
+ ...mdxOptions,
588
+ data,
589
+ filePath: file,
590
+ frontmatter: matter.data,
591
+ _compiler: {
592
+ addDependency: (file2) => {
593
+ this.addWatchFile(file2);
594
+ }
595
+ }
596
+ }
597
+ );
598
+ return {
599
+ code: String(compiled.value),
600
+ map: compiled.map
601
+ };
457
602
  }
458
603
  return {
459
604
  name: "fumadocs-mdx",
@@ -465,6 +610,7 @@ function mdx(config, options = {}) {
465
610
  const outdir = process.cwd();
466
611
  const outFile = "source.generated.ts";
467
612
  const lines = [
613
+ '/// <reference types="vite/client" />',
468
614
  `import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
469
615
  `import type * as Config from '${toImportPath(configPath, {
470
616
  relativeTo: outdir
@@ -497,139 +643,22 @@ ${args}
497
643
  lines.push(doc(name, collection));
498
644
  }
499
645
  }
500
- await import_promises.default.writeFile(import_node_path2.default.join(outdir, outFile), lines.join("\n"));
646
+ await fs2.writeFile(path4.join(outdir, outFile), lines.join("\n"));
501
647
  },
502
648
  async transform(value, id) {
503
- const [path4, query = ""] = id.split("?");
504
- const isJson = path4.endsWith(".json");
505
- const isYaml = path4.endsWith(".yaml");
506
- if (isJson || isYaml) {
507
- const parsed2 = (0, import_node_querystring.parse)(query);
508
- const collection2 = parsed2.collection ? loaded.collections.get(parsed2.collection) : void 0;
509
- if (!collection2) return null;
510
- let schema2;
511
- switch (collection2.type) {
512
- case "meta":
513
- schema2 = collection2.schema;
514
- break;
515
- case "docs":
516
- schema2 = collection2.meta.schema;
517
- break;
518
- }
519
- if (!schema2) return null;
520
- let data;
521
- try {
522
- data = isJson ? JSON.parse(value) : (0, import_js_yaml2.load)(value);
523
- } catch {
524
- return null;
525
- }
526
- const out = await validate(
527
- schema2,
528
- data,
529
- { path: path4, source: value },
530
- `invalid data in ${path4}`
531
- );
532
- return {
533
- code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
534
- map: null
535
- };
536
- }
537
- if (!fileRegex.test(path4)) return;
538
- const matter = fumaMatter(value);
539
- const isDevelopment = this.environment.mode === "dev";
540
- const parsed = (0, import_node_querystring.parse)(query);
541
- const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
542
- const only = parsed.only ? onlySchema.parse(parsed.only) : "all";
543
- let schema;
544
- let mdxOptions;
545
- switch (collection?.type) {
546
- case "doc":
547
- mdxOptions = collection.mdxOptions;
548
- schema = collection.schema;
549
- break;
550
- case "docs":
551
- mdxOptions = collection.docs.mdxOptions;
552
- schema = collection.docs.schema;
553
- break;
554
- }
555
- if (schema) {
556
- try {
557
- matter.data = await validate(
558
- schema,
559
- matter.data,
560
- {
561
- source: value,
562
- path: path4
563
- },
564
- `invalid frontmatter in ${path4}`
565
- );
566
- } catch (e) {
567
- if (e instanceof ValidationError) {
568
- throw new Error(e.toStringFormatted());
569
- }
570
- throw e;
649
+ const [file, query = ""] = id.split("?");
650
+ const ext = path4.extname(file);
651
+ try {
652
+ if ([".yaml", ".json"].includes(ext))
653
+ return await transformMeta(file, query, value);
654
+ if ([".md", ".mdx"].includes(ext))
655
+ return await transformContent.call(this, file, query, value);
656
+ } catch (e) {
657
+ if (e instanceof ValidationError) {
658
+ throw new Error(e.toStringFormatted());
571
659
  }
660
+ throw e;
572
661
  }
573
- if (only === "frontmatter") {
574
- return {
575
- code: `export const frontmatter = ${JSON.stringify(matter.data)}`
576
- };
577
- }
578
- mdxOptions ??= await loaded.getDefaultMDXOptions();
579
- const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
580
- const file = await buildMDX(
581
- parsed.collection ?? "global",
582
- "\n".repeat(lineOffset) + matter.content,
583
- {
584
- development: isDevelopment,
585
- ...mdxOptions,
586
- filePath: path4,
587
- frontmatter: matter.data,
588
- _compiler: {
589
- addDependency: (file2) => {
590
- this.addWatchFile(file2);
591
- }
592
- }
593
- }
594
- );
595
- return {
596
- code: String(file.value),
597
- map: file.map
598
- };
599
662
  }
600
663
  };
601
664
  }
602
- function generateGlob(name, collection) {
603
- const patterns = mapGlobPatterns(getGlobPatterns(collection));
604
- const options = {
605
- query: {
606
- collection: name
607
- },
608
- base: getGlobBase(collection)
609
- };
610
- if (collection.type === "meta") {
611
- options.import = "default";
612
- }
613
- return `import.meta.glob(${JSON.stringify(patterns)}, ${JSON.stringify(options, null, 2)})`;
614
- }
615
- function mapGlobPatterns(patterns) {
616
- return patterns.map((file) => {
617
- if (file.startsWith("./")) return file;
618
- if (file.startsWith("/")) return `.${file}`;
619
- return `./${file}`;
620
- });
621
- }
622
- function getGlobBase(collection) {
623
- let dir = collection.dir;
624
- if (Array.isArray(dir)) {
625
- if (dir.length !== 1)
626
- throw new Error(
627
- `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
628
- );
629
- dir = dir[0];
630
- }
631
- if (!dir.startsWith("./") && !dir.startsWith("/")) {
632
- return "/" + dir;
633
- }
634
- return dir;
635
- }