-
-
Notifications
You must be signed in to change notification settings - Fork 6.3k
/
Copy pathnext.mdx.compiler.mjs
75 lines (62 loc) · 2.69 KB
/
next.mdx.compiler.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
'use strict';
import { compile as mdxCompile } from '@mdx-js/mdx';
import { Fragment, jsx, jsxs } from 'react/jsx-runtime';
import { matter } from 'vfile-matter';
import { createSval } from './next.jsx.compiler.mjs';
import { REHYPE_PLUGINS, REMARK_PLUGINS } from './next.mdx.plugins.mjs';
import { createGitHubSlugger } from './util/gitHubUtils';
// Defines a JSX Fragment and JSX Runtime for the MDX Compiler
export const reactRuntime = { Fragment, jsx, jsxs };
/**
* This is our custom simple MDX Compiler that is used to compile Markdown and MDX
* this returns a serializable VFile as a string that then gets passed to our MDX Provider
*
* @param {import('vfile').VFile} source The source Markdown/MDX content
* @param {'md' | 'mdx'} fileExtension If it should use the MDX or a plain Markdown parser/compiler
* @param {import('mdx/types').MDXComponents} components The MDX Components to be used in the MDX Provider
* @param {Record<string, any>} props Extra optional React props for the MDX Provider
*
* @returns {Promise<{
* content: import('react').ReactElement;
* headings: Array<import('@vcarl/remark-headings').Heading>;
* frontmatter: Record<string, any>;
* readingTime: import('reading-time').ReadTimeResults;
* }>}
*/
export async function compile(
source,
fileExtension,
components = {},
props = {}
) {
// Parses the Frontmatter to the VFile and removes from the original source
// cleaning the frontmatter to the source that is going to be parsed by the MDX Compiler
matter(source, { strip: true });
// Creates a GitHub slugger to generate the same slugs as GitHub
const slugger = createGitHubSlugger();
// Compiles the MDX/Markdown source into a serializable VFile
const compiled = await mdxCompile(source, {
rehypePlugins: REHYPE_PLUGINS,
remarkPlugins: REMARK_PLUGINS,
format: fileExtension,
});
const interpreter = createSval({
...components,
'react/jsx-runtime': reactRuntime,
});
// Run the compiled JavaScript code from MDX
interpreter.run(compiled.toString());
// Retrieve the default export from the compiled MDX
const MDXContent = interpreter.exports.default;
// Render the MDX content directly from the compiler
const content = <MDXContent {...props} components={components} />;
// Retrieve some parsed data from the VFile metadata
// such as frontmatter and Markdown headings
const { headings = [], matter: frontmatter, readingTime } = source.data;
headings.forEach(heading => {
// we re-sluggify the links to match the GitHub slugger
// since some also do not come with sluggifed links
heading.data = { ...heading.data, id: slugger(heading.value) };
});
return { content, headings, frontmatter, readingTime };
}