@docusaurus/mdx-loader 3.0.0-rc.0 → 3.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.
Files changed (61) hide show
  1. package/lib/loader.d.ts.map +1 -1
  2. package/lib/loader.js +2 -0
  3. package/lib/loader.js.map +1 -1
  4. package/lib/processor.d.ts +3 -1
  5. package/lib/processor.d.ts.map +1 -1
  6. package/lib/processor.js +10 -11
  7. package/lib/processor.js.map +1 -1
  8. package/lib/remark/admonitions/index.d.ts.map +1 -1
  9. package/lib/remark/admonitions/index.js +5 -10
  10. package/lib/remark/admonitions/index.js.map +1 -1
  11. package/lib/remark/contentTitle/index.d.ts.map +1 -1
  12. package/lib/remark/contentTitle/index.js +5 -5
  13. package/lib/remark/contentTitle/index.js.map +1 -1
  14. package/lib/remark/details/index.d.ts.map +1 -1
  15. package/lib/remark/details/index.js +3 -4
  16. package/lib/remark/details/index.js.map +1 -1
  17. package/lib/remark/head/index.d.ts.map +1 -1
  18. package/lib/remark/head/index.js +3 -4
  19. package/lib/remark/head/index.js.map +1 -1
  20. package/lib/remark/headings/index.d.ts.map +1 -1
  21. package/lib/remark/headings/index.js +2 -3
  22. package/lib/remark/headings/index.js.map +1 -1
  23. package/lib/remark/mdx1Compat/codeCompatPlugin.d.ts.map +1 -1
  24. package/lib/remark/mdx1Compat/codeCompatPlugin.js +4 -9
  25. package/lib/remark/mdx1Compat/codeCompatPlugin.js.map +1 -1
  26. package/lib/remark/mermaid/index.d.ts.map +1 -1
  27. package/lib/remark/mermaid/index.js +5 -5
  28. package/lib/remark/mermaid/index.js.map +1 -1
  29. package/lib/remark/toc/index.d.ts.map +1 -1
  30. package/lib/remark/toc/index.js +2 -2
  31. package/lib/remark/toc/index.js.map +1 -1
  32. package/lib/remark/transformImage/index.d.ts.map +1 -1
  33. package/lib/remark/transformImage/index.js +8 -7
  34. package/lib/remark/transformImage/index.js.map +1 -1
  35. package/lib/remark/transformLinks/index.d.ts.map +1 -1
  36. package/lib/remark/transformLinks/index.js +8 -7
  37. package/lib/remark/transformLinks/index.js.map +1 -1
  38. package/lib/remark/unusedDirectives/index.d.ts +4 -0
  39. package/lib/remark/unusedDirectives/index.d.ts.map +1 -0
  40. package/lib/remark/unusedDirectives/index.js +117 -0
  41. package/lib/remark/unusedDirectives/index.js.map +1 -0
  42. package/lib/remark/utils/index.d.ts +10 -3
  43. package/lib/remark/utils/index.d.ts.map +1 -1
  44. package/lib/remark/utils/index.js +19 -1
  45. package/lib/remark/utils/index.js.map +1 -1
  46. package/package.json +24 -25
  47. package/src/loader.ts +4 -0
  48. package/src/processor.ts +14 -11
  49. package/src/remark/admonitions/index.ts +3 -1
  50. package/src/remark/contentTitle/index.ts +3 -1
  51. package/src/remark/details/index.ts +2 -2
  52. package/src/remark/head/index.ts +2 -2
  53. package/src/remark/headings/index.ts +1 -1
  54. package/src/remark/mdx1Compat/codeCompatPlugin.ts +6 -8
  55. package/src/remark/mermaid/index.ts +7 -4
  56. package/src/remark/toc/index.ts +10 -4
  57. package/src/remark/transformImage/index.ts +9 -10
  58. package/src/remark/transformLinks/index.ts +9 -10
  59. package/src/remark/unusedDirectives/index.ts +167 -0
  60. package/src/remark/utils/index.ts +23 -2
  61. package/src/types.d.mts +34 -0
@@ -8,13 +8,16 @@
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
@@ -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 as string,
108
+ id: child.data!.id!,
104
109
  level: child.depth,
105
110
  });
106
111
  });
107
- const {children} = root as Parent<Literal>;
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
- Object.keys(jsxNode).forEach(
114
- (key) => delete jsxNode[key as keyof typeof jsxNode],
115
- );
116
-
117
- jsxNode.type = 'mdxJsxTextElement';
118
- jsxNode.name = 'img';
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
- Object.keys(jsxNode).forEach(
94
- (key) => delete jsxNode[key as keyof typeof jsxNode],
95
- );
96
-
97
- jsxNode.type = 'mdxJsxTextElement';
98
- jsxNode.name = 'a';
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) {
@@ -0,0 +1,34 @@
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 type {WebpackCompilerName} from '@docusaurus/utils';
9
+
10
+ declare module 'vfile' {
11
+ /*
12
+ This map registers the type of the data key of a VFile (TypeScript type).
13
+ This type can be augmented to register custom data types.
14
+ See https://github.com/vfile/vfile#datamap
15
+ */
16
+ interface DataMap {
17
+ frontMatter: {[key: string]: unknown};
18
+ compilerName: WebpackCompilerName;
19
+ contentTitle?: string;
20
+ }
21
+ }
22
+
23
+ declare module 'unist' {
24
+ interface Data {
25
+ hName?: string;
26
+ hProperties?: Record<string, unknown>;
27
+ }
28
+ }
29
+
30
+ declare module 'mdast' {
31
+ interface HeadingData {
32
+ id?: string;
33
+ }
34
+ }