fumadocs-mdx 11.10.0 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/bin.cjs +953 -0
  2. package/dist/bin.d.cts +1 -0
  3. package/dist/bin.d.ts +1 -0
  4. package/dist/bin.js +16 -0
  5. package/dist/{browser-B2G8uAF2.d.cts → browser-D5lvL8vv.d.ts} +51 -4
  6. package/dist/{browser-DrH7tKRi.d.ts → browser-DjWADqp8.d.cts} +51 -4
  7. package/dist/bun/index.cjs +129 -109
  8. package/dist/bun/index.js +9 -6
  9. package/dist/chunk-3M4SHY6K.js +80 -0
  10. package/dist/chunk-6Y5JDZHD.js +65 -0
  11. package/dist/{chunk-NUDEC6C5.js → chunk-AUOOMFAI.js} +28 -22
  12. package/dist/chunk-IQAEAI4P.js +66 -0
  13. package/dist/{chunk-5XJM5RPV.js → chunk-KGUBBRL6.js} +13 -13
  14. package/dist/{chunk-SVTXMVLQ.js → chunk-KTDVTBMH.js} +1 -1
  15. package/dist/chunk-POXTQZ4D.js +60 -0
  16. package/dist/chunk-SWNOXPYJ.js +142 -0
  17. package/dist/{chunk-COQ4VMK2.js → chunk-TLD6JMT6.js} +28 -61
  18. package/dist/{chunk-NVX3U5YE.js → chunk-VXEBLM4X.js} +2 -2
  19. package/dist/{chunk-QVZ7JH4H.js → chunk-YC25YEBF.js} +1 -1
  20. package/dist/chunk-ZLCSVXCD.js +10 -0
  21. package/dist/config/index.cjs +18 -97
  22. package/dist/config/index.d.cts +1 -1
  23. package/dist/config/index.d.ts +1 -1
  24. package/dist/config/index.js +48 -9
  25. package/dist/{define-BH4bnHQl.d.cts → define--6HQ1ehX.d.cts} +18 -3
  26. package/dist/{define-BH4bnHQl.d.ts → define--6HQ1ehX.d.ts} +18 -3
  27. package/dist/loader-mdx.cjs +127 -139
  28. package/dist/loader-mdx.js +7 -6
  29. package/dist/next/index.cjs +44 -269
  30. package/dist/next/index.js +30 -46
  31. package/dist/node/loader.cjs +131 -143
  32. package/dist/node/loader.js +7 -6
  33. package/dist/postinstall-U7VROOY7.js +9 -0
  34. package/dist/{mdx-options-T73E4LQB.js → preset-WFEORCAB.js} +1 -1
  35. package/dist/runtime/{async.cjs → next/async.cjs} +202 -154
  36. package/dist/runtime/{async.d.cts → next/async.d.cts} +3 -3
  37. package/dist/runtime/{async.d.ts → next/async.d.ts} +3 -3
  38. package/dist/runtime/next/async.js +92 -0
  39. package/dist/{index.cjs → runtime/next/index.cjs} +35 -26
  40. package/dist/runtime/next/index.d.cts +30 -0
  41. package/dist/runtime/next/index.d.ts +30 -0
  42. package/dist/{index.js → runtime/next/index.js} +2 -1
  43. package/dist/runtime/vite/browser.d.cts +2 -3
  44. package/dist/runtime/vite/browser.d.ts +2 -3
  45. package/dist/runtime/vite/server.cjs +67 -21
  46. package/dist/runtime/vite/server.d.cts +14 -28
  47. package/dist/runtime/vite/server.d.ts +14 -28
  48. package/dist/runtime/vite/server.js +61 -21
  49. package/dist/shared-0QIuV0XZ.d.ts +70 -0
  50. package/dist/shared-CqgMnt9h.d.cts +70 -0
  51. package/dist/{types-DN9KrG7R.d.ts → types-DLIAvrgC.d.ts} +6 -32
  52. package/dist/{types-DT83Ijs6.d.cts → types-Dl8HLbm5.d.cts} +6 -32
  53. package/dist/vite/index.cjs +201 -123
  54. package/dist/vite/index.d.cts +4 -1
  55. package/dist/vite/index.d.ts +4 -1
  56. package/dist/vite/index.js +13 -9
  57. package/package.json +11 -17
  58. package/bin.js +0 -5
  59. package/dist/build-mdx-DnC1jKvn.d.cts +0 -46
  60. package/dist/build-mdx-DnC1jKvn.d.ts +0 -46
  61. package/dist/chunk-2HKRTQYP.js +0 -154
  62. package/dist/chunk-GBMFGEC7.js +0 -57
  63. package/dist/chunk-QQWCBFFE.js +0 -40
  64. package/dist/chunk-SMSNZ6N5.js +0 -155
  65. package/dist/config/zod-3.cjs +0 -422
  66. package/dist/config/zod-3.d.cts +0 -53
  67. package/dist/config/zod-3.d.ts +0 -53
  68. package/dist/config/zod-3.js +0 -40
  69. package/dist/index.d.cts +0 -26
  70. package/dist/index.d.ts +0 -26
  71. package/dist/runtime/async.js +0 -72
@@ -1,23 +1,29 @@
1
- // src/runtime/index.ts
2
- import fs from "fs";
3
- var cache = /* @__PURE__ */ new Map();
1
+ import {
2
+ missingProcessedMarkdown
3
+ } from "./chunk-ZLCSVXCD.js";
4
+
5
+ // src/runtime/next/index.ts
6
+ import * as fs from "fs/promises";
4
7
  var _runtime = {
5
8
  doc(files) {
6
9
  return files.map((file) => {
7
- const { default: body, frontmatter, ...exports } = file.data;
10
+ const data = file.data;
11
+ const filePath = file.info.fullPath;
8
12
  return {
9
- body,
10
- ...exports,
11
- ...frontmatter,
12
- _file: file.info,
13
- _exports: file.data,
14
- get content() {
15
- const path = this._file.absolutePath;
16
- const cached = cache.get(path);
17
- if (cached) return cached;
18
- const content = fs.readFileSync(path).toString();
19
- cache.set(path, content);
20
- return content;
13
+ info: file.info,
14
+ _exports: data,
15
+ body: data.default,
16
+ lastModified: data.lastModified,
17
+ toc: data.toc,
18
+ structuredData: data.structuredData,
19
+ extractedReferences: data.extractedReferences,
20
+ ...data.frontmatter,
21
+ async getText(type) {
22
+ if (type === "raw") {
23
+ return (await fs.readFile(filePath)).toString();
24
+ }
25
+ if (typeof data._markdown !== "string") missingProcessedMarkdown();
26
+ return data._markdown;
21
27
  }
22
28
  };
23
29
  });
@@ -25,8 +31,8 @@ var _runtime = {
25
31
  meta(files) {
26
32
  return files.map((file) => {
27
33
  return {
28
- ...file.data,
29
- _file: file.info
34
+ info: file.info,
35
+ ...file.data
30
36
  };
31
37
  });
32
38
  },
@@ -55,16 +61,16 @@ function resolveFiles({ docs, meta }) {
55
61
  for (const entry of docs) {
56
62
  outputs.push({
57
63
  type: "page",
58
- absolutePath: entry._file.absolutePath,
59
- path: entry._file.path,
64
+ absolutePath: entry.info.fullPath,
65
+ path: entry.info.path,
60
66
  data: entry
61
67
  });
62
68
  }
63
69
  for (const entry of meta) {
64
70
  outputs.push({
65
71
  type: "meta",
66
- absolutePath: entry._file.absolutePath,
67
- path: entry._file.path,
72
+ absolutePath: entry.info.fullPath,
73
+ path: entry.info.path,
68
74
  data: entry
69
75
  });
70
76
  }
@@ -0,0 +1,66 @@
1
+ // src/utils/validation.ts
2
+ import picocolors from "picocolors";
3
+ var ValidationError = class extends Error {
4
+ constructor(message, issues) {
5
+ super(
6
+ `${message}:
7
+ ${issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n")}`
8
+ );
9
+ this.title = message;
10
+ this.issues = issues;
11
+ }
12
+ toStringFormatted() {
13
+ return [
14
+ picocolors.bold(`[MDX] ${this.title}:`),
15
+ ...this.issues.map(
16
+ (issue) => picocolors.redBright(
17
+ `- ${picocolors.bold(issue.path?.join(".") ?? "*")}: ${issue.message}`
18
+ )
19
+ )
20
+ ].join("\n");
21
+ }
22
+ };
23
+ async function validate(schema, data, context, errorMessage) {
24
+ if (typeof schema === "function" && !("~standard" in schema)) {
25
+ schema = schema(context);
26
+ }
27
+ if ("~standard" in schema) {
28
+ const result = await schema["~standard"].validate(
29
+ data
30
+ );
31
+ if (result.issues) {
32
+ throw new ValidationError(errorMessage, result.issues);
33
+ }
34
+ return result.value;
35
+ }
36
+ return data;
37
+ }
38
+
39
+ // src/utils/git-timestamp.ts
40
+ import path from "path";
41
+ import { x } from "tinyexec";
42
+ var cache = /* @__PURE__ */ new Map();
43
+ async function getGitTimestamp(file) {
44
+ const cached = cache.get(file);
45
+ if (cached) return cached;
46
+ try {
47
+ const out = await x(
48
+ "git",
49
+ ["log", "-1", '--pretty="%ai"', path.relative(process.cwd(), file)],
50
+ {
51
+ throwOnError: true
52
+ }
53
+ );
54
+ const time = new Date(out.stdout);
55
+ cache.set(file, time);
56
+ return time;
57
+ } catch {
58
+ return;
59
+ }
60
+ }
61
+
62
+ export {
63
+ ValidationError,
64
+ validate,
65
+ getGitTimestamp
66
+ };
@@ -1,12 +1,14 @@
1
1
  import {
2
- getConfigHash,
3
2
  getGitTimestamp,
4
- loadConfig,
5
3
  validate
6
- } from "./chunk-2HKRTQYP.js";
4
+ } from "./chunk-IQAEAI4P.js";
5
+ import {
6
+ getConfigHash,
7
+ loadConfig
8
+ } from "./chunk-POXTQZ4D.js";
7
9
  import {
8
10
  buildMDX
9
- } from "./chunk-QQWCBFFE.js";
11
+ } from "./chunk-SWNOXPYJ.js";
10
12
  import {
11
13
  fumaMatter
12
14
  } from "./chunk-VWJKRQZR.js";
@@ -55,21 +57,18 @@ function createMdxLoader(configLoader) {
55
57
  if (cached && cached.hash === generateCacheHash(value)) return cached;
56
58
  }
57
59
  const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
58
- let schema;
59
- let mdxOptions;
60
+ let docCollection;
60
61
  switch (collection?.type) {
61
62
  case "doc":
62
- mdxOptions = collection.mdxOptions;
63
- schema = collection.schema;
63
+ docCollection = collection;
64
64
  break;
65
65
  case "docs":
66
- mdxOptions = collection.docs.mdxOptions;
67
- schema = collection.docs.schema;
66
+ docCollection = collection.docs;
68
67
  break;
69
68
  }
70
- if (schema) {
69
+ if (docCollection?.schema) {
71
70
  matter.data = await validate(
72
- schema,
71
+ docCollection.schema,
73
72
  matter.data,
74
73
  {
75
74
  source: value,
@@ -94,7 +93,8 @@ function createMdxLoader(configLoader) {
94
93
  "\n".repeat(lineOffset) + matter.content,
95
94
  {
96
95
  development: isDevelopment,
97
- ...mdxOptions ?? await loaded.getDefaultMDXOptions(),
96
+ ...docCollection?.mdxOptions ?? await loaded.getDefaultMDXOptions(),
97
+ postprocess: docCollection?.postprocess,
98
98
  data,
99
99
  filePath,
100
100
  frontmatter: matter.data,
@@ -2,7 +2,7 @@ import {
2
2
  fumaMatter
3
3
  } from "./chunk-VWJKRQZR.js";
4
4
 
5
- // src/mdx-plugins/remark-include.ts
5
+ // src/mdx/remark-include.ts
6
6
  import { unified } from "unified";
7
7
  import { visit } from "unist-util-visit";
8
8
  import * as path from "path";
@@ -0,0 +1,60 @@
1
+ import {
2
+ buildConfig
3
+ } from "./chunk-YC25YEBF.js";
4
+
5
+ // src/utils/config.ts
6
+ import * as fs from "fs/promises";
7
+ import * as path from "path";
8
+ import { pathToFileURL } from "url";
9
+ function findConfigFile() {
10
+ return path.resolve("source.config.ts");
11
+ }
12
+ var cache = null;
13
+ async function compileConfig(configPath, outDir) {
14
+ const { build } = await import("esbuild");
15
+ const transformed = await build({
16
+ entryPoints: [{ in: configPath, out: "source.config" }],
17
+ bundle: true,
18
+ outdir: outDir,
19
+ target: "node20",
20
+ write: true,
21
+ platform: "node",
22
+ format: "esm",
23
+ packages: "external",
24
+ outExtension: {
25
+ ".js": ".mjs"
26
+ },
27
+ allowOverwrite: true
28
+ });
29
+ if (transformed.errors.length > 0) {
30
+ throw new Error("failed to compile configuration file");
31
+ }
32
+ }
33
+ async function loadConfig(configPath, outDir, hash, build = false) {
34
+ if (cache && cache.hash === hash) {
35
+ return await cache.config;
36
+ }
37
+ if (build) await compileConfig(configPath, outDir);
38
+ const url = pathToFileURL(path.resolve(outDir, "source.config.mjs"));
39
+ const config = import(`${url.href}?hash=${hash}`).then((loaded) => {
40
+ return buildConfig(
41
+ // every call to `loadConfig` will cause the previous cache to be ignored
42
+ loaded
43
+ );
44
+ });
45
+ if (hash) cache = { config, hash };
46
+ return await config;
47
+ }
48
+ async function getConfigHash(configPath) {
49
+ const stats = await fs.stat(configPath).catch(() => void 0);
50
+ if (stats) {
51
+ return stats.mtime.getTime().toString();
52
+ }
53
+ throw new Error("Cannot find config file");
54
+ }
55
+
56
+ export {
57
+ findConfigFile,
58
+ loadConfig,
59
+ getConfigHash
60
+ };
@@ -0,0 +1,142 @@
1
+ import {
2
+ remarkInclude
3
+ } from "./chunk-KTDVTBMH.js";
4
+
5
+ // src/mdx/build-mdx.ts
6
+ import { createProcessor } from "@mdx-js/mdx";
7
+
8
+ // src/mdx/remark-postprocess.ts
9
+ import { visit } from "unist-util-visit";
10
+ import { toMarkdown } from "mdast-util-to-markdown";
11
+ import { valueToEstree } from "estree-util-value-to-estree";
12
+ function remarkPostprocess({
13
+ includeProcessedMarkdown = false,
14
+ valueToExport = []
15
+ } = {}) {
16
+ return (tree, file) => {
17
+ let title;
18
+ const urls = [];
19
+ visit(tree, ["heading", "link"], (node) => {
20
+ if (node.type === "heading" && node.depth === 1) {
21
+ title = flattenNode(node);
22
+ }
23
+ if (node.type !== "link") return;
24
+ urls.push({
25
+ href: node.url
26
+ });
27
+ return "skip";
28
+ });
29
+ if (title) {
30
+ file.data.frontmatter ??= {};
31
+ if (!file.data.frontmatter.title) file.data.frontmatter.title = title;
32
+ }
33
+ file.data.extractedReferences = urls;
34
+ if (includeProcessedMarkdown) {
35
+ file.data._markdown = toMarkdown(tree, {
36
+ ...this.data("settings"),
37
+ // @ts-expect-error - from https://github.com/remarkjs/remark/blob/main/packages/remark-stringify/lib/index.js
38
+ extensions: this.data("toMarkdownExtensions") || []
39
+ });
40
+ }
41
+ for (const { name, value } of file.data["mdx-export"] ?? []) {
42
+ tree.children.unshift(getMdastExport(name, value));
43
+ }
44
+ for (const name of valueToExport) {
45
+ if (!(name in file.data)) continue;
46
+ tree.children.unshift(getMdastExport(name, file.data[name]));
47
+ }
48
+ };
49
+ }
50
+ function getMdastExport(name, value) {
51
+ return {
52
+ type: "mdxjsEsm",
53
+ value: "",
54
+ data: {
55
+ estree: {
56
+ type: "Program",
57
+ sourceType: "module",
58
+ body: [
59
+ {
60
+ type: "ExportNamedDeclaration",
61
+ attributes: [],
62
+ specifiers: [],
63
+ source: null,
64
+ declaration: {
65
+ type: "VariableDeclaration",
66
+ kind: "let",
67
+ declarations: [
68
+ {
69
+ type: "VariableDeclarator",
70
+ id: {
71
+ type: "Identifier",
72
+ name
73
+ },
74
+ init: valueToEstree(value)
75
+ }
76
+ ]
77
+ }
78
+ }
79
+ ]
80
+ }
81
+ }
82
+ };
83
+ }
84
+ function flattenNode(node) {
85
+ if ("children" in node)
86
+ return node.children.map((child) => flattenNode(child)).join("");
87
+ if ("value" in node) return node.value;
88
+ return "";
89
+ }
90
+
91
+ // src/mdx/build-mdx.ts
92
+ var cache = /* @__PURE__ */ new Map();
93
+ async function buildMDX(cacheKey, source, options) {
94
+ const { filePath, frontmatter, data, _compiler, ...rest } = options;
95
+ function getProcessor(format) {
96
+ const key = `${cacheKey}:${format}`;
97
+ let processor = cache.get(key);
98
+ if (!processor) {
99
+ processor = createProcessor({
100
+ outputFormat: "program",
101
+ ...rest,
102
+ remarkPlugins: [
103
+ remarkInclude,
104
+ ...rest.remarkPlugins ?? [],
105
+ [
106
+ remarkPostprocess,
107
+ {
108
+ ...options.postprocess,
109
+ valueToExport: [
110
+ ...options.postprocess?.valueToExport ?? [],
111
+ "structuredData",
112
+ "extractedReferences",
113
+ "frontmatter",
114
+ "lastModified",
115
+ "_markdown"
116
+ ]
117
+ }
118
+ ]
119
+ ],
120
+ format
121
+ });
122
+ cache.set(key, processor);
123
+ }
124
+ return processor;
125
+ }
126
+ return getProcessor(
127
+ options.format ?? filePath.endsWith(".mdx") ? "mdx" : "md"
128
+ ).process({
129
+ value: source,
130
+ path: filePath,
131
+ data: {
132
+ ...data,
133
+ frontmatter,
134
+ _compiler,
135
+ _getProcessor: getProcessor
136
+ }
137
+ });
138
+ }
139
+
140
+ export {
141
+ buildMDX
142
+ };
@@ -1,42 +1,16 @@
1
- // src/utils/import-formatter.ts
1
+ import {
2
+ getGlobPatterns,
3
+ ident,
4
+ toImportPath
5
+ } from "./chunk-6Y5JDZHD.js";
6
+ import {
7
+ findConfigFile,
8
+ loadConfig
9
+ } from "./chunk-POXTQZ4D.js";
10
+
11
+ // src/vite/postinstall.ts
12
+ import fs from "fs/promises";
2
13
  import path from "path";
3
- function getImportCode(info) {
4
- const specifier = JSON.stringify(info.specifier);
5
- if (info.type === "default") return `import ${info.name} from ${specifier}`;
6
- if (info.type === "namespace")
7
- return `import * as ${info.name} from ${specifier}`;
8
- if (info.type === "named") {
9
- const names = info.names.map(
10
- (name) => Array.isArray(name) ? `${name[0]} as ${name[1]}` : name
11
- );
12
- return `import { ${names.join(", ")} } from ${specifier}`;
13
- }
14
- return `import ${specifier}`;
15
- }
16
- function toImportPath(file, config) {
17
- const ext = path.extname(file);
18
- let filename;
19
- if (ext === ".ts" && config.jsExtension) {
20
- filename = file.substring(0, file.length - ext.length) + ".js";
21
- } else if (ext === ".ts") {
22
- filename = file.substring(0, file.length - ext.length);
23
- } else {
24
- filename = file;
25
- }
26
- let importPath;
27
- if ("relativeTo" in config) {
28
- importPath = path.relative(config.relativeTo, filename);
29
- if (!path.isAbsolute(importPath) && !importPath.startsWith(".")) {
30
- importPath = `./${importPath}`;
31
- }
32
- } else {
33
- importPath = path.resolve(filename);
34
- }
35
- return importPath.replaceAll(path.sep, "/");
36
- }
37
- function ident(code, tab = 1) {
38
- return code.split("\n").map((v) => " ".repeat(tab) + v).join("\n");
39
- }
40
14
 
41
15
  // src/vite/generate-glob.ts
42
16
  function generateGlob(name, patterns, globOptions) {
@@ -69,24 +43,6 @@ function getGlobBase(collection) {
69
43
  return enforceRelative(dir);
70
44
  }
71
45
 
72
- // src/utils/collections.ts
73
- function getSupportedFormats(collection) {
74
- return {
75
- doc: ["mdx", "md"],
76
- meta: ["json", "yaml"]
77
- }[collection.type];
78
- }
79
- function getGlobPatterns(collection) {
80
- if (collection.files) return collection.files;
81
- return [`**/*.{${getSupportedFormats(collection).join(",")}}`];
82
- }
83
- function isFileSupported(filePath, collection) {
84
- for (const format of getSupportedFormats(collection)) {
85
- if (filePath.endsWith(`.${format}`)) return true;
86
- }
87
- return false;
88
- }
89
-
90
46
  // src/vite/generate.ts
91
47
  function docs(name, collection) {
92
48
  const obj = [
@@ -149,10 +105,21 @@ function entry(configPath, config, outDir, jsExtension) {
149
105
  return lines.join("\n");
150
106
  }
151
107
 
108
+ // src/vite/postinstall.ts
109
+ async function postInstall(configPath = findConfigFile(), outDir, addJsExtension = false) {
110
+ const config = await loadConfig(configPath, "node_modules", void 0, true);
111
+ const outFile = "source.generated.ts";
112
+ if (outDir) {
113
+ await fs.mkdir(outDir, { recursive: true });
114
+ }
115
+ await fs.writeFile(
116
+ outDir ? path.join(outDir, outFile) : outFile,
117
+ entry(configPath, config, outDir ?? process.cwd(), addJsExtension)
118
+ );
119
+ console.log("[MDX] types generated");
120
+ }
121
+
152
122
  export {
153
- getImportCode,
154
- toImportPath,
155
- getGlobPatterns,
156
- isFileSupported,
157
- entry
123
+ entry,
124
+ postInstall
158
125
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ValidationError
3
- } from "./chunk-2HKRTQYP.js";
3
+ } from "./chunk-IQAEAI4P.js";
4
4
 
5
5
  // src/loaders/adapter.ts
6
6
  import { fileURLToPath } from "url";
@@ -57,7 +57,7 @@ function toWebpack(loader) {
57
57
  try {
58
58
  const result = await loader({
59
59
  filePath: this.resourcePath,
60
- query: parse(this.resourceQuery),
60
+ query: parse(this.resourceQuery.slice(1)),
61
61
  source,
62
62
  development: this.mode === "development",
63
63
  compiler: this
@@ -34,7 +34,7 @@ function buildConfig(config) {
34
34
  const input = this.global.mdxOptions;
35
35
  async function uncached() {
36
36
  const options = typeof input === "function" ? await input() : input;
37
- const { getDefaultMDXOptions } = await import("./mdx-options-T73E4LQB.js");
37
+ const { getDefaultMDXOptions } = await import("./preset-WFEORCAB.js");
38
38
  if (options?.preset === "minimal") return options;
39
39
  return getDefaultMDXOptions({
40
40
  ...options,
@@ -0,0 +1,10 @@
1
+ // src/runtime/shared.ts
2
+ function missingProcessedMarkdown() {
3
+ throw new Error(
4
+ "getText('processed') requires `includeProcessedMarkdown` to be enabled in your collection config."
5
+ );
6
+ }
7
+
8
+ export {
9
+ missingProcessedMarkdown
10
+ };