@docusaurus/mdx-loader 3.5.2 → 3.6.0-canary-6134
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/README.md +0 -1
- package/lib/createMDXLoader.d.ts +18 -0
- package/lib/createMDXLoader.d.ts.map +1 -0
- package/lib/createMDXLoader.js +48 -0
- package/lib/createMDXLoader.js.map +1 -0
- package/lib/index.d.ts +3 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -1
- package/lib/loader.d.ts +1 -23
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +120 -139
- package/lib/loader.js.map +1 -1
- package/lib/options.d.ts +33 -0
- package/lib/options.d.ts.map +1 -0
- package/lib/options.js +9 -0
- package/lib/options.js.map +1 -0
- package/lib/preprocessor.d.ts +1 -1
- package/lib/preprocessor.d.ts.map +1 -1
- package/lib/processor.d.ts +12 -6
- package/lib/processor.d.ts.map +1 -1
- package/lib/processor.js +19 -15
- package/lib/processor.js.map +1 -1
- package/lib/remark/transformImage/index.d.ts.map +1 -1
- package/lib/remark/transformImage/index.js +11 -9
- package/lib/remark/transformImage/index.js.map +1 -1
- package/lib/remark/transformLinks/index.d.ts.map +1 -1
- package/lib/remark/transformLinks/index.js +11 -9
- package/lib/remark/transformLinks/index.js.map +1 -1
- package/lib/remark/unusedDirectives/index.d.ts.map +1 -1
- package/lib/remark/unusedDirectives/index.js +1 -0
- package/lib/remark/unusedDirectives/index.js.map +1 -1
- package/lib/utils.d.ts +41 -0
- package/lib/utils.d.ts.map +1 -0
- package/lib/utils.js +108 -0
- package/lib/utils.js.map +1 -0
- package/package.json +6 -6
- package/src/createMDXLoader.ts +67 -0
- package/src/index.ts +4 -1
- package/src/loader.ts +163 -198
- package/src/options.ts +32 -0
- package/src/preprocessor.ts +1 -1
- package/src/processor.ts +35 -31
- package/src/remark/transformImage/index.ts +17 -15
- package/src/remark/transformLinks/index.ts +19 -15
- package/src/remark/unusedDirectives/index.ts +1 -0
- package/src/types.d.mts +3 -1
- package/src/utils.ts +151 -0
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
toMessageRelativeFilePath,
|
|
13
13
|
posixPath,
|
|
14
14
|
escapePath,
|
|
15
|
-
getFileLoaderUtils,
|
|
16
15
|
findAsyncSequential,
|
|
16
|
+
getFileLoaderUtils,
|
|
17
17
|
} from '@docusaurus/utils';
|
|
18
18
|
import escapeHtml from 'escape-html';
|
|
19
19
|
import {assetRequireAttributeValue, transformNode} from '../utils';
|
|
@@ -24,10 +24,6 @@ import type {MdxJsxTextElement} from 'mdast-util-mdx';
|
|
|
24
24
|
import type {Parent} from 'unist';
|
|
25
25
|
import type {Link, Literal} from 'mdast';
|
|
26
26
|
|
|
27
|
-
const {
|
|
28
|
-
loaders: {inlineMarkdownLinkFileLoader},
|
|
29
|
-
} = getFileLoaderUtils();
|
|
30
|
-
|
|
31
27
|
type PluginOptions = {
|
|
32
28
|
staticDirs: string[];
|
|
33
29
|
siteDir: string;
|
|
@@ -35,6 +31,7 @@ type PluginOptions = {
|
|
|
35
31
|
|
|
36
32
|
type Context = PluginOptions & {
|
|
37
33
|
filePath: string;
|
|
34
|
+
inlineMarkdownLinkFileLoader: string;
|
|
38
35
|
};
|
|
39
36
|
|
|
40
37
|
type Target = [node: Link, index: number, parent: Parent];
|
|
@@ -45,7 +42,7 @@ type Target = [node: Link, index: number, parent: Parent];
|
|
|
45
42
|
async function toAssetRequireNode(
|
|
46
43
|
[node]: Target,
|
|
47
44
|
assetPath: string,
|
|
48
|
-
|
|
45
|
+
context: Context,
|
|
49
46
|
) {
|
|
50
47
|
// MdxJsxTextElement => see https://github.com/facebook/docusaurus/pull/8288#discussion_r1125871405
|
|
51
48
|
const jsxNode = node as unknown as MdxJsxTextElement;
|
|
@@ -53,7 +50,7 @@ async function toAssetRequireNode(
|
|
|
53
50
|
|
|
54
51
|
// require("assets/file.pdf") means requiring from a package called assets
|
|
55
52
|
const relativeAssetPath = `./${posixPath(
|
|
56
|
-
path.relative(path.dirname(filePath), assetPath),
|
|
53
|
+
path.relative(path.dirname(context.filePath), assetPath),
|
|
57
54
|
)}`;
|
|
58
55
|
|
|
59
56
|
const parsedUrl = url.parse(node.url);
|
|
@@ -65,7 +62,9 @@ async function toAssetRequireNode(
|
|
|
65
62
|
path.extname(relativeAssetPath) === '.json'
|
|
66
63
|
? `${relativeAssetPath.replace('.json', '.raw')}!=`
|
|
67
64
|
: ''
|
|
68
|
-
}${inlineMarkdownLinkFileLoader}${
|
|
65
|
+
}${context.inlineMarkdownLinkFileLoader}${
|
|
66
|
+
escapePath(relativeAssetPath) + search
|
|
67
|
+
}`;
|
|
69
68
|
|
|
70
69
|
attributes.push({
|
|
71
70
|
type: 'mdxJsxAttribute',
|
|
@@ -196,7 +195,7 @@ async function processLinkNode(target: Target, context: Context) {
|
|
|
196
195
|
context,
|
|
197
196
|
);
|
|
198
197
|
if (assetPath) {
|
|
199
|
-
await toAssetRequireNode(target, assetPath, context
|
|
198
|
+
await toAssetRequireNode(target, assetPath, context);
|
|
200
199
|
}
|
|
201
200
|
}
|
|
202
201
|
|
|
@@ -204,14 +203,19 @@ export default function plugin(options: PluginOptions): Transformer {
|
|
|
204
203
|
return async (root, vfile) => {
|
|
205
204
|
const {visit} = await import('unist-util-visit');
|
|
206
205
|
|
|
206
|
+
const fileLoaderUtils = getFileLoaderUtils(
|
|
207
|
+
vfile.data.compilerName === 'server',
|
|
208
|
+
);
|
|
209
|
+
const context: Context = {
|
|
210
|
+
...options,
|
|
211
|
+
filePath: vfile.path!,
|
|
212
|
+
inlineMarkdownLinkFileLoader:
|
|
213
|
+
fileLoaderUtils.loaders.inlineMarkdownLinkFileLoader,
|
|
214
|
+
};
|
|
215
|
+
|
|
207
216
|
const promises: Promise<void>[] = [];
|
|
208
217
|
visit(root, 'link', (node: Link, index, parent) => {
|
|
209
|
-
promises.push(
|
|
210
|
-
processLinkNode([node, index, parent!], {
|
|
211
|
-
...options,
|
|
212
|
-
filePath: vfile.path!,
|
|
213
|
-
}),
|
|
214
|
-
);
|
|
218
|
+
promises.push(processLinkNode([node, index, parent!], context));
|
|
215
219
|
});
|
|
216
220
|
await Promise.all(promises);
|
|
217
221
|
};
|
|
@@ -155,6 +155,7 @@ const plugin: Plugin = function plugin(this: Processor): Transformer {
|
|
|
155
155
|
// We only enable these warnings for the client compiler
|
|
156
156
|
// This avoids emitting duplicate warnings in prod mode
|
|
157
157
|
// Note: the client compiler is used in both dev/prod modes
|
|
158
|
+
// Also: the client compiler is what gets used when using crossCompilerCache
|
|
158
159
|
if (file.data.compilerName === 'client') {
|
|
159
160
|
logUnusedDirectivesWarning({
|
|
160
161
|
directives: unusedDirectives,
|
package/src/types.d.mts
CHANGED
package/src/utils.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import logger from '@docusaurus/logger';
|
|
9
|
+
import {escapePath, type WebpackCompilerName} from '@docusaurus/utils';
|
|
10
|
+
import {getProcessor, type SimpleProcessorResult} from './processor';
|
|
11
|
+
import {validateMDXFrontMatter} from './frontMatter';
|
|
12
|
+
import preprocessor from './preprocessor';
|
|
13
|
+
import type {Options} from './options';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Converts assets an object with Webpack require calls code.
|
|
17
|
+
* This is useful for mdx files to reference co-located assets using relative
|
|
18
|
+
* paths. Those assets should enter the Webpack assets pipeline and be hashed.
|
|
19
|
+
* For now, we only handle that for images and paths starting with `./`:
|
|
20
|
+
*
|
|
21
|
+
* `{image: "./myImage.png"}` => `{image: require("./myImage.png")}`
|
|
22
|
+
*/
|
|
23
|
+
export function createAssetsExportCode({
|
|
24
|
+
assets,
|
|
25
|
+
inlineMarkdownAssetImageFileLoader,
|
|
26
|
+
}: {
|
|
27
|
+
assets: unknown;
|
|
28
|
+
inlineMarkdownAssetImageFileLoader: string;
|
|
29
|
+
}): string {
|
|
30
|
+
if (
|
|
31
|
+
typeof assets !== 'object' ||
|
|
32
|
+
!assets ||
|
|
33
|
+
Object.keys(assets).length === 0
|
|
34
|
+
) {
|
|
35
|
+
return 'undefined';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// TODO implementation can be completed/enhanced
|
|
39
|
+
function createAssetValueCode(assetValue: unknown): string | undefined {
|
|
40
|
+
if (Array.isArray(assetValue)) {
|
|
41
|
+
const arrayItemCodes = assetValue.map(
|
|
42
|
+
(item: unknown) => createAssetValueCode(item) ?? 'undefined',
|
|
43
|
+
);
|
|
44
|
+
return `[${arrayItemCodes.join(', ')}]`;
|
|
45
|
+
}
|
|
46
|
+
// Only process string values starting with ./
|
|
47
|
+
// We could enhance this logic and check if file exists on disc?
|
|
48
|
+
if (typeof assetValue === 'string' && assetValue.startsWith('./')) {
|
|
49
|
+
// TODO do we have other use-cases than image assets?
|
|
50
|
+
// Probably not worth adding more support, as we want to move to Webpack 5 new asset system (https://github.com/facebook/docusaurus/pull/4708)
|
|
51
|
+
return `require("${inlineMarkdownAssetImageFileLoader}${escapePath(
|
|
52
|
+
assetValue,
|
|
53
|
+
)}").default`;
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const assetEntries = Object.entries(assets);
|
|
59
|
+
|
|
60
|
+
const codeLines = assetEntries
|
|
61
|
+
.map(([key, value]: [string, unknown]) => {
|
|
62
|
+
const assetRequireCode = createAssetValueCode(value);
|
|
63
|
+
return assetRequireCode ? `"${key}": ${assetRequireCode},` : undefined;
|
|
64
|
+
})
|
|
65
|
+
.filter(Boolean);
|
|
66
|
+
|
|
67
|
+
return `{\n${codeLines.join('\n')}\n}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* data.contentTitle is set by the remark contentTitle plugin
|
|
72
|
+
*/
|
|
73
|
+
export function extractContentTitleData(data: {
|
|
74
|
+
[key: string]: unknown;
|
|
75
|
+
}): string | undefined {
|
|
76
|
+
return data.contentTitle as string | undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function compileToJSX({
|
|
80
|
+
filePath,
|
|
81
|
+
fileContent,
|
|
82
|
+
frontMatter,
|
|
83
|
+
options,
|
|
84
|
+
compilerName,
|
|
85
|
+
}: {
|
|
86
|
+
filePath: string;
|
|
87
|
+
fileContent: string;
|
|
88
|
+
frontMatter: Record<string, unknown>;
|
|
89
|
+
options: Options;
|
|
90
|
+
compilerName: WebpackCompilerName;
|
|
91
|
+
}): Promise<SimpleProcessorResult> {
|
|
92
|
+
const preprocessedFileContent = preprocessor({
|
|
93
|
+
fileContent,
|
|
94
|
+
filePath,
|
|
95
|
+
admonitions: options.admonitions,
|
|
96
|
+
markdownConfig: options.markdownConfig,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const mdxFrontMatter = validateMDXFrontMatter(frontMatter.mdx);
|
|
100
|
+
|
|
101
|
+
const processor = await getProcessor({
|
|
102
|
+
filePath,
|
|
103
|
+
options,
|
|
104
|
+
mdxFrontMatter,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
return await processor.process({
|
|
109
|
+
content: preprocessedFileContent,
|
|
110
|
+
filePath,
|
|
111
|
+
frontMatter,
|
|
112
|
+
compilerName,
|
|
113
|
+
});
|
|
114
|
+
} catch (errorUnknown) {
|
|
115
|
+
const error = errorUnknown as Error;
|
|
116
|
+
|
|
117
|
+
// MDX can emit errors that have useful extra attributes
|
|
118
|
+
const errorJSON = JSON.stringify(error, null, 2);
|
|
119
|
+
const errorDetails =
|
|
120
|
+
errorJSON === '{}'
|
|
121
|
+
? // regular JS error case: print stacktrace
|
|
122
|
+
error.stack ?? 'N/A'
|
|
123
|
+
: // MDX error: print extra attributes + stacktrace
|
|
124
|
+
`${errorJSON}\n${error.stack}`;
|
|
125
|
+
|
|
126
|
+
throw new Error(
|
|
127
|
+
`MDX compilation failed for file ${logger.path(filePath)}\nCause: ${
|
|
128
|
+
error.message
|
|
129
|
+
}\nDetails:\n${errorDetails}`,
|
|
130
|
+
// TODO error cause doesn't seem to be used by Webpack stats.errors :s
|
|
131
|
+
{cause: error},
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// TODO Docusaurus v4, remove temporary polyfill when upgrading to Node 22+
|
|
137
|
+
export interface PromiseWithResolvers<T> {
|
|
138
|
+
promise: Promise<T>;
|
|
139
|
+
resolve: (value: T | PromiseLike<T>) => void;
|
|
140
|
+
reject: (reason?: any) => void;
|
|
141
|
+
}
|
|
142
|
+
// TODO Docusaurus v4, remove temporary polyfill when upgrading to Node 22+
|
|
143
|
+
export function promiseWithResolvers<T>(): PromiseWithResolvers<T> {
|
|
144
|
+
// @ts-expect-error: it's fine
|
|
145
|
+
const out: PromiseWithResolvers<T> = {};
|
|
146
|
+
out.promise = new Promise((resolve, reject) => {
|
|
147
|
+
out.resolve = resolve;
|
|
148
|
+
out.reject = reject;
|
|
149
|
+
});
|
|
150
|
+
return out;
|
|
151
|
+
}
|