fumadocs-mdx 9.0.3 → 10.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.
- package/bin.mjs +5 -0
- package/dist/chunk-EKBKQCSU.mjs +137 -0
- package/dist/chunk-LRV535YP.mjs +161 -0
- package/dist/config/index.d.mts +171 -0
- package/dist/config/index.mjs +16 -0
- package/dist/index.d.mts +20 -93
- package/dist/index.mjs +49 -87
- package/dist/loader-mdx.d.mts +13 -13
- package/dist/loader-mdx.mjs +167 -44
- package/dist/next/index.d.mts +13 -0
- package/dist/next/index.mjs +239 -0
- package/package.json +20 -9
- package/dist/config.d.mts +0 -44
- package/dist/config.mjs +0 -260
- package/dist/loader.d.mts +0 -18
- package/dist/loader.mjs +0 -36
- package/dist/search-index-plugin-DG9nZ1CX.d.mts +0 -40
- package/loader.js +0 -8
package/dist/index.mjs
CHANGED
|
@@ -1,111 +1,73 @@
|
|
|
1
|
-
// src/resolve-files.ts
|
|
1
|
+
// src/runtime/resolve-files.ts
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
// src/utils/schema.ts
|
|
5
|
-
import { z } from "zod";
|
|
6
|
-
var metaSchema = z.object({
|
|
7
|
-
title: z.string().optional(),
|
|
8
|
-
pages: z.array(z.string()).optional(),
|
|
9
|
-
root: z.boolean().optional(),
|
|
10
|
-
defaultOpen: z.boolean().optional(),
|
|
11
|
-
icon: z.string().optional()
|
|
12
|
-
});
|
|
13
|
-
var frontmatterSchema = z.object({
|
|
14
|
-
title: z.string(),
|
|
15
|
-
description: z.string().optional(),
|
|
16
|
-
icon: z.string().optional(),
|
|
17
|
-
full: z.boolean().optional(),
|
|
18
|
-
// Fumadocs OpenAPI generated
|
|
19
|
-
_openapi: z.object({}).passthrough().optional()
|
|
20
|
-
});
|
|
21
|
-
var defaultSchemas = {
|
|
22
|
-
frontmatter: frontmatterSchema,
|
|
23
|
-
meta: metaSchema
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// src/resolve-files.ts
|
|
27
3
|
var pageTypes = [".md", ".mdx"];
|
|
28
|
-
var metaTypes = [".json"];
|
|
29
|
-
var DataError = class extends Error {
|
|
30
|
-
constructor(name, error) {
|
|
31
|
-
const info = error.flatten();
|
|
32
|
-
super(
|
|
33
|
-
`${name}: ${JSON.stringify(
|
|
34
|
-
{
|
|
35
|
-
root: info.formErrors,
|
|
36
|
-
...info.fieldErrors
|
|
37
|
-
},
|
|
38
|
-
null,
|
|
39
|
-
2
|
|
40
|
-
)}`
|
|
41
|
-
);
|
|
42
|
-
this.name = "DataError";
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
function parse(schema, object, errorName) {
|
|
46
|
-
const result = schema.safeParse(object);
|
|
47
|
-
if (!result.success) {
|
|
48
|
-
throw new DataError(errorName, result.error);
|
|
49
|
-
}
|
|
50
|
-
return result.data;
|
|
51
|
-
}
|
|
4
|
+
var metaTypes = [".json", ".yaml"];
|
|
52
5
|
function resolveFiles({
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
6
|
+
docs,
|
|
7
|
+
meta,
|
|
8
|
+
rootDir = ""
|
|
56
9
|
}) {
|
|
57
10
|
const outputs = [];
|
|
58
|
-
for (const
|
|
59
|
-
if (!
|
|
60
|
-
const
|
|
61
|
-
if (
|
|
11
|
+
for (const entry of docs) {
|
|
12
|
+
if (!entry._file.path.startsWith(rootDir)) continue;
|
|
13
|
+
const ext = path.extname(entry._file.path);
|
|
14
|
+
if (pageTypes.includes(ext)) {
|
|
62
15
|
outputs.push({
|
|
63
|
-
type: "
|
|
64
|
-
path:
|
|
65
|
-
data:
|
|
66
|
-
schema.meta ?? defaultSchemas.meta,
|
|
67
|
-
value,
|
|
68
|
-
`Invalid meta file in ${file}`
|
|
69
|
-
)
|
|
16
|
+
type: "page",
|
|
17
|
+
path: entry._file.path,
|
|
18
|
+
data: entry
|
|
70
19
|
});
|
|
71
20
|
continue;
|
|
72
21
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
22
|
+
console.warn(
|
|
23
|
+
`Unknown Type: ${ext} on ${entry._file.path}, expected: ${pageTypes.toString()}`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
for (const entry of meta) {
|
|
27
|
+
if (!entry._file.path.startsWith(rootDir)) continue;
|
|
28
|
+
const ext = path.extname(entry._file.path);
|
|
29
|
+
if (metaTypes.includes(ext)) {
|
|
80
30
|
outputs.push({
|
|
81
|
-
type: "
|
|
82
|
-
path:
|
|
83
|
-
data:
|
|
84
|
-
...parsedFrontmatter,
|
|
85
|
-
exports: data
|
|
86
|
-
}
|
|
31
|
+
type: "meta",
|
|
32
|
+
path: entry._file.path,
|
|
33
|
+
data: entry
|
|
87
34
|
});
|
|
88
35
|
continue;
|
|
89
36
|
}
|
|
90
|
-
console.warn(
|
|
37
|
+
console.warn(
|
|
38
|
+
`Unknown Type: ${ext} on ${entry._file.path}, expected: ${metaTypes.toString()}`
|
|
39
|
+
);
|
|
91
40
|
}
|
|
92
41
|
return outputs;
|
|
93
42
|
}
|
|
94
43
|
|
|
95
|
-
// src/create.ts
|
|
96
|
-
function
|
|
44
|
+
// src/runtime/create.ts
|
|
45
|
+
function toRuntime(type, file, info) {
|
|
46
|
+
if (type === "doc") {
|
|
47
|
+
const { default: body, frontmatter, ...exports } = file;
|
|
48
|
+
return {
|
|
49
|
+
body,
|
|
50
|
+
...exports,
|
|
51
|
+
...frontmatter,
|
|
52
|
+
_exports: file,
|
|
53
|
+
_file: info
|
|
54
|
+
};
|
|
55
|
+
}
|
|
97
56
|
return {
|
|
98
|
-
|
|
57
|
+
...file.default,
|
|
58
|
+
_file: info
|
|
99
59
|
};
|
|
100
60
|
}
|
|
101
|
-
function
|
|
102
|
-
return
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
61
|
+
function createMDXSource(docs, meta) {
|
|
62
|
+
return {
|
|
63
|
+
files: (rootDir) => resolveFiles({
|
|
64
|
+
docs,
|
|
65
|
+
meta,
|
|
66
|
+
rootDir
|
|
67
|
+
})
|
|
68
|
+
};
|
|
106
69
|
}
|
|
107
70
|
export {
|
|
108
71
|
createMDXSource,
|
|
109
|
-
|
|
110
|
-
loadMDXSource
|
|
72
|
+
toRuntime
|
|
111
73
|
};
|
package/dist/loader-mdx.d.mts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { ProcessorOptions } from '@mdx-js/mdx';
|
|
2
1
|
import { LoaderContext } from 'webpack';
|
|
2
|
+
import { StructuredData } from 'fumadocs-core/mdx-plugins';
|
|
3
3
|
|
|
4
|
-
interface Options
|
|
4
|
+
interface Options {
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
* @defaultValue 'none'
|
|
6
|
+
* @internal
|
|
8
7
|
*/
|
|
9
|
-
|
|
8
|
+
_ctx: {
|
|
9
|
+
configPath: string;
|
|
10
|
+
};
|
|
10
11
|
}
|
|
11
|
-
interface
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
data: unknown;
|
|
12
|
+
interface MetaFile {
|
|
13
|
+
path: string;
|
|
14
|
+
data: {
|
|
15
|
+
frontmatter: Record<string, unknown>;
|
|
16
|
+
structuredData?: StructuredData;
|
|
17
|
+
[key: string]: unknown;
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
@@ -24,4 +24,4 @@ interface InternalBuildInfo {
|
|
|
24
24
|
*/
|
|
25
25
|
declare function loader(this: LoaderContext<Options>, source: string, callback: LoaderContext<Options>['callback']): Promise<void>;
|
|
26
26
|
|
|
27
|
-
export { type
|
|
27
|
+
export { type MetaFile, type Options, loader as default };
|
package/dist/loader-mdx.mjs
CHANGED
|
@@ -1,31 +1,116 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getConfigHash,
|
|
3
|
+
getKey,
|
|
4
|
+
loadConfigCached
|
|
5
|
+
} from "./chunk-EKBKQCSU.mjs";
|
|
6
|
+
import {
|
|
7
|
+
getDefaultMDXOptions
|
|
8
|
+
} from "./chunk-LRV535YP.mjs";
|
|
9
|
+
|
|
1
10
|
// src/loader-mdx.ts
|
|
2
|
-
import
|
|
11
|
+
import path3 from "node:path";
|
|
3
12
|
import fs2 from "node:fs/promises";
|
|
4
|
-
import {
|
|
13
|
+
import { parse } from "node:querystring";
|
|
5
14
|
import grayMatter from "gray-matter";
|
|
6
15
|
|
|
7
|
-
// src/utils/
|
|
16
|
+
// src/utils/find-collection.ts
|
|
8
17
|
import path from "node:path";
|
|
18
|
+
import micromatch from "micromatch";
|
|
19
|
+
function findCollectionId(config, file, type) {
|
|
20
|
+
const cached = config._runtime.files.get(file);
|
|
21
|
+
if (cached) return cached;
|
|
22
|
+
for (const [name, collection] of config.collections.entries()) {
|
|
23
|
+
if (collection.type !== type) continue;
|
|
24
|
+
const dirs = Array.isArray(collection.dir) ? collection.dir : [collection.dir];
|
|
25
|
+
const isInDir = dirs.some((dir) => {
|
|
26
|
+
const relative = path.relative(dir, path.dirname(file));
|
|
27
|
+
return !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
28
|
+
});
|
|
29
|
+
if (!isInDir) continue;
|
|
30
|
+
const isIncluded = collection.files ? micromatch.isMatch(file, collection.files) : true;
|
|
31
|
+
if (!isIncluded) continue;
|
|
32
|
+
config._runtime.files.set(file, name);
|
|
33
|
+
return name;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/utils/build-mdx.ts
|
|
38
|
+
import { createProcessor } from "@mdx-js/mdx";
|
|
39
|
+
var cache = /* @__PURE__ */ new Map();
|
|
40
|
+
function cacheKey(group, format) {
|
|
41
|
+
return `${group}:${format}`;
|
|
42
|
+
}
|
|
43
|
+
function buildMDX(group, configHash, source, options = {}) {
|
|
44
|
+
const { filePath, frontmatter, data, ...rest } = options;
|
|
45
|
+
let format = options.format;
|
|
46
|
+
if (!format && filePath) {
|
|
47
|
+
format = filePath.endsWith(".mdx") ? "mdx" : "md";
|
|
48
|
+
}
|
|
49
|
+
format ??= "mdx";
|
|
50
|
+
const key = cacheKey(group, format);
|
|
51
|
+
let cached = cache.get(key);
|
|
52
|
+
if (cached === void 0 || cached.configHash !== configHash) {
|
|
53
|
+
cached = {
|
|
54
|
+
processor: createProcessor({
|
|
55
|
+
outputFormat: "program",
|
|
56
|
+
development: process.env.NODE_ENV === "development",
|
|
57
|
+
...rest,
|
|
58
|
+
format
|
|
59
|
+
}),
|
|
60
|
+
configHash
|
|
61
|
+
};
|
|
62
|
+
cache.set(key, cached);
|
|
63
|
+
}
|
|
64
|
+
return cached.processor.process({
|
|
65
|
+
value: source,
|
|
66
|
+
path: filePath,
|
|
67
|
+
data: {
|
|
68
|
+
...data,
|
|
69
|
+
frontmatter
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/utils/format-error.ts
|
|
75
|
+
function formatError(file, error) {
|
|
76
|
+
const lines = [];
|
|
77
|
+
function walk(key, { _errors, ...rest }, padStart = 0) {
|
|
78
|
+
if (key !== void 0 || _errors.length > 0) {
|
|
79
|
+
const text = key ? `${key}: ${_errors.join("\n ")}` : _errors.join("\n");
|
|
80
|
+
lines.push(
|
|
81
|
+
text.split("\n").map((line) => `${" ".repeat(padStart)}${line}`).join("\n")
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
for (const [k, v] of Object.entries(rest)) {
|
|
85
|
+
walk(key ? `${key}.${k}` : k, v, padStart + 2);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
walk(void 0, error.format());
|
|
89
|
+
return [`in ${file}:`, ...lines].join("\n");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/utils/git-timestamp.ts
|
|
93
|
+
import path2 from "node:path";
|
|
9
94
|
import fs from "node:fs";
|
|
10
95
|
import { spawn } from "cross-spawn";
|
|
11
|
-
var
|
|
96
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
12
97
|
function getGitTimestamp(file) {
|
|
13
|
-
const cachedTimestamp =
|
|
98
|
+
const cachedTimestamp = cache2.get(file);
|
|
14
99
|
if (cachedTimestamp) return Promise.resolve(cachedTimestamp);
|
|
15
100
|
return new Promise((resolve, reject) => {
|
|
16
|
-
const cwd =
|
|
101
|
+
const cwd = path2.dirname(file);
|
|
17
102
|
if (!fs.existsSync(cwd)) {
|
|
18
103
|
resolve(void 0);
|
|
19
104
|
return;
|
|
20
105
|
}
|
|
21
|
-
const fileName =
|
|
106
|
+
const fileName = path2.basename(file);
|
|
22
107
|
const child = spawn("git", ["log", "-1", '--pretty="%ai"', fileName], {
|
|
23
108
|
cwd
|
|
24
109
|
});
|
|
25
110
|
let output;
|
|
26
111
|
child.stdout.on("data", (d) => output = new Date(String(d)));
|
|
27
112
|
child.on("close", () => {
|
|
28
|
-
if (output)
|
|
113
|
+
if (output) cache2.set(file, output);
|
|
29
114
|
resolve(output);
|
|
30
115
|
});
|
|
31
116
|
child.on("error", reject);
|
|
@@ -33,55 +118,93 @@ function getGitTimestamp(file) {
|
|
|
33
118
|
}
|
|
34
119
|
|
|
35
120
|
// src/loader-mdx.ts
|
|
36
|
-
|
|
121
|
+
function getQuery(query) {
|
|
122
|
+
let collection;
|
|
123
|
+
let hash;
|
|
124
|
+
const parsed = parse(query.slice(1));
|
|
125
|
+
if (parsed.collection && typeof parsed.collection === "string")
|
|
126
|
+
collection = parsed.collection;
|
|
127
|
+
if (parsed.hash && typeof parsed.hash === "string") hash = parsed.hash;
|
|
128
|
+
return { collection, hash };
|
|
129
|
+
}
|
|
37
130
|
async function loader(source, callback) {
|
|
38
131
|
this.cacheable(true);
|
|
39
132
|
const context = this.context;
|
|
40
133
|
const filePath = this.resourcePath;
|
|
41
|
-
const {
|
|
42
|
-
const detectedFormat = filePath.endsWith(".mdx") ? "mdx" : "md";
|
|
43
|
-
const format = options.format ?? detectedFormat;
|
|
44
|
-
let processor = cache2.get(format);
|
|
45
|
-
if (processor === void 0) {
|
|
46
|
-
processor = createProcessor({
|
|
47
|
-
...options,
|
|
48
|
-
development: this.mode === "development",
|
|
49
|
-
format
|
|
50
|
-
});
|
|
51
|
-
cache2.set(format, processor);
|
|
52
|
-
}
|
|
134
|
+
const { _ctx } = this.getOptions();
|
|
53
135
|
const matter = grayMatter(source);
|
|
136
|
+
const query = getQuery(this.resourceQuery);
|
|
137
|
+
const configHash = query.hash ?? await getConfigHash(_ctx.configPath);
|
|
138
|
+
const config = await loadConfigCached(_ctx.configPath, configHash);
|
|
139
|
+
const collectionId = query.collection ?? findCollectionId(config, filePath, "doc");
|
|
140
|
+
const collection = collectionId !== void 0 ? config.collections.get(collectionId) : void 0;
|
|
141
|
+
const mdxOptions = collection?.mdxOptions ?? getDefaultMDXOptions(config.global?.mdxOptions ?? {});
|
|
142
|
+
function getTransformContext() {
|
|
143
|
+
return {
|
|
144
|
+
buildMDX: async (v, options = mdxOptions) => {
|
|
145
|
+
const res = await buildMDX(
|
|
146
|
+
collectionId ?? "global",
|
|
147
|
+
configHash,
|
|
148
|
+
v,
|
|
149
|
+
options
|
|
150
|
+
);
|
|
151
|
+
return String(res.value);
|
|
152
|
+
},
|
|
153
|
+
source,
|
|
154
|
+
path: filePath
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
let frontmatter = matter.data;
|
|
158
|
+
if (collection?.schema) {
|
|
159
|
+
const schema = typeof collection.schema === "function" ? collection.schema(getTransformContext()) : collection.schema;
|
|
160
|
+
const result = await schema.safeParseAsync(frontmatter);
|
|
161
|
+
if (result.error) {
|
|
162
|
+
callback(new Error(formatError(filePath, result.error)));
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
frontmatter = result.data;
|
|
166
|
+
}
|
|
54
167
|
const props = matter.data._mdx ?? {};
|
|
55
168
|
if (props.mirror) {
|
|
56
|
-
const mirrorPath =
|
|
169
|
+
const mirrorPath = path3.resolve(path3.dirname(filePath), props.mirror);
|
|
57
170
|
this.addDependency(mirrorPath);
|
|
58
171
|
matter.content = await fs2.readFile(mirrorPath).then((res) => grayMatter(res.toString()).content);
|
|
59
172
|
}
|
|
60
173
|
let timestamp;
|
|
61
|
-
if (lastModifiedTime === "git")
|
|
174
|
+
if (config.global?.lastModifiedTime === "git")
|
|
62
175
|
timestamp = (await getGitTimestamp(filePath))?.getTime();
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
176
|
+
try {
|
|
177
|
+
const file = await buildMDX(
|
|
178
|
+
collectionId ?? "global",
|
|
179
|
+
configHash,
|
|
180
|
+
matter.content,
|
|
181
|
+
{
|
|
182
|
+
development: this.mode === "development",
|
|
183
|
+
...mdxOptions,
|
|
184
|
+
filePath,
|
|
185
|
+
frontmatter,
|
|
186
|
+
data: {
|
|
187
|
+
lastModified: timestamp
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
callback(void 0, String(file.value), file.map ?? void 0);
|
|
192
|
+
if (config.global?.generateManifest) {
|
|
193
|
+
await fs2.mkdir(".next/cache/fumadocs", { recursive: true });
|
|
194
|
+
await fs2.writeFile(
|
|
195
|
+
path3.resolve(".next/cache/fumadocs", `${getKey(filePath)}.json`),
|
|
196
|
+
JSON.stringify({
|
|
197
|
+
path: filePath,
|
|
198
|
+
data: file.data
|
|
199
|
+
})
|
|
200
|
+
);
|
|
69
201
|
}
|
|
70
|
-
})
|
|
71
|
-
(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
};
|
|
77
|
-
callback(void 0, String(file.value), file.map ?? void 0);
|
|
78
|
-
},
|
|
79
|
-
(error) => {
|
|
80
|
-
const fpath = path2.relative(context, filePath);
|
|
81
|
-
error.message = `${fpath}:${error.name}: ${error.message}`;
|
|
82
|
-
callback(error);
|
|
83
|
-
}
|
|
84
|
-
);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
if (!(error instanceof Error)) throw error;
|
|
204
|
+
const fpath = path3.relative(context, filePath);
|
|
205
|
+
error.message = `${fpath}:${error.name}: ${error.message}`;
|
|
206
|
+
callback(error);
|
|
207
|
+
}
|
|
85
208
|
}
|
|
86
209
|
export {
|
|
87
210
|
loader as default
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { NextConfig } from 'next';
|
|
2
|
+
|
|
3
|
+
interface CreateMDXOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Path to source configuration file
|
|
6
|
+
*/
|
|
7
|
+
configPath?: string;
|
|
8
|
+
}
|
|
9
|
+
declare function createMDX({ configPath, }?: CreateMDXOptions): (nextConfig?: NextConfig) => NextConfig;
|
|
10
|
+
|
|
11
|
+
declare function postInstall(configPath?: string): Promise<void>;
|
|
12
|
+
|
|
13
|
+
export { type CreateMDXOptions, createMDX, postInstall };
|