fumadocs-mdx 11.6.11 → 11.7.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.
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-OWZSTKKX.js +58 -0
  6. package/dist/{chunk-22SBT5SQ.js → chunk-ZOWJF3OH.js} +6 -6
  7. package/dist/config/index.cjs +4 -19
  8. package/dist/config/index.d.cts +3 -7
  9. package/dist/config/index.d.ts +3 -7
  10. package/dist/config/index.js +7 -13
  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 +253 -85
  19. package/dist/next/index.js +49 -63
  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 +150 -0
  25. package/dist/runtime/vite.d.cts +71 -0
  26. package/dist/runtime/vite.d.ts +71 -0
  27. package/dist/runtime/vite.js +123 -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 +385 -134
  31. package/dist/vite/index.d.cts +12 -3
  32. package/dist/vite/index.d.ts +12 -3
  33. package/dist/vite/index.js +165 -20
  34. package/package.json +20 -10
@@ -1,13 +1,19 @@
1
1
  import {
2
2
  buildMDX,
3
3
  countLines
4
- } from "../chunk-6PDS7MUA.js";
4
+ } from "../chunk-C5INPAZJ.js";
5
+ import {
6
+ getGlobPatterns,
7
+ ident,
8
+ toImportPath
9
+ } from "../chunk-OWZSTKKX.js";
5
10
  import {
6
11
  buildConfig
7
- } from "../chunk-DRVUBK5B.js";
12
+ } from "../chunk-GWR7KMRU.js";
8
13
  import {
9
- loadDefaultOptions
10
- } from "../chunk-64MMPGML.js";
14
+ ValidationError,
15
+ validate
16
+ } from "../chunk-ZOWJF3OH.js";
11
17
  import "../chunk-AVMO2SRO.js";
12
18
  import {
13
19
  fumaMatter
@@ -15,43 +21,147 @@ import {
15
21
 
16
22
  // src/vite/index.ts
17
23
  import { parse } from "querystring";
24
+ import { z } from "zod";
25
+ import fs from "fs/promises";
26
+ import path from "path";
27
+ import { load } from "js-yaml";
18
28
  var fileRegex = /\.(md|mdx)$/;
19
- function unstable_mdx(config, _options = {}) {
29
+ var onlySchema = z.literal(["frontmatter", "all"]);
30
+ function mdx(config, options = {}) {
31
+ const { generateIndexFile = true, configPath = "source.config.ts" } = options;
20
32
  const [err, loaded] = buildConfig(config);
21
33
  if (err || !loaded) {
22
34
  throw new Error(err);
23
35
  }
24
36
  return {
25
37
  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.
38
+ // needed, otherwise other plugins will be executed before our `transform`.
39
+ enforce: "pre",
40
+ async buildStart() {
41
+ if (!generateIndexFile) return;
42
+ console.log("[Fumadocs MDX] Generating index files");
43
+ const outdir = process.cwd();
44
+ const outFile = "source.generated.ts";
45
+ const lines = [
46
+ `import { fromConfig } from 'fumadocs-mdx/runtime/vite';`,
47
+ `import type * as Config from '${toImportPath(configPath, {
48
+ relativeTo: outdir
49
+ })}';`,
50
+ "",
51
+ `export const create = fromConfig<typeof Config>();`
52
+ ];
53
+ function docs(name, collection) {
54
+ const args = [
55
+ ident(`doc: ${generateGlob(name, collection.docs)}`),
56
+ ident(`meta: ${generateGlob(name, collection.meta)}`)
57
+ ].join(",\n");
58
+ return `export const ${name} = create.docs("${name}", {
59
+ ${args}
60
+ });`;
61
+ }
62
+ function doc(name, collection) {
63
+ return `export const ${name} = create.doc("${name}", ${generateGlob(name, collection)});`;
64
+ }
65
+ function meta(name, collection) {
66
+ return `export const ${name} = create.meta("${name}", ${generateGlob(name, collection)});`;
67
+ }
68
+ for (const [name, collection] of loaded.collections.entries()) {
69
+ lines.push("");
70
+ if (collection.type === "docs") {
71
+ lines.push(docs(name, collection));
72
+ } else if (collection.type === "meta") {
73
+ lines.push(meta(name, collection));
74
+ } else {
75
+ lines.push(doc(name, collection));
76
+ }
77
+ }
78
+ await fs.writeFile(path.join(outdir, outFile), lines.join("\n"));
79
+ },
28
80
  async transform(value, id) {
29
- const [path, query = ""] = id.split("?");
30
- if (!fileRegex.test(path)) return;
81
+ const [path2, query = ""] = id.split("?");
82
+ const isJson = path2.endsWith(".json");
83
+ const isYaml = path2.endsWith(".yaml");
84
+ if (isJson || isYaml) {
85
+ const parsed2 = parse(query);
86
+ const collection2 = parsed2.collection ? loaded.collections.get(parsed2.collection) : void 0;
87
+ if (!collection2) return null;
88
+ let schema2;
89
+ switch (collection2.type) {
90
+ case "meta":
91
+ schema2 = collection2.schema;
92
+ break;
93
+ case "docs":
94
+ schema2 = collection2.meta.schema;
95
+ break;
96
+ }
97
+ if (!schema2) return null;
98
+ let data;
99
+ try {
100
+ data = isJson ? JSON.parse(value) : load(value);
101
+ } catch {
102
+ return null;
103
+ }
104
+ const out = await validate(
105
+ schema2,
106
+ data,
107
+ { path: path2, source: value },
108
+ `invalid data in ${path2}`
109
+ );
110
+ return {
111
+ code: isJson ? JSON.stringify(out) : `export default ${JSON.stringify(out)}`,
112
+ map: null
113
+ };
114
+ }
115
+ if (!fileRegex.test(path2)) return;
31
116
  const matter = fumaMatter(value);
32
117
  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
- );
118
+ const parsed = parse(query);
119
+ const collection = parsed.collection ? loaded.collections.get(parsed.collection) : void 0;
120
+ const only = parsed.only ? onlySchema.parse(parsed.only) : "all";
121
+ let schema;
38
122
  let mdxOptions;
39
123
  switch (collection?.type) {
40
124
  case "doc":
41
125
  mdxOptions = collection.mdxOptions;
126
+ schema = collection.schema;
42
127
  break;
43
128
  case "docs":
44
129
  mdxOptions = collection.docs.mdxOptions;
130
+ schema = collection.docs.schema;
45
131
  break;
46
132
  }
47
- mdxOptions ??= await loadDefaultOptions(loaded);
133
+ if (schema) {
134
+ try {
135
+ matter.data = await validate(
136
+ schema,
137
+ matter.data,
138
+ {
139
+ source: value,
140
+ path: path2
141
+ },
142
+ `invalid frontmatter in ${path2}`
143
+ );
144
+ } catch (e) {
145
+ if (e instanceof ValidationError) {
146
+ throw new Error(e.toStringFormatted());
147
+ }
148
+ throw e;
149
+ }
150
+ }
151
+ if (only === "frontmatter") {
152
+ return {
153
+ code: `export const frontmatter = ${JSON.stringify(matter.data)}`
154
+ };
155
+ }
156
+ mdxOptions ??= await loaded.getDefaultMDXOptions();
157
+ const lineOffset = isDevelopment ? countLines(matter.matter) : 0;
48
158
  const file = await buildMDX(
49
- collectionId ?? "global",
50
- lineOffset + matter.content,
159
+ parsed.collection ?? "global",
160
+ "\n".repeat(lineOffset) + matter.content,
51
161
  {
52
162
  development: isDevelopment,
53
163
  ...mdxOptions,
54
- filePath: path,
164
+ filePath: path2,
55
165
  frontmatter: matter.data,
56
166
  _compiler: {
57
167
  addDependency: (file2) => {
@@ -61,11 +171,46 @@ function unstable_mdx(config, _options = {}) {
61
171
  }
62
172
  );
63
173
  return {
64
- code: typeof raw === "string" ? `export default ${JSON.stringify(file.value)}` : String(file.value)
174
+ code: String(file.value),
175
+ map: file.map
65
176
  };
66
177
  }
67
178
  };
68
179
  }
180
+ function generateGlob(name, collection) {
181
+ const patterns = mapGlobPatterns(getGlobPatterns(collection));
182
+ const options = {
183
+ query: {
184
+ collection: name
185
+ },
186
+ base: getGlobBase(collection)
187
+ };
188
+ if (collection.type === "meta") {
189
+ options.import = "default";
190
+ }
191
+ return `import.meta.glob(${JSON.stringify(patterns)}, ${JSON.stringify(options, null, 2)})`;
192
+ }
193
+ function mapGlobPatterns(patterns) {
194
+ return patterns.map((file) => {
195
+ if (file.startsWith("./")) return file;
196
+ if (file.startsWith("/")) return `.${file}`;
197
+ return `./${file}`;
198
+ });
199
+ }
200
+ function getGlobBase(collection) {
201
+ let dir = collection.dir;
202
+ if (Array.isArray(dir)) {
203
+ if (dir.length !== 1)
204
+ throw new Error(
205
+ `[Fumadocs MDX] Vite Plugin doesn't support multiple \`dir\` for a collection at the moment.`
206
+ );
207
+ dir = dir[0];
208
+ }
209
+ if (!dir.startsWith("./") && !dir.startsWith("/")) {
210
+ return "/" + dir;
211
+ }
212
+ return dir;
213
+ }
69
214
  export {
70
- unstable_mdx as default
215
+ mdx as default
71
216
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-mdx",
3
- "version": "11.6.11",
3
+ "version": "11.7.1",
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",
@@ -58,31 +62,37 @@
58
62
  "tinyexec": "^1.0.1",
59
63
  "tinyglobby": "^0.2.14",
60
64
  "unist-util-visit": "^5.0.0",
61
- "zod": "^4.0.5"
65
+ "zod": "^4.0.10"
62
66
  },
63
67
  "devDependencies": {
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.1.0",
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.4",
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.6",
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
  },