fumadocs-mdx 11.6.11 → 11.7.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 (34) hide show
  1. package/dist/{chunk-64MMPGML.js → chunk-2CSSQTP6.js} +1 -10
  2. package/dist/{chunk-SXOJYWZ3.js → chunk-2KBRPMAM.js} +1 -1
  3. package/dist/{chunk-6PDS7MUA.js → chunk-C5INPAZJ.js} +4 -4
  4. package/dist/{chunk-DRVUBK5B.js → chunk-GWR7KMRU.js} +13 -1
  5. package/dist/chunk-JPPCALFT.js +34 -0
  6. package/dist/{chunk-22SBT5SQ.js → chunk-ZOWJF3OH.js} +6 -6
  7. package/dist/config/index.cjs +5 -18
  8. package/dist/config/index.d.cts +3 -7
  9. package/dist/config/index.d.ts +3 -7
  10. package/dist/config/index.js +8 -12
  11. package/dist/{types-DVeuYiq5.d.cts → define-CCrinVBZ.d.cts} +37 -119
  12. package/dist/{types-DVeuYiq5.d.ts → define-CCrinVBZ.d.ts} +37 -119
  13. package/dist/index.d.cts +6 -7
  14. package/dist/index.d.ts +6 -7
  15. package/dist/loader-mdx.cjs +155 -134
  16. package/dist/loader-mdx.js +7 -10
  17. package/dist/mdx-options-UDV5WEFU.js +6 -0
  18. package/dist/next/index.cjs +196 -53
  19. package/dist/next/index.js +7 -30
  20. package/dist/runtime/async.cjs +167 -15
  21. package/dist/runtime/async.d.cts +5 -6
  22. package/dist/runtime/async.d.ts +5 -6
  23. package/dist/runtime/async.js +24 -15
  24. package/dist/runtime/vite.cjs +116 -0
  25. package/dist/runtime/vite.d.cts +47 -0
  26. package/dist/runtime/vite.d.ts +47 -0
  27. package/dist/runtime/vite.js +90 -0
  28. package/dist/{types-HIdjlLo0.d.ts → types-C0bKwtAx.d.ts} +38 -50
  29. package/dist/{types-BcUhOIxN.d.cts → types-CnslxmoO.d.cts} +38 -50
  30. package/dist/vite/index.cjs +384 -137
  31. package/dist/vite/index.d.cts +12 -3
  32. package/dist/vite/index.d.ts +12 -3
  33. package/dist/vite/index.js +176 -20
  34. package/package.json +19 -9
@@ -1,13 +1,17 @@
1
1
  import {
2
2
  buildMDX,
3
3
  countLines
4
- } from "../chunk-6PDS7MUA.js";
4
+ } from "../chunk-C5INPAZJ.js";
5
+ import {
6
+ toImportPath
7
+ } from "../chunk-JPPCALFT.js";
5
8
  import {
6
9
  buildConfig
7
- } from "../chunk-DRVUBK5B.js";
10
+ } from "../chunk-GWR7KMRU.js";
8
11
  import {
9
- loadDefaultOptions
10
- } from "../chunk-64MMPGML.js";
12
+ ValidationError,
13
+ validate
14
+ } from "../chunk-ZOWJF3OH.js";
11
15
  import "../chunk-AVMO2SRO.js";
12
16
  import {
13
17
  fumaMatter
@@ -15,43 +19,194 @@ import {
15
19
 
16
20
  // src/vite/index.ts
17
21
  import { parse } from "querystring";
22
+ import { z } from "zod";
23
+ import fs from "fs/promises";
24
+ import path from "path";
25
+ import { load } from "js-yaml";
18
26
  var fileRegex = /\.(md|mdx)$/;
19
- function unstable_mdx(config, _options = {}) {
27
+ var onlySchema = z.literal(["frontmatter", "all"]);
28
+ function mdx(config, options = {}) {
29
+ const { generateIndexFile = true, configPath = "source.config.ts" } = options;
20
30
  const [err, loaded] = buildConfig(config);
21
31
  if (err || !loaded) {
22
32
  throw new Error(err);
23
33
  }
24
34
  return {
25
35
  name: "fumadocs-mdx",
26
- // TODO: need a way to generate .source folder that works for non-RSC based frameworks, currently, we need to dynamic import MDX files using `import.meta.glob`.
27
- // at the moment, RR and Tanstack Start has no stable support for RSC yet.
36
+ // needed, otherwise other plugins will be executed before our `transform`.
37
+ enforce: "pre",
38
+ async buildStart() {
39
+ if (!generateIndexFile) return;
40
+ console.log("[Fumadocs MDX] Generating index files");
41
+ const outdir = process.cwd();
42
+ const outFile = "source.generated.ts";
43
+ const lines = [
44
+ `import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
45
+ `import type * as Config from '${toImportPath(configPath, {
46
+ relativeTo: outdir
47
+ })}';`,
48
+ "",
49
+ `export const create = fromConfig<typeof Config>();`
50
+ ];
51
+ function filesToGlob(files) {
52
+ return files.map((file) => {
53
+ if (file.startsWith("./")) return file;
54
+ if (file.startsWith("/")) return `.${file}`;
55
+ return `./${file}`;
56
+ });
57
+ }
58
+ function docs(name, dir, collection) {
59
+ const docFiles = collection.docs.files ? filesToGlob(collection.docs.files) : ["./**/*.{mdx,md}"];
60
+ const metaFiles = collection.meta.files ? filesToGlob(collection.meta.files) : ["./**/*.{yaml,json}"];
61
+ return `export const ${name} = create.docs('${name}', {
62
+ doc: import.meta.glob(${JSON.stringify(docFiles)}, {
63
+ query: {
64
+ collection: '${name}',
65
+ },
66
+ base: '${dir}',
67
+ }),
68
+ meta: import.meta.glob(${JSON.stringify(metaFiles)}, {
69
+ query: {
70
+ collection: '${name}',
71
+ },
72
+ base: '${dir}',
73
+ import: 'default',
74
+ }),
75
+ });`;
76
+ }
77
+ function doc(name, dir, collection) {
78
+ const files = collection.files ? filesToGlob(collection.files) : ["./**/*.{mdx,md}"];
79
+ return `export const ${name} = create.doc(
80
+ '${name}',
81
+ import.meta.glob(${JSON.stringify(files)}, {
82
+ query: {
83
+ collection: '${name}',
84
+ },
85
+ base: '${dir}',
86
+ }),
87
+ );`;
88
+ }
89
+ function meta(name, dir, collection) {
90
+ const files = collection.files ? filesToGlob(collection.files) : ["./**/*.{yaml,json}"];
91
+ return `export const ${name} = create.meta(
92
+ '${name}',
93
+ import.meta.glob(${JSON.stringify(files)}, {
94
+ query: {
95
+ collection: '${name}',
96
+ },
97
+ base: '${dir}',
98
+ import: 'default',
99
+ }),
100
+ );`;
101
+ }
102
+ for (const [name, collection] of loaded.collections.entries()) {
103
+ let dir = collection.dir;
104
+ if (Array.isArray(dir) && dir.length === 1) {
105
+ dir = dir[0];
106
+ } else if (Array.isArray(dir)) {
107
+ throw new Error(
108
+ `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
109
+ );
110
+ }
111
+ if (!dir.startsWith("./") && !dir.startsWith("/")) {
112
+ dir = "/" + dir;
113
+ }
114
+ lines.push("");
115
+ if (collection.type === "docs") {
116
+ lines.push(docs(name, dir, collection));
117
+ } else if (collection.type === "meta") {
118
+ lines.push(meta(name, dir, collection));
119
+ } else {
120
+ lines.push(doc(name, dir, collection));
121
+ }
122
+ }
123
+ await fs.writeFile(path.join(outdir, outFile), lines.join("\n"));
124
+ },
28
125
  async transform(value, id) {
29
- const [path, query = ""] = id.split("?");
30
- if (!fileRegex.test(path)) return;
126
+ const [path2, query = ""] = id.split("?");
127
+ const isJson = path2.endsWith(".json");
128
+ const isYaml = path2.endsWith(".yaml");
129
+ if (isJson || isYaml) {
130
+ const parsed2 = parse(query);
131
+ const collection2 = parsed2.collection ? loaded.collections.get(parsed2.collection) : void 0;
132
+ if (!collection2) return null;
133
+ let schema2;
134
+ switch (collection2.type) {
135
+ case "meta":
136
+ schema2 = collection2.schema;
137
+ break;
138
+ case "docs":
139
+ schema2 = collection2.meta.schema;
140
+ break;
141
+ }
142
+ if (!schema2) return null;
143
+ let data;
144
+ try {
145
+ data = isJson ? JSON.parse(value) : load(value);
146
+ } catch {
147
+ return null;
148
+ }
149
+ const out = await validate(
150
+ schema2,
151
+ data,
152
+ { path: path2, source: value },
153
+ `invalid data in ${path2}`
154
+ );
155
+ return {
156
+ code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
157
+ map: null
158
+ };
159
+ }
160
+ if (!fileRegex.test(path2)) return;
31
161
  const matter = fumaMatter(value);
32
162
  const isDevelopment = this.environment.mode === "dev";
33
- const { collection: collectionId, raw } = parse(query);
34
- const collection = collectionId ? loaded.collections.get(collectionId) : void 0;
35
- const lineOffset = "\n".repeat(
36
- isDevelopment ? countLines(matter.matter) : 0
37
- );
163
+ const parsed = parse(query);
164
+ const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
165
+ const only = parsed.only ? onlySchema.parse(parsed.only) : "all";
166
+ let schema;
38
167
  let mdxOptions;
39
168
  switch (collection?.type) {
40
169
  case "doc":
41
170
  mdxOptions = collection.mdxOptions;
171
+ schema = collection.schema;
42
172
  break;
43
173
  case "docs":
44
174
  mdxOptions = collection.docs.mdxOptions;
175
+ schema = collection.docs.schema;
45
176
  break;
46
177
  }
47
- mdxOptions ??= await loadDefaultOptions(loaded);
178
+ if (schema) {
179
+ try {
180
+ matter.data = await validate(
181
+ schema,
182
+ matter.data,
183
+ {
184
+ source: value,
185
+ path: path2
186
+ },
187
+ `invalid frontmatter in ${path2}`
188
+ );
189
+ } catch (e) {
190
+ if (e instanceof ValidationError) {
191
+ throw new Error(e.toStringFormatted());
192
+ }
193
+ throw e;
194
+ }
195
+ }
196
+ if (only === "frontmatter") {
197
+ return {
198
+ code: `export const frontmatter = ${JSON.stringify(matter.data)}`
199
+ };
200
+ }
201
+ mdxOptions ??= await loaded.getDefaultMDXOptions();
202
+ const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
48
203
  const file = await buildMDX(
49
- collectionId ?? "global",
50
- lineOffset + matter.content,
204
+ parsed.collection ?? "global",
205
+ "\n".repeat(lineOffset) + matter.content,
51
206
  {
52
207
  development: isDevelopment,
53
208
  ...mdxOptions,
54
- filePath: path,
209
+ filePath: path2,
55
210
  frontmatter: matter.data,
56
211
  _compiler: {
57
212
  addDependency: (file2) => {
@@ -61,11 +216,12 @@ function unstable_mdx(config, _options = {}) {
61
216
  }
62
217
  );
63
218
  return {
64
- code: typeof raw === "string" ? `export default ${JSON.stringify(file.value)}` : String(file.value)
219
+ code: String(file.value),
220
+ map: file.map
65
221
  };
66
222
  }
67
223
  };
68
224
  }
69
225
  export {
70
- unstable_mdx as default
226
+ mdx as default
71
227
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-mdx",
3
- "version": "11.6.11",
3
+ "version": "11.7.0",
4
4
  "description": "The built-in source for Fumadocs",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -32,6 +32,10 @@
32
32
  "import": "./dist/runtime/async.js",
33
33
  "types": "./dist/runtime/async.d.ts"
34
34
  },
35
+ "./runtime/vite": {
36
+ "import": "./dist/runtime/vite.js",
37
+ "types": "./dist/runtime/vite.d.ts"
38
+ },
35
39
  ".": {
36
40
  "import": "./dist/index.js",
37
41
  "types": "./dist/index.d.ts",
@@ -50,7 +54,7 @@
50
54
  "@mdx-js/mdx": "^3.1.0",
51
55
  "@standard-schema/spec": "^1.0.0",
52
56
  "chokidar": "^4.0.3",
53
- "esbuild": "^0.25.6",
57
+ "esbuild": "^0.25.8",
54
58
  "estree-util-value-to-estree": "^3.4.0",
55
59
  "js-yaml": "^4.1.0",
56
60
  "lru-cache": "^11.1.0",
@@ -64,25 +68,31 @@
64
68
  "@types/js-yaml": "^4.0.9",
65
69
  "@types/mdast": "^4.0.3",
66
70
  "@types/mdx": "^2.0.13",
71
+ "@types/node": "^24.0.15",
67
72
  "@types/react": "^19.1.8",
68
73
  "mdast-util-mdx-jsx": "^3.2.0",
69
- "next": "^15.3.5",
74
+ "next": "^15.4.2",
75
+ "react": "^19.1.0",
70
76
  "unified": "^11.0.5",
71
77
  "vfile": "^6.0.3",
72
- "vite": "^7.0.4",
73
- "webpack": "^5.100.0",
74
- "@fumadocs/mdx-remote": "1.3.4",
78
+ "vite": "^7.0.5",
79
+ "webpack": "^5.100.2",
80
+ "@fumadocs/mdx-remote": "1.4.0",
75
81
  "eslint-config-custom": "0.0.0",
76
- "fumadocs-core": "15.6.3",
82
+ "fumadocs-core": "15.6.5",
77
83
  "tsconfig": "0.0.0"
78
84
  },
79
85
  "peerDependencies": {
80
- "@fumadocs/mdx-remote": "^1.2.0",
86
+ "@fumadocs/mdx-remote": "^1.4.0",
81
87
  "fumadocs-core": "^14.0.0 || ^15.0.0",
82
88
  "next": "^15.3.0",
83
- "vite": "6.x.x"
89
+ "react": "*",
90
+ "vite": "6.x.x || 7.x.x"
84
91
  },
85
92
  "peerDependenciesMeta": {
93
+ "react": {
94
+ "optional": true
95
+ },
86
96
  "next": {
87
97
  "optional": true
88
98
  },