@docusaurus/mdx-loader 2.0.0-beta.ff31de0ff → 2.0.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 (84) hide show
  1. package/lib/index.d.ts +32 -0
  2. package/lib/index.d.ts.map +1 -0
  3. package/lib/index.js +11 -0
  4. package/lib/index.js.map +1 -0
  5. package/lib/loader.d.ts +41 -0
  6. package/lib/loader.d.ts.map +1 -0
  7. package/lib/loader.js +210 -0
  8. package/lib/loader.js.map +1 -0
  9. package/lib/remark/admonitions/index.d.ts +15 -0
  10. package/lib/remark/admonitions/index.d.ts.map +1 -0
  11. package/lib/remark/admonitions/index.js +132 -0
  12. package/lib/remark/admonitions/index.js.map +1 -0
  13. package/lib/remark/headings/index.d.ts +9 -0
  14. package/lib/remark/headings/index.d.ts.map +1 -0
  15. package/lib/remark/headings/index.js +58 -0
  16. package/lib/remark/headings/index.js.map +1 -0
  17. package/lib/remark/toc/index.d.ts +9 -0
  18. package/lib/remark/toc/index.d.ts.map +1 -0
  19. package/lib/remark/toc/index.js +81 -0
  20. package/lib/remark/toc/index.js.map +1 -0
  21. package/lib/remark/transformImage/index.d.ts +13 -0
  22. package/lib/remark/transformImage/index.d.ts.map +1 -0
  23. package/lib/remark/transformImage/index.js +114 -0
  24. package/lib/remark/transformImage/index.js.map +1 -0
  25. package/lib/remark/transformLinks/index.d.ts +13 -0
  26. package/lib/remark/transformLinks/index.d.ts.map +1 -0
  27. package/lib/remark/transformLinks/index.js +106 -0
  28. package/lib/remark/transformLinks/index.js.map +1 -0
  29. package/lib/remark/unwrapMdxCodeBlocks/index.d.ts +9 -0
  30. package/lib/remark/unwrapMdxCodeBlocks/index.d.ts.map +1 -0
  31. package/lib/remark/unwrapMdxCodeBlocks/index.js +29 -0
  32. package/lib/remark/unwrapMdxCodeBlocks/index.js.map +1 -0
  33. package/lib/remark/utils/index.d.ts +11 -0
  34. package/lib/remark/utils/index.d.ts.map +1 -0
  35. package/lib/remark/utils/index.js +38 -0
  36. package/lib/remark/utils/index.js.map +1 -0
  37. package/package.json +26 -20
  38. package/src/deps.d.ts +31 -0
  39. package/src/index.ts +35 -0
  40. package/src/loader.ts +282 -0
  41. package/src/remark/admonitions/LICENSE +45 -0
  42. package/src/remark/admonitions/README.md +3 -0
  43. package/src/remark/admonitions/index.ts +186 -0
  44. package/src/remark/headings/{index.js → index.ts} +23 -27
  45. package/src/remark/toc/index.ts +98 -0
  46. package/src/remark/transformImage/index.ts +173 -0
  47. package/src/remark/transformLinks/index.ts +164 -0
  48. package/src/remark/unwrapMdxCodeBlocks/{index.js → index.ts} +14 -15
  49. package/src/remark/utils/index.ts +36 -0
  50. package/src/index.d.ts +0 -19
  51. package/src/index.js +0 -104
  52. package/src/remark/headings/__tests__/index.test.js +0 -315
  53. package/src/remark/toc/__tests__/__snapshots__/index.test.js.snap +0 -85
  54. package/src/remark/toc/__tests__/fixtures/empty-headings.md +0 -5
  55. package/src/remark/toc/__tests__/fixtures/inline-code.md +0 -9
  56. package/src/remark/toc/__tests__/fixtures/insert-below-imports.md +0 -11
  57. package/src/remark/toc/__tests__/fixtures/just-content.md +0 -15
  58. package/src/remark/toc/__tests__/fixtures/name-exist.md +0 -7
  59. package/src/remark/toc/__tests__/fixtures/non-text-content.md +0 -9
  60. package/src/remark/toc/__tests__/index.test.js +0 -212
  61. package/src/remark/toc/index.js +0 -79
  62. package/src/remark/toc/search.js +0 -73
  63. package/src/remark/transformImage/__tests__/__snapshots__/index.test.js.snap +0 -31
  64. package/src/remark/transformImage/__tests__/fixtures/fail.md +0 -1
  65. package/src/remark/transformImage/__tests__/fixtures/img.md +0 -17
  66. package/src/remark/transformImage/__tests__/fixtures/img.png +0 -0
  67. package/src/remark/transformImage/__tests__/fixtures/noUrl.md +0 -1
  68. package/src/remark/transformImage/__tests__/fixtures/pathname.md +0 -1
  69. package/src/remark/transformImage/__tests__/index.test.js +0 -59
  70. package/src/remark/transformImage/index.js +0 -106
  71. package/src/remark/transformLinks/__tests__/__snapshots__/index.test.js.snap +0 -41
  72. package/src/remark/transformLinks/__tests__/fixtures/asset.md +0 -29
  73. package/src/remark/transformLinks/__tests__/fixtures/asset.pdf +0 -0
  74. package/src/remark/transformLinks/__tests__/fixtures/noUrl.md +0 -1
  75. package/src/remark/transformLinks/__tests__/fixtures/pathname.md +0 -1
  76. package/src/remark/transformLinks/__tests__/fixtures/static/staticAsset.pdf +0 -0
  77. package/src/remark/transformLinks/__tests__/fixtures/static/staticAssetImage.png +0 -0
  78. package/src/remark/transformLinks/__tests__/index.test.js +0 -44
  79. package/src/remark/transformLinks/index.js +0 -143
  80. package/src/remark/unwrapMdxCodeBlocks/__tests__/__snapshots__/index.test.js.snap +0 -819
  81. package/src/remark/unwrapMdxCodeBlocks/__tests__/fixtures/has-mdx-code-blocks.mdx +0 -95
  82. package/src/remark/unwrapMdxCodeBlocks/__tests__/index.test.js +0 -38
  83. package/src/remark/utils/index.js +0 -39
  84. package/tsconfig.json +0 -9
@@ -0,0 +1,173 @@
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 path from 'path';
9
+ import url from 'url';
10
+ import fs from 'fs-extra';
11
+ import {promisify} from 'util';
12
+ import logger from '@docusaurus/logger';
13
+ import {
14
+ toMessageRelativeFilePath,
15
+ posixPath,
16
+ escapePath,
17
+ getFileLoaderUtils,
18
+ findAsyncSequential,
19
+ } from '@docusaurus/utils';
20
+ import visit from 'unist-util-visit';
21
+ import escapeHtml from 'escape-html';
22
+ import sizeOf from 'image-size';
23
+ import type {Transformer} from 'unified';
24
+ import type {Parent} from 'unist';
25
+ import type {Image, Literal} from 'mdast';
26
+
27
+ const {
28
+ loaders: {inlineMarkdownImageFileLoader},
29
+ } = getFileLoaderUtils();
30
+
31
+ export type PluginOptions = {
32
+ staticDirs: string[];
33
+ siteDir: string;
34
+ };
35
+
36
+ type Context = PluginOptions & {
37
+ filePath: string;
38
+ };
39
+
40
+ type Target = [node: Image, index: number, parent: Parent];
41
+
42
+ async function toImageRequireNode(
43
+ [node, index, parent]: Target,
44
+ imagePath: string,
45
+ filePath: string,
46
+ ) {
47
+ let relativeImagePath = posixPath(
48
+ path.relative(path.dirname(filePath), imagePath),
49
+ );
50
+ relativeImagePath = `./${relativeImagePath}`;
51
+
52
+ const parsedUrl = url.parse(node.url);
53
+ const hash = parsedUrl.hash ?? '';
54
+ const search = parsedUrl.search ?? '';
55
+
56
+ const alt = node.alt ? `alt={"${escapeHtml(node.alt)}"} ` : '';
57
+ const src = `require("${inlineMarkdownImageFileLoader}${
58
+ escapePath(relativeImagePath) + search
59
+ }").default${hash ? ` + '${hash}'` : ''}`;
60
+ const title = node.title ? ` title="${escapeHtml(node.title)}"` : '';
61
+ let width = '';
62
+ let height = '';
63
+ try {
64
+ const size = (await promisify(sizeOf)(imagePath))!;
65
+ if (size.width) {
66
+ width = ` width="${size.width}"`;
67
+ }
68
+ if (size.height) {
69
+ height = ` height="${size.height}"`;
70
+ }
71
+ } catch (err) {
72
+ // Workaround for https://github.com/yarnpkg/berry/pull/3889#issuecomment-1034469784
73
+ // TODO remove this check once fixed in Yarn PnP
74
+ if (!process.versions.pnp) {
75
+ logger.warn`The image at path=${imagePath} can't be read correctly. Please ensure it's a valid image.
76
+ ${(err as Error).message}`;
77
+ }
78
+ }
79
+
80
+ const jsxNode: Literal = {
81
+ type: 'jsx',
82
+ value: `<img ${alt}src={${src}}${title}${width}${height} />`,
83
+ };
84
+
85
+ parent.children.splice(index, 1, jsxNode);
86
+ }
87
+
88
+ async function ensureImageFileExist(imagePath: string, sourceFilePath: string) {
89
+ const imageExists = await fs.pathExists(imagePath);
90
+ if (!imageExists) {
91
+ throw new Error(
92
+ `Image ${toMessageRelativeFilePath(
93
+ imagePath,
94
+ )} used in ${toMessageRelativeFilePath(sourceFilePath)} not found.`,
95
+ );
96
+ }
97
+ }
98
+
99
+ async function getImageAbsolutePath(
100
+ imagePath: string,
101
+ {siteDir, filePath, staticDirs}: Context,
102
+ ) {
103
+ if (imagePath.startsWith('@site/')) {
104
+ const imageFilePath = path.join(siteDir, imagePath.replace('@site/', ''));
105
+ await ensureImageFileExist(imageFilePath, filePath);
106
+ return imageFilePath;
107
+ } else if (path.isAbsolute(imagePath)) {
108
+ // Absolute paths are expected to exist in the static folder.
109
+ const possiblePaths = staticDirs.map((dir) => path.join(dir, imagePath));
110
+ const imageFilePath = await findAsyncSequential(
111
+ possiblePaths,
112
+ fs.pathExists,
113
+ );
114
+ if (!imageFilePath) {
115
+ throw new Error(
116
+ `Image ${possiblePaths
117
+ .map((p) => toMessageRelativeFilePath(p))
118
+ .join(' or ')} used in ${toMessageRelativeFilePath(
119
+ filePath,
120
+ )} not found.`,
121
+ );
122
+ }
123
+ return imageFilePath;
124
+ }
125
+ // Relative paths are resolved against the source file's folder.
126
+ const imageFilePath = path.join(
127
+ path.dirname(filePath),
128
+ decodeURIComponent(imagePath),
129
+ );
130
+ await ensureImageFileExist(imageFilePath, filePath);
131
+ return imageFilePath;
132
+ }
133
+
134
+ async function processImageNode(target: Target, context: Context) {
135
+ const [node] = target;
136
+ if (!node.url) {
137
+ throw new Error(
138
+ `Markdown image URL is mandatory in "${toMessageRelativeFilePath(
139
+ context.filePath,
140
+ )}" file`,
141
+ );
142
+ }
143
+
144
+ const parsedUrl = url.parse(node.url);
145
+ if (parsedUrl.protocol || !parsedUrl.pathname) {
146
+ // pathname:// is an escape hatch, in case user does not want her images to
147
+ // be converted to require calls going through webpack loader
148
+ if (parsedUrl.protocol === 'pathname:') {
149
+ node.url = node.url.replace('pathname://', '');
150
+ }
151
+ return;
152
+ }
153
+
154
+ // We try to convert image urls without protocol to images with require calls
155
+ // going through webpack ensures that image assets exist at build time
156
+ const imagePath = await getImageAbsolutePath(parsedUrl.pathname, context);
157
+ await toImageRequireNode(target, imagePath, context.filePath);
158
+ }
159
+
160
+ export default function plugin(options: PluginOptions): Transformer {
161
+ return async (root, vfile) => {
162
+ const promises: Promise<void>[] = [];
163
+ visit(root, 'image', (node: Image, index, parent) => {
164
+ promises.push(
165
+ processImageNode([node, index, parent!], {
166
+ ...options,
167
+ filePath: vfile.path!,
168
+ }),
169
+ );
170
+ });
171
+ await Promise.all(promises);
172
+ };
173
+ }
@@ -0,0 +1,164 @@
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 path from 'path';
9
+ import url from 'url';
10
+ import fs from 'fs-extra';
11
+ import {
12
+ toMessageRelativeFilePath,
13
+ posixPath,
14
+ escapePath,
15
+ getFileLoaderUtils,
16
+ findAsyncSequential,
17
+ } from '@docusaurus/utils';
18
+ import visit from 'unist-util-visit';
19
+ import escapeHtml from 'escape-html';
20
+ import {stringifyContent} from '../utils';
21
+ import type {Transformer} from 'unified';
22
+ import type {Parent} from 'unist';
23
+ import type {Link, Literal} from 'mdast';
24
+
25
+ const {
26
+ loaders: {inlineMarkdownLinkFileLoader},
27
+ } = getFileLoaderUtils();
28
+
29
+ export type PluginOptions = {
30
+ staticDirs: string[];
31
+ siteDir: string;
32
+ };
33
+
34
+ type Context = PluginOptions & {
35
+ filePath: string;
36
+ };
37
+
38
+ type Target = [node: Link, index: number, parent: Parent];
39
+
40
+ /**
41
+ * Transforms the link node to a JSX `<a>` element with a `require()` call.
42
+ */
43
+ function toAssetRequireNode(
44
+ [node, index, parent]: Target,
45
+ assetPath: string,
46
+ filePath: string,
47
+ ) {
48
+ // require("assets/file.pdf") means requiring from a package called assets
49
+ const relativeAssetPath = `./${posixPath(
50
+ path.relative(path.dirname(filePath), assetPath),
51
+ )}`;
52
+
53
+ const parsedUrl = url.parse(node.url);
54
+ const hash = parsedUrl.hash ?? '';
55
+ const search = parsedUrl.search ?? '';
56
+
57
+ const href = `require('${
58
+ // A hack to stop Webpack from using its built-in loader to parse JSON
59
+ path.extname(relativeAssetPath) === '.json'
60
+ ? `${relativeAssetPath.replace('.json', '.raw')}!=`
61
+ : ''
62
+ }${inlineMarkdownLinkFileLoader}${
63
+ escapePath(relativeAssetPath) + search
64
+ }').default${hash ? ` + '${hash}'` : ''}`;
65
+ const children = stringifyContent(node);
66
+ const title = node.title ? ` title="${escapeHtml(node.title)}"` : '';
67
+
68
+ const jsxNode: Literal = {
69
+ type: 'jsx',
70
+ value: `<a target="_blank" href={${href}}${title}>${children}</a>`,
71
+ };
72
+
73
+ parent.children.splice(index, 1, jsxNode);
74
+ }
75
+
76
+ async function ensureAssetFileExist(assetPath: string, sourceFilePath: string) {
77
+ const assetExists = await fs.pathExists(assetPath);
78
+ if (!assetExists) {
79
+ throw new Error(
80
+ `Asset ${toMessageRelativeFilePath(
81
+ assetPath,
82
+ )} used in ${toMessageRelativeFilePath(sourceFilePath)} not found.`,
83
+ );
84
+ }
85
+ }
86
+
87
+ async function getAssetAbsolutePath(
88
+ assetPath: string,
89
+ {siteDir, filePath, staticDirs}: Context,
90
+ ) {
91
+ if (assetPath.startsWith('@site/')) {
92
+ const assetFilePath = path.join(siteDir, assetPath.replace('@site/', ''));
93
+ // The @site alias is the only way to believe that the user wants an asset.
94
+ // Everything else can just be a link URL
95
+ await ensureAssetFileExist(assetFilePath, filePath);
96
+ return assetFilePath;
97
+ } else if (path.isAbsolute(assetPath)) {
98
+ const assetFilePath = await findAsyncSequential(
99
+ staticDirs.map((dir) => path.join(dir, assetPath)),
100
+ fs.pathExists,
101
+ );
102
+ if (assetFilePath) {
103
+ return assetFilePath;
104
+ }
105
+ } else {
106
+ const assetFilePath = path.join(path.dirname(filePath), assetPath);
107
+ if (await fs.pathExists(assetFilePath)) {
108
+ return assetFilePath;
109
+ }
110
+ }
111
+ return null;
112
+ }
113
+
114
+ async function processLinkNode(target: Target, context: Context) {
115
+ const [node] = target;
116
+ if (!node.url) {
117
+ // Try to improve error feedback
118
+ // see https://github.com/facebook/docusaurus/issues/3309#issuecomment-690371675
119
+ const title =
120
+ node.title ?? (node.children[0] as Literal | undefined)?.value ?? '?';
121
+ const line = node.position?.start.line ?? '?';
122
+ throw new Error(
123
+ `Markdown link URL is mandatory in "${toMessageRelativeFilePath(
124
+ context.filePath,
125
+ )}" file (title: ${title}, line: ${line}).`,
126
+ );
127
+ }
128
+
129
+ const parsedUrl = url.parse(node.url);
130
+ if (parsedUrl.protocol || !parsedUrl.pathname) {
131
+ // Don't process pathname:// here, it's used by the <Link> component
132
+ return;
133
+ }
134
+ const hasSiteAlias = parsedUrl.pathname.startsWith('@site/');
135
+ const hasAssetLikeExtension =
136
+ path.extname(parsedUrl.pathname) &&
137
+ !parsedUrl.pathname.match(/\.(?:mdx?|html)(?:#|$)/);
138
+ if (!hasSiteAlias && !hasAssetLikeExtension) {
139
+ return;
140
+ }
141
+
142
+ const assetPath = await getAssetAbsolutePath(
143
+ decodeURIComponent(parsedUrl.pathname),
144
+ context,
145
+ );
146
+ if (assetPath) {
147
+ toAssetRequireNode(target, assetPath, context.filePath);
148
+ }
149
+ }
150
+
151
+ export default function plugin(options: PluginOptions): Transformer {
152
+ return async (root, vfile) => {
153
+ const promises: Promise<void>[] = [];
154
+ visit(root, 'link', (node: Link, index, parent) => {
155
+ promises.push(
156
+ processLinkNode([node, index, parent!], {
157
+ ...options,
158
+ filePath: vfile.path!,
159
+ }),
160
+ );
161
+ });
162
+ await Promise.all(promises);
163
+ };
164
+ }
@@ -5,30 +5,29 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- const visit = require('unist-util-visit');
8
+ import visit from 'unist-util-visit';
9
+ import type {Transformer, Processor} from 'unified';
10
+ import type {Code, Parent} from 'mdast';
9
11
 
10
12
  // This plugin is mostly to help integrating Docusaurus with translation systems
11
- // that do not support well MDX embedded JSX syntax (like Crowdin)
12
- // We wrap the JSX syntax in code blocks so that translation tools don't mess-up with the markup
13
- // But the JSX inside such code blocks should still be evaluated as JSX
13
+ // that do not support well MDX embedded JSX syntax (like Crowdin).
14
+ // We wrap the JSX syntax in code blocks so that translation tools don't mess up
15
+ // with the markup, but the JSX inside such code blocks should still be
16
+ // evaluated as JSX
14
17
  // See https://github.com/facebook/docusaurus/pull/4278
15
- function plugin() {
16
- const transformer = (root) => {
17
- visit(root, 'code', (node, _index, parent) => {
18
+ export default function plugin(this: Processor): Transformer {
19
+ return (root) => {
20
+ visit(root, 'code', (node: Code, index, parent) => {
18
21
  if (node.lang === 'mdx-code-block') {
19
- const newChildrens = this.parse(node.value).children;
22
+ const newChildren = (this.parse(node.value) as Parent).children;
20
23
 
21
24
  // Replace the mdx code block by its content, parsed
22
- parent.children.splice(
23
- parent.children.indexOf(node),
25
+ parent!.children.splice(
26
+ parent!.children.indexOf(node),
24
27
  1,
25
- ...newChildrens,
28
+ ...newChildren,
26
29
  );
27
30
  }
28
31
  });
29
32
  };
30
-
31
- return transformer;
32
33
  }
33
-
34
- module.exports = plugin;
@@ -0,0 +1,36 @@
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 escapeHtml from 'escape-html';
9
+ import toString from 'mdast-util-to-string';
10
+ import type {Parent} from 'unist';
11
+ import type {PhrasingContent, Heading} from 'mdast';
12
+
13
+ export function stringifyContent(node: Parent): string {
14
+ return (node.children as PhrasingContent[]).map(toValue).join('');
15
+ }
16
+
17
+ export function toValue(node: PhrasingContent | Heading): string {
18
+ switch (node.type) {
19
+ case 'text':
20
+ return escapeHtml(node.value);
21
+ case 'heading':
22
+ return stringifyContent(node);
23
+ case 'inlineCode':
24
+ return `<code>${escapeHtml(node.value)}</code>`;
25
+ case 'emphasis':
26
+ return `<em>${stringifyContent(node)}</em>`;
27
+ case 'strong':
28
+ return `<strong>${stringifyContent(node)}</strong>`;
29
+ case 'delete':
30
+ return `<del>${stringifyContent(node)}</del>`;
31
+ case 'link':
32
+ return stringifyContent(node);
33
+ default:
34
+ return toString(node);
35
+ }
36
+ }
package/src/index.d.ts DELETED
@@ -1,19 +0,0 @@
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
- type RemarkOrRehypePlugin =
9
- // eslint-disable-next-line @typescript-eslint/ban-types
10
- [Function, Record<string, unknown>] | Function;
11
-
12
- declare function docusaurusMdxLoader(fileString: string): string;
13
-
14
- export interface RemarkAndRehypePluginOptions {
15
- remarkPlugins: RemarkOrRehypePlugin[];
16
- rehypePlugins: string[];
17
- beforeDefaultRemarkPlugins: RemarkOrRehypePlugin[];
18
- beforeDefaultRehypePlugins: RemarkOrRehypePlugin[];
19
- }
package/src/index.js DELETED
@@ -1,104 +0,0 @@
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
- const {readFile} = require('fs-extra');
9
- const mdx = require('@mdx-js/mdx');
10
- const emoji = require('remark-emoji');
11
- const {
12
- parseFrontMatter,
13
- parseMarkdownContentTitle,
14
- } = require('@docusaurus/utils');
15
- const stringifyObject = require('stringify-object');
16
- const headings = require('./remark/headings');
17
- const toc = require('./remark/toc');
18
- const unwrapMdxCodeBlocks = require('./remark/unwrapMdxCodeBlocks');
19
- const transformImage = require('./remark/transformImage');
20
- const transformLinks = require('./remark/transformLinks');
21
-
22
- const DEFAULT_OPTIONS = {
23
- rehypePlugins: [],
24
- remarkPlugins: [unwrapMdxCodeBlocks, emoji, headings, toc],
25
- };
26
-
27
- module.exports = async function docusaurusMdxLoader(fileString) {
28
- const callback = this.async();
29
-
30
- const reqOptions = this.getOptions() || {};
31
-
32
- const {frontMatter, content: contentWithTitle} = parseFrontMatter(fileString);
33
-
34
- // By default, will remove the markdown title from the content
35
- const {content} = parseMarkdownContentTitle(contentWithTitle, {
36
- keepContentTitle: reqOptions.keepContentTitle,
37
- });
38
-
39
- const hasFrontMatter = Object.keys(frontMatter).length > 0;
40
-
41
- const options = {
42
- ...reqOptions,
43
- remarkPlugins: [
44
- ...(reqOptions.beforeDefaultRemarkPlugins || []),
45
- ...DEFAULT_OPTIONS.remarkPlugins,
46
- [
47
- transformImage,
48
- {staticDir: reqOptions.staticDir, filePath: this.resourcePath},
49
- ],
50
- [
51
- transformLinks,
52
- {staticDir: reqOptions.staticDir, filePath: this.resourcePath},
53
- ],
54
- ...(reqOptions.remarkPlugins || []),
55
- ],
56
- rehypePlugins: [
57
- ...(reqOptions.beforeDefaultRehypePlugins || []),
58
- ...DEFAULT_OPTIONS.rehypePlugins,
59
-
60
- ...(reqOptions.rehypePlugins || []),
61
- ],
62
- filepath: this.resourcePath,
63
- };
64
- let result;
65
-
66
- try {
67
- result = await mdx(content, options);
68
- } catch (err) {
69
- return callback(err);
70
- }
71
-
72
- let exportStr = `export const frontMatter = ${stringifyObject(frontMatter)};`;
73
-
74
- // Read metadata for this MDX and export it.
75
- if (options.metadataPath && typeof options.metadataPath === 'function') {
76
- const metadataPath = options.metadataPath(this.resourcePath);
77
-
78
- if (metadataPath) {
79
- // Add as dependency of this loader result so that we can
80
- // recompile if metadata is changed.
81
- this.addDependency(metadataPath);
82
- const metadata = await readFile(metadataPath, 'utf8');
83
- exportStr += `\nexport const metadata = ${metadata};`;
84
- }
85
- }
86
-
87
- if (
88
- options.forbidFrontMatter &&
89
- typeof options.forbidFrontMatter === 'function'
90
- ) {
91
- if (options.forbidFrontMatter(this.resourcePath) && hasFrontMatter) {
92
- return callback(new Error(`Front matter is forbidden in this file`));
93
- }
94
- }
95
- const code = `
96
- import React from 'react';
97
- import { mdx } from '@mdx-js/react';
98
-
99
- ${exportStr}
100
- ${result}
101
- `;
102
-
103
- return callback(null, code);
104
- };