@docusaurus/mdx-loader 3.0.0-beta.0 → 3.0.0-rc.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.
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +20 -11
- package/lib/loader.js.map +1 -1
- package/lib/processor.d.ts +13 -2
- package/lib/processor.d.ts.map +1 -1
- package/lib/processor.js +27 -16
- package/lib/processor.js.map +1 -1
- package/lib/remark/admonitions/index.d.ts.map +1 -1
- package/lib/remark/admonitions/index.js +5 -10
- package/lib/remark/admonitions/index.js.map +1 -1
- package/lib/remark/contentTitle/index.d.ts +15 -0
- package/lib/remark/contentTitle/index.d.ts.map +1 -0
- package/lib/remark/contentTitle/index.js +38 -0
- package/lib/remark/contentTitle/index.js.map +1 -0
- package/lib/remark/details/index.d.ts.map +1 -1
- package/lib/remark/details/index.js +3 -4
- package/lib/remark/details/index.js.map +1 -1
- package/lib/remark/head/index.d.ts.map +1 -1
- package/lib/remark/head/index.js +3 -4
- package/lib/remark/head/index.js.map +1 -1
- package/lib/remark/headings/index.d.ts.map +1 -1
- package/lib/remark/headings/index.js +2 -3
- package/lib/remark/headings/index.js.map +1 -1
- package/lib/remark/mdx1Compat/codeCompatPlugin.d.ts.map +1 -1
- package/lib/remark/mdx1Compat/codeCompatPlugin.js +4 -9
- package/lib/remark/mdx1Compat/codeCompatPlugin.js.map +1 -1
- package/lib/remark/mermaid/index.d.ts.map +1 -1
- package/lib/remark/mermaid/index.js +5 -5
- package/lib/remark/mermaid/index.js.map +1 -1
- package/lib/remark/toc/index.d.ts.map +1 -1
- package/lib/remark/toc/index.js +2 -2
- package/lib/remark/toc/index.js.map +1 -1
- package/lib/remark/transformImage/index.d.ts.map +1 -1
- package/lib/remark/transformImage/index.js +8 -7
- 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 +8 -7
- package/lib/remark/transformLinks/index.js.map +1 -1
- package/lib/remark/unusedDirectives/index.d.ts +4 -0
- package/lib/remark/unusedDirectives/index.d.ts.map +1 -0
- package/lib/remark/unusedDirectives/index.js +117 -0
- package/lib/remark/unusedDirectives/index.js.map +1 -0
- package/lib/remark/utils/index.d.ts +10 -3
- package/lib/remark/utils/index.d.ts.map +1 -1
- package/lib/remark/utils/index.js +19 -1
- package/lib/remark/utils/index.js.map +1 -1
- package/package.json +26 -25
- package/src/loader.ts +29 -17
- package/src/processor.ts +36 -18
- package/src/remark/admonitions/index.ts +3 -1
- package/src/remark/contentTitle/index.ts +55 -0
- package/src/remark/details/index.ts +2 -2
- package/src/remark/head/index.ts +2 -2
- package/src/remark/headings/index.ts +1 -1
- package/src/remark/mdx1Compat/codeCompatPlugin.ts +6 -8
- package/src/remark/mermaid/index.ts +7 -4
- package/src/remark/toc/index.ts +11 -5
- package/src/remark/transformImage/index.ts +9 -10
- package/src/remark/transformLinks/index.ts +9 -10
- package/src/remark/unusedDirectives/index.ts +167 -0
- package/src/remark/utils/index.ts +23 -2
- package/src/types.d.mts +34 -0
package/src/processor.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import emoji from 'remark-emoji';
|
|
9
8
|
import headings from './remark/headings';
|
|
9
|
+
import contentTitle from './remark/contentTitle';
|
|
10
10
|
import toc from './remark/toc';
|
|
11
11
|
import transformImage from './remark/transformImage';
|
|
12
12
|
import transformLinks from './remark/transformLinks';
|
|
@@ -14,8 +14,10 @@ import details from './remark/details';
|
|
|
14
14
|
import head from './remark/head';
|
|
15
15
|
import mermaid from './remark/mermaid';
|
|
16
16
|
import transformAdmonitions from './remark/admonitions';
|
|
17
|
+
import unusedDirectivesWarning from './remark/unusedDirectives';
|
|
17
18
|
import codeCompatPlugin from './remark/mdx1Compat/codeCompatPlugin';
|
|
18
19
|
import {getFormat} from './format';
|
|
20
|
+
import type {WebpackCompilerName} from '@docusaurus/utils';
|
|
19
21
|
import type {MDXFrontMatter} from './frontMatter';
|
|
20
22
|
import type {Options} from './loader';
|
|
21
23
|
import type {AdmonitionOptions} from './remark/admonitions';
|
|
@@ -28,24 +30,27 @@ import type {ProcessorOptions} from '@mdx-js/mdx';
|
|
|
28
30
|
// See https://github.com/microsoft/TypeScript/issues/49721#issuecomment-1517839391
|
|
29
31
|
type Pluggable = any; // TODO fix this asap
|
|
30
32
|
|
|
33
|
+
type SimpleProcessorResult = {content: string; data: {[key: string]: unknown}};
|
|
34
|
+
|
|
31
35
|
// TODO alt interface because impossible to import type Processor (ESM + TS :/)
|
|
32
36
|
type SimpleProcessor = {
|
|
33
37
|
process: ({
|
|
34
38
|
content,
|
|
35
39
|
filePath,
|
|
40
|
+
frontMatter,
|
|
41
|
+
compilerName,
|
|
36
42
|
}: {
|
|
37
43
|
content: string;
|
|
38
44
|
filePath: string;
|
|
39
|
-
|
|
45
|
+
frontMatter: {[key: string]: unknown};
|
|
46
|
+
compilerName: WebpackCompilerName;
|
|
47
|
+
}) => Promise<SimpleProcessorResult>;
|
|
40
48
|
};
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
beforeDefaultRemarkPlugins: [],
|
|
47
|
-
beforeDefaultRehypePlugins: [],
|
|
48
|
-
};
|
|
50
|
+
async function getDefaultRemarkPlugins(): Promise<MDXPlugin[]> {
|
|
51
|
+
const {default: emoji} = await import('remark-emoji');
|
|
52
|
+
return [headings, emoji, toc];
|
|
53
|
+
}
|
|
49
54
|
|
|
50
55
|
export type MDXPlugin = Pluggable;
|
|
51
56
|
|
|
@@ -74,11 +79,15 @@ function getAdmonitionsPlugins(
|
|
|
74
79
|
// Need to be async due to ESM dynamic imports...
|
|
75
80
|
async function createProcessorFactory() {
|
|
76
81
|
const {createProcessor: createMdxProcessor} = await import('@mdx-js/mdx');
|
|
82
|
+
const {default: frontmatter} = await import('remark-frontmatter');
|
|
77
83
|
const {default: rehypeRaw} = await import('rehype-raw');
|
|
78
84
|
const {default: gfm} = await import('remark-gfm');
|
|
79
85
|
// TODO using fork until PR merged: https://github.com/leebyron/remark-comment/pull/3
|
|
80
86
|
const {default: comment} = await import('@slorber/remark-comment');
|
|
81
87
|
const {default: directive} = await import('remark-directive');
|
|
88
|
+
const {VFile} = await import('vfile');
|
|
89
|
+
|
|
90
|
+
const defaultRemarkPlugins = await getDefaultRemarkPlugins();
|
|
82
91
|
|
|
83
92
|
// /!\ this method is synchronous on purpose
|
|
84
93
|
// Using async code here can create cache entry race conditions!
|
|
@@ -91,9 +100,11 @@ async function createProcessorFactory() {
|
|
|
91
100
|
}): SimpleProcessor {
|
|
92
101
|
const remarkPlugins: MDXPlugin[] = [
|
|
93
102
|
...(options.beforeDefaultRemarkPlugins ?? []),
|
|
103
|
+
frontmatter,
|
|
94
104
|
directive,
|
|
105
|
+
[contentTitle, {removeContentTitle: options.removeContentTitle}],
|
|
95
106
|
...getAdmonitionsPlugins(options.admonitions ?? false),
|
|
96
|
-
...
|
|
107
|
+
...defaultRemarkPlugins,
|
|
97
108
|
details,
|
|
98
109
|
head,
|
|
99
110
|
...(options.markdownConfig.mermaid ? [mermaid] : []),
|
|
@@ -114,6 +125,7 @@ async function createProcessorFactory() {
|
|
|
114
125
|
gfm,
|
|
115
126
|
options.markdownConfig.mdx1Compat.comments ? comment : null,
|
|
116
127
|
...(options.remarkPlugins ?? []),
|
|
128
|
+
unusedDirectivesWarning,
|
|
117
129
|
].filter((plugin): plugin is MDXPlugin => Boolean(plugin));
|
|
118
130
|
|
|
119
131
|
// codeCompatPlugin needs to be applied last after user-provided plugins
|
|
@@ -122,7 +134,6 @@ async function createProcessorFactory() {
|
|
|
122
134
|
|
|
123
135
|
const rehypePlugins: MDXPlugin[] = [
|
|
124
136
|
...(options.beforeDefaultRehypePlugins ?? []),
|
|
125
|
-
...DEFAULT_OPTIONS.rehypePlugins,
|
|
126
137
|
...(options.rehypePlugins ?? []),
|
|
127
138
|
];
|
|
128
139
|
|
|
@@ -158,13 +169,20 @@ async function createProcessorFactory() {
|
|
|
158
169
|
});
|
|
159
170
|
|
|
160
171
|
return {
|
|
161
|
-
process: async ({content, filePath}) =>
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
172
|
+
process: async ({content, filePath, frontMatter, compilerName}) => {
|
|
173
|
+
const vfile = new VFile({
|
|
174
|
+
value: content,
|
|
175
|
+
path: filePath,
|
|
176
|
+
data: {
|
|
177
|
+
frontMatter,
|
|
178
|
+
compilerName,
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
return mdxProcessor.process(vfile).then((result) => ({
|
|
182
|
+
content: result.toString(),
|
|
183
|
+
data: result.data,
|
|
184
|
+
}));
|
|
185
|
+
},
|
|
168
186
|
};
|
|
169
187
|
}
|
|
170
188
|
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import visit from 'unist-util-visit';
|
|
8
7
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
9
8
|
import type {Transformer, Processor} from 'unified';
|
|
10
9
|
|
|
@@ -67,6 +66,7 @@ function parseDirective(directive: ContainerDirective): {
|
|
|
67
66
|
contentNodes: DirectiveContent;
|
|
68
67
|
} {
|
|
69
68
|
const hasDirectiveLabel =
|
|
69
|
+
// @ts-expect-error: fine
|
|
70
70
|
directive.children?.[0]?.data?.directiveLabel === true;
|
|
71
71
|
if (hasDirectiveLabel) {
|
|
72
72
|
const [directiveLabel, ...contentNodes] = directive.children;
|
|
@@ -92,6 +92,8 @@ const plugin: Plugin = function plugin(
|
|
|
92
92
|
const {keywords} = normalizeAdmonitionOptions(optionsInput);
|
|
93
93
|
|
|
94
94
|
return async (root) => {
|
|
95
|
+
const {visit} = await import('unist-util-visit');
|
|
96
|
+
|
|
95
97
|
visit(root, (node) => {
|
|
96
98
|
if (node.type === 'containerDirective') {
|
|
97
99
|
const directive = node as ContainerDirective;
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
9
|
+
import type {Transformer} from 'unified';
|
|
10
|
+
import type {Heading} from 'mdast';
|
|
11
|
+
|
|
12
|
+
// TODO as of April 2023, no way to import/re-export this ESM type easily :/
|
|
13
|
+
// TODO upgrade to TS 5.3
|
|
14
|
+
// See https://github.com/microsoft/TypeScript/issues/49721#issuecomment-1517839391
|
|
15
|
+
// import type {Plugin} from 'unified';
|
|
16
|
+
type Plugin = any; // TODO fix this asap
|
|
17
|
+
|
|
18
|
+
interface PluginOptions {
|
|
19
|
+
removeContentTitle?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A remark plugin to extract the h1 heading found in Markdown files
|
|
24
|
+
* This is exposed as "data.contentTitle" to the processed vfile
|
|
25
|
+
* Also gives the ability to strip that content title (used for the blog plugin)
|
|
26
|
+
*/
|
|
27
|
+
const plugin: Plugin = function plugin(
|
|
28
|
+
options: PluginOptions = {},
|
|
29
|
+
): Transformer {
|
|
30
|
+
// content title is
|
|
31
|
+
const removeContentTitle = options.removeContentTitle ?? false;
|
|
32
|
+
|
|
33
|
+
return async (root, vfile) => {
|
|
34
|
+
const {toString} = await import('mdast-util-to-string');
|
|
35
|
+
const {visit, EXIT} = await import('unist-util-visit');
|
|
36
|
+
|
|
37
|
+
visit(root, 'heading', (headingNode: Heading, index, parent) => {
|
|
38
|
+
if (headingNode.depth === 1) {
|
|
39
|
+
vfile.data.contentTitle = toString(headingNode);
|
|
40
|
+
if (removeContentTitle) {
|
|
41
|
+
// @ts-expect-error: TODO how to fix?
|
|
42
|
+
parent!.children.splice(index, 1);
|
|
43
|
+
}
|
|
44
|
+
return EXIT; // We only handle the very first heading
|
|
45
|
+
}
|
|
46
|
+
// We only handle contentTitle if it's the very first heading found
|
|
47
|
+
if (headingNode.depth >= 1) {
|
|
48
|
+
return EXIT;
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default plugin;
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import visit from 'unist-util-visit';
|
|
9
8
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
10
9
|
import type {Transformer} from 'unified';
|
|
11
10
|
|
|
@@ -15,7 +14,8 @@ import type {MdxJsxFlowElement} from 'mdast-util-mdx';
|
|
|
15
14
|
// Transform <details> to <Details>
|
|
16
15
|
// MDX 2 doesn't allow to substitute html elements with the provider anymore
|
|
17
16
|
export default function plugin(): Transformer {
|
|
18
|
-
return (root) => {
|
|
17
|
+
return async (root) => {
|
|
18
|
+
const {visit} = await import('unist-util-visit');
|
|
19
19
|
visit(root, 'mdxJsxFlowElement', (node: MdxJsxFlowElement) => {
|
|
20
20
|
if (node.name === 'details') {
|
|
21
21
|
node.name = 'Details';
|
package/src/remark/head/index.ts
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import visit from 'unist-util-visit';
|
|
9
8
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
10
9
|
import type {Transformer} from 'unified';
|
|
11
10
|
|
|
@@ -15,7 +14,8 @@ import type {MdxJsxFlowElement} from 'mdast-util-mdx';
|
|
|
15
14
|
// Transform <head> to <Head>
|
|
16
15
|
// MDX 2 doesn't allow to substitute html elements with the provider anymore
|
|
17
16
|
export default function plugin(): Transformer {
|
|
18
|
-
return (root) => {
|
|
17
|
+
return async (root) => {
|
|
18
|
+
const {visit} = await import('unist-util-visit');
|
|
19
19
|
visit(root, 'mdxJsxFlowElement', (node: MdxJsxFlowElement) => {
|
|
20
20
|
if (node.name === 'head') {
|
|
21
21
|
node.name = 'Head';
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
/* Based on remark-slug (https://github.com/remarkjs/remark-slug) and gatsby-remark-autolink-headers (https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-remark-autolink-headers) */
|
|
9
9
|
|
|
10
10
|
import {parseMarkdownHeadingId, createSlugger} from '@docusaurus/utils';
|
|
11
|
-
import visit from 'unist-util-visit';
|
|
12
11
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
13
12
|
import type {Transformer} from 'unified';
|
|
14
13
|
import type {Heading, Text} from 'mdast';
|
|
@@ -16,6 +15,7 @@ import type {Heading, Text} from 'mdast';
|
|
|
16
15
|
export default function plugin(): Transformer {
|
|
17
16
|
return async (root) => {
|
|
18
17
|
const {toString} = await import('mdast-util-to-string');
|
|
18
|
+
const {visit} = await import('unist-util-visit');
|
|
19
19
|
|
|
20
20
|
const slugs = createSlugger();
|
|
21
21
|
visit(root, 'heading', (headingNode: Heading) => {
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import visit from 'unist-util-visit';
|
|
9
8
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
10
9
|
import type {Transformer, Processor} from 'unified';
|
|
11
10
|
import type {Code} from 'mdast';
|
|
@@ -18,19 +17,18 @@ import type {Code} from 'mdast';
|
|
|
18
17
|
// To make theme-classic/src/theme/MDXComponents/Pre work
|
|
19
18
|
// we need to fill two properties that mdx v2 doesn't provide anymore
|
|
20
19
|
export default function codeCompatPlugin(this: Processor): Transformer {
|
|
21
|
-
return (root) => {
|
|
20
|
+
return async (root) => {
|
|
21
|
+
const {visit} = await import('unist-util-visit');
|
|
22
|
+
|
|
22
23
|
visit(root, 'code', (node: Code) => {
|
|
23
24
|
node.data = node.data || {};
|
|
25
|
+
|
|
24
26
|
node.data.hProperties = node.data.hProperties || {};
|
|
25
|
-
|
|
26
|
-
(node.data.hProperties as any).metastring = node.meta;
|
|
27
|
+
node.data.hProperties.metastring = node.meta;
|
|
27
28
|
|
|
28
29
|
// Retrocompatible support for live codeblock metastring
|
|
29
30
|
// Not really the appropriate place to handle that :s
|
|
30
|
-
|
|
31
|
-
(node.data.hProperties as any).live = node.meta
|
|
32
|
-
?.split(' ')
|
|
33
|
-
.includes('live');
|
|
31
|
+
node.data.hProperties.live = node.meta?.split(' ').includes('live');
|
|
34
32
|
});
|
|
35
33
|
};
|
|
36
34
|
}
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import {transformNode} from '../utils';
|
|
9
|
+
|
|
9
10
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
10
11
|
import type {Transformer} from 'unified';
|
|
11
12
|
import type {Code} from 'mdast';
|
|
@@ -15,11 +16,13 @@ import type {Code} from 'mdast';
|
|
|
15
16
|
// https://github.com/facebook/docusaurus/issues/6370), this should be provided
|
|
16
17
|
// by theme-mermaid itself
|
|
17
18
|
export default function plugin(): Transformer {
|
|
18
|
-
return (root) => {
|
|
19
|
-
visit(
|
|
19
|
+
return async (root) => {
|
|
20
|
+
const {visit} = await import('unist-util-visit');
|
|
21
|
+
|
|
22
|
+
visit(root, 'code', (node: Code) => {
|
|
20
23
|
if (node.lang === 'mermaid') {
|
|
21
24
|
// TODO migrate to mdxJsxFlowElement? cf admonitions
|
|
22
|
-
|
|
25
|
+
transformNode(node, {
|
|
23
26
|
type: 'mermaidCodeBlock',
|
|
24
27
|
data: {
|
|
25
28
|
hName: 'mermaid',
|
package/src/remark/toc/index.ts
CHANGED
|
@@ -8,16 +8,19 @@
|
|
|
8
8
|
import {parse, type ParserOptions} from '@babel/parser';
|
|
9
9
|
import traverse from '@babel/traverse';
|
|
10
10
|
import stringifyObject from 'stringify-object';
|
|
11
|
-
import visit from 'unist-util-visit';
|
|
12
11
|
import {toValue} from '../utils';
|
|
13
12
|
import type {Identifier} from '@babel/types';
|
|
14
13
|
import type {Node, Parent} from 'unist';
|
|
15
14
|
import type {Heading, Literal} from 'mdast';
|
|
16
15
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
17
16
|
import type {Transformer} from 'unified';
|
|
17
|
+
import type {
|
|
18
|
+
MdxjsEsm,
|
|
19
|
+
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
20
|
+
} from 'mdast-util-mdx';
|
|
18
21
|
|
|
19
22
|
// TODO as of April 2023, no way to import/re-export this ESM type easily :/
|
|
20
|
-
//
|
|
23
|
+
// TODO upgrade to TS 5.3
|
|
21
24
|
// See https://github.com/microsoft/TypeScript/issues/49721#issuecomment-1517839391
|
|
22
25
|
// import type {Plugin} from 'unified';
|
|
23
26
|
type Plugin = any; // TODO fix this asap
|
|
@@ -88,6 +91,8 @@ const plugin: Plugin = function plugin(
|
|
|
88
91
|
|
|
89
92
|
return async (root) => {
|
|
90
93
|
const {toString} = await import('mdast-util-to-string');
|
|
94
|
+
const {visit} = await import('unist-util-visit');
|
|
95
|
+
|
|
91
96
|
const headings: TOCItem[] = [];
|
|
92
97
|
|
|
93
98
|
visit(root, 'heading', (child: Heading) => {
|
|
@@ -100,11 +105,12 @@ const plugin: Plugin = function plugin(
|
|
|
100
105
|
|
|
101
106
|
headings.push({
|
|
102
107
|
value: toValue(child, toString),
|
|
103
|
-
id: child.data!.id
|
|
108
|
+
id: child.data!.id!,
|
|
104
109
|
level: child.depth,
|
|
105
110
|
});
|
|
106
111
|
});
|
|
107
|
-
|
|
112
|
+
|
|
113
|
+
const {children} = root as Parent;
|
|
108
114
|
const targetIndex = await getOrCreateExistingTargetIndex(children, name);
|
|
109
115
|
|
|
110
116
|
if (headings?.length) {
|
|
@@ -115,7 +121,7 @@ const plugin: Plugin = function plugin(
|
|
|
115
121
|
|
|
116
122
|
export default plugin;
|
|
117
123
|
|
|
118
|
-
async function createExportNode(name: string, object: any) {
|
|
124
|
+
async function createExportNode(name: string, object: any): Promise<MdxjsEsm> {
|
|
119
125
|
const {valueToEstree} = await import('estree-util-value-to-estree');
|
|
120
126
|
|
|
121
127
|
return {
|
|
@@ -16,11 +16,10 @@ import {
|
|
|
16
16
|
getFileLoaderUtils,
|
|
17
17
|
findAsyncSequential,
|
|
18
18
|
} from '@docusaurus/utils';
|
|
19
|
-
import visit from 'unist-util-visit';
|
|
20
19
|
import escapeHtml from 'escape-html';
|
|
21
20
|
import sizeOf from 'image-size';
|
|
22
21
|
import logger from '@docusaurus/logger';
|
|
23
|
-
import {assetRequireAttributeValue} from '../utils';
|
|
22
|
+
import {assetRequireAttributeValue, transformNode} from '../utils';
|
|
24
23
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
25
24
|
import type {Transformer} from 'unified';
|
|
26
25
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
@@ -110,14 +109,12 @@ ${(err as Error).message}`;
|
|
|
110
109
|
}
|
|
111
110
|
}
|
|
112
111
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
jsxNode.attributes = attributes;
|
|
120
|
-
jsxNode.children = [];
|
|
112
|
+
transformNode(jsxNode, {
|
|
113
|
+
type: 'mdxJsxTextElement',
|
|
114
|
+
name: 'img',
|
|
115
|
+
attributes,
|
|
116
|
+
children: [],
|
|
117
|
+
});
|
|
121
118
|
}
|
|
122
119
|
|
|
123
120
|
async function ensureImageFileExist(imagePath: string, sourceFilePath: string) {
|
|
@@ -194,6 +191,8 @@ async function processImageNode(target: Target, context: Context) {
|
|
|
194
191
|
|
|
195
192
|
export default function plugin(options: PluginOptions): Transformer {
|
|
196
193
|
return async (root, vfile) => {
|
|
194
|
+
const {visit} = await import('unist-util-visit');
|
|
195
|
+
|
|
197
196
|
const promises: Promise<void>[] = [];
|
|
198
197
|
visit(root, 'image', (node: Image, index, parent) => {
|
|
199
198
|
promises.push(
|
|
@@ -15,9 +15,8 @@ import {
|
|
|
15
15
|
getFileLoaderUtils,
|
|
16
16
|
findAsyncSequential,
|
|
17
17
|
} from '@docusaurus/utils';
|
|
18
|
-
import visit from 'unist-util-visit';
|
|
19
18
|
import escapeHtml from 'escape-html';
|
|
20
|
-
import {assetRequireAttributeValue} from '../utils';
|
|
19
|
+
import {assetRequireAttributeValue, transformNode} from '../utils';
|
|
21
20
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
22
21
|
import type {Transformer} from 'unified';
|
|
23
22
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
@@ -90,14 +89,12 @@ async function toAssetRequireNode(
|
|
|
90
89
|
|
|
91
90
|
const {children} = node;
|
|
92
91
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
jsxNode.attributes = attributes;
|
|
100
|
-
jsxNode.children = children;
|
|
92
|
+
transformNode(jsxNode, {
|
|
93
|
+
type: 'mdxJsxTextElement',
|
|
94
|
+
name: 'a',
|
|
95
|
+
attributes,
|
|
96
|
+
children,
|
|
97
|
+
});
|
|
101
98
|
}
|
|
102
99
|
|
|
103
100
|
async function ensureAssetFileExist(assetPath: string, sourceFilePath: string) {
|
|
@@ -177,6 +174,8 @@ async function processLinkNode(target: Target, context: Context) {
|
|
|
177
174
|
|
|
178
175
|
export default function plugin(options: PluginOptions): Transformer {
|
|
179
176
|
return async (root, vfile) => {
|
|
177
|
+
const {visit} = await import('unist-util-visit');
|
|
178
|
+
|
|
180
179
|
const promises: Promise<void>[] = [];
|
|
181
180
|
visit(root, 'link', (node: Link, index, parent) => {
|
|
182
181
|
promises.push(
|
|
@@ -0,0 +1,167 @@
|
|
|
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
|
+
import path from 'path';
|
|
8
|
+
import process from 'process';
|
|
9
|
+
import logger from '@docusaurus/logger';
|
|
10
|
+
import {posixPath} from '@docusaurus/utils';
|
|
11
|
+
import {transformNode} from '../utils';
|
|
12
|
+
|
|
13
|
+
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
14
|
+
import type {Transformer, Processor, Parent} from 'unified';
|
|
15
|
+
import type {
|
|
16
|
+
Directives,
|
|
17
|
+
TextDirective,
|
|
18
|
+
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
19
|
+
} from 'mdast-util-directive';
|
|
20
|
+
|
|
21
|
+
// TODO as of April 2023, no way to import/re-export this ESM type easily :/
|
|
22
|
+
// This might change soon, likely after TS 5.2
|
|
23
|
+
// See https://github.com/microsoft/TypeScript/issues/49721#issuecomment-1517839391
|
|
24
|
+
// import type {Plugin} from 'unified';
|
|
25
|
+
type Plugin = any; // TODO fix this asap
|
|
26
|
+
|
|
27
|
+
type DirectiveType = Directives['type'];
|
|
28
|
+
|
|
29
|
+
const directiveTypes: DirectiveType[] = [
|
|
30
|
+
'containerDirective',
|
|
31
|
+
'leafDirective',
|
|
32
|
+
'textDirective',
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const directivePrefixMap: {[key in DirectiveType]: string} = {
|
|
36
|
+
textDirective: ':',
|
|
37
|
+
leafDirective: '::',
|
|
38
|
+
containerDirective: ':::',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
function formatDirectiveName(directive: Directives) {
|
|
42
|
+
const prefix = directivePrefixMap[directive.type];
|
|
43
|
+
if (!prefix) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`unexpected, no prefix found for directive of type ${directive.type}`,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
// To simplify we don't display the eventual label/props of directives
|
|
49
|
+
return `${prefix}${directive.name}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function formatDirectivePosition(directive: Directives): string | undefined {
|
|
53
|
+
return directive.position?.start
|
|
54
|
+
? logger.interpolate`number=${directive.position.start.line}:number=${directive.position.start.column}`
|
|
55
|
+
: undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function formatUnusedDirectiveMessage(directive: Directives) {
|
|
59
|
+
const name = formatDirectiveName(directive);
|
|
60
|
+
const position = formatDirectivePosition(directive);
|
|
61
|
+
|
|
62
|
+
return `- ${name} ${position ? `(${position})` : ''}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function formatUnusedDirectivesMessage({
|
|
66
|
+
directives,
|
|
67
|
+
filePath,
|
|
68
|
+
}: {
|
|
69
|
+
directives: Directives[];
|
|
70
|
+
filePath: string;
|
|
71
|
+
}): string {
|
|
72
|
+
const supportUrl = 'https://github.com/facebook/docusaurus/pull/9394';
|
|
73
|
+
const customPath = posixPath(path.relative(process.cwd(), filePath));
|
|
74
|
+
const warningTitle = logger.interpolate`Docusaurus found ${directives.length} unused Markdown directives in file path=${customPath}`;
|
|
75
|
+
const customSupportUrl = logger.interpolate`url=${supportUrl}`;
|
|
76
|
+
const warningMessages = directives
|
|
77
|
+
.map(formatUnusedDirectiveMessage)
|
|
78
|
+
.join('\n');
|
|
79
|
+
|
|
80
|
+
return `${warningTitle}
|
|
81
|
+
${warningMessages}
|
|
82
|
+
Your content might render in an unexpected way. Visit ${customSupportUrl} to find out why and how to fix it.`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function logUnusedDirectivesWarning({
|
|
86
|
+
directives,
|
|
87
|
+
filePath,
|
|
88
|
+
}: {
|
|
89
|
+
directives: Directives[];
|
|
90
|
+
filePath: string;
|
|
91
|
+
}) {
|
|
92
|
+
if (directives.length > 0) {
|
|
93
|
+
const message = formatUnusedDirectivesMessage({
|
|
94
|
+
directives,
|
|
95
|
+
filePath,
|
|
96
|
+
});
|
|
97
|
+
logger.warn(message);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function isTextDirective(directive: Directives): directive is TextDirective {
|
|
102
|
+
return directive.type === 'textDirective';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// A simple text directive is one without any label/props
|
|
106
|
+
function isSimpleTextDirective(
|
|
107
|
+
directive: Directives,
|
|
108
|
+
): directive is TextDirective {
|
|
109
|
+
if (isTextDirective(directive)) {
|
|
110
|
+
// Attributes in MDAST = Directive props
|
|
111
|
+
const hasAttributes =
|
|
112
|
+
directive.attributes && Object.keys(directive.attributes).length > 0;
|
|
113
|
+
// Children in MDAST = Directive label
|
|
114
|
+
const hasChildren = directive.children.length > 0;
|
|
115
|
+
return !hasAttributes && !hasChildren;
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function transformSimpleTextDirectiveToString(textDirective: Directives) {
|
|
121
|
+
transformNode(textDirective, {
|
|
122
|
+
type: 'text',
|
|
123
|
+
value: `:${textDirective.name}`, // We ignore label/props on purpose here
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function isUnusedDirective(directive: Directives) {
|
|
128
|
+
// If directive data is set (notably hName/hProperties set by admonitions)
|
|
129
|
+
// this usually means the directive has been handled by another plugin
|
|
130
|
+
return !directive.data;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const plugin: Plugin = function plugin(this: Processor): Transformer {
|
|
134
|
+
return async (tree, file) => {
|
|
135
|
+
const {visit} = await import('unist-util-visit');
|
|
136
|
+
|
|
137
|
+
const unusedDirectives: Directives[] = [];
|
|
138
|
+
|
|
139
|
+
visit<Parent, DirectiveType[]>(
|
|
140
|
+
tree,
|
|
141
|
+
directiveTypes,
|
|
142
|
+
(directive: Directives) => {
|
|
143
|
+
// If directive data is set (hName/hProperties set by admonitions)
|
|
144
|
+
// this usually means the directive has been handled by another plugin
|
|
145
|
+
if (isUnusedDirective(directive)) {
|
|
146
|
+
if (isSimpleTextDirective(directive)) {
|
|
147
|
+
transformSimpleTextDirectiveToString(directive);
|
|
148
|
+
} else {
|
|
149
|
+
unusedDirectives.push(directive);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
// We only enable these warnings for the client compiler
|
|
156
|
+
// This avoids emitting duplicate warnings in prod mode
|
|
157
|
+
// Note: the client compiler is used in both dev/prod modes
|
|
158
|
+
if (file.data.compilerName === 'client') {
|
|
159
|
+
logUnusedDirectivesWarning({
|
|
160
|
+
directives: unusedDirectives,
|
|
161
|
+
filePath: file.path,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export default plugin;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import escapeHtml from 'escape-html';
|
|
9
|
-
import type {Parent} from 'unist';
|
|
9
|
+
import type {Parent, Node} from 'unist';
|
|
10
10
|
import type {PhrasingContent, Heading} from 'mdast';
|
|
11
11
|
import type {
|
|
12
12
|
MdxJsxAttribute,
|
|
@@ -15,6 +15,27 @@ import type {
|
|
|
15
15
|
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
|
|
16
16
|
} from 'mdast-util-mdx';
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Util to transform one node type to another node type
|
|
20
|
+
* The input node is mutated in place
|
|
21
|
+
* @param node the node to mutate
|
|
22
|
+
* @param newNode what the original node should become become
|
|
23
|
+
*/
|
|
24
|
+
export function transformNode<NewNode extends Node>(
|
|
25
|
+
node: Node,
|
|
26
|
+
newNode: NewNode,
|
|
27
|
+
): NewNode {
|
|
28
|
+
Object.keys(node).forEach((key) => {
|
|
29
|
+
// @ts-expect-error: unsafe but ok
|
|
30
|
+
delete node[key];
|
|
31
|
+
});
|
|
32
|
+
Object.keys(newNode).forEach((key) => {
|
|
33
|
+
// @ts-expect-error: unsafe but ok
|
|
34
|
+
node[key] = newNode[key];
|
|
35
|
+
});
|
|
36
|
+
return node as NewNode;
|
|
37
|
+
}
|
|
38
|
+
|
|
18
39
|
export function stringifyContent(
|
|
19
40
|
node: Parent,
|
|
20
41
|
toString: (param: unknown) => string, // TODO weird but works
|
|
@@ -53,7 +74,7 @@ function mdxJsxTextElementToHtml(
|
|
|
53
74
|
}
|
|
54
75
|
|
|
55
76
|
export function toValue(
|
|
56
|
-
node: PhrasingContent | Heading,
|
|
77
|
+
node: PhrasingContent | Heading | MdxJsxTextElement,
|
|
57
78
|
toString: (param: unknown) => string, // TODO weird but works
|
|
58
79
|
): string {
|
|
59
80
|
switch (node.type) {
|