Merge pull request #96 from timlrx/mdx-bundler
feat: mdx-bundler and xdm
This commit is contained in:
@ -15,13 +15,14 @@ module.exports = (options) => (tree) => {
|
||||
const dimensions = sizeOf(`${process.cwd()}/public${imageNode.url}`)
|
||||
|
||||
// Convert original node to next/image
|
||||
imageNode.type = 'jsx'
|
||||
imageNode.value = `<Image
|
||||
alt={\`${imageNode.alt}\`}
|
||||
src={\`${imageNode.url}\`}
|
||||
width={${dimensions.width}}
|
||||
height={${dimensions.height}}
|
||||
/>`
|
||||
;(imageNode.type = 'mdxJsxFlowElement'),
|
||||
(imageNode.name = 'Image'),
|
||||
(imageNode.attributes = [
|
||||
{ type: 'mdxJsxAttribute', name: 'alt', value: imageNode.alt },
|
||||
{ type: 'mdxJsxAttribute', name: 'src', value: imageNode.url },
|
||||
{ type: 'mdxJsxAttribute', name: 'width', value: dimensions.width },
|
||||
{ type: 'mdxJsxAttribute', name: 'height', value: dimensions.height },
|
||||
])
|
||||
|
||||
// Change node type from p to div to avoid nesting error
|
||||
node.type = 'div'
|
||||
|
64
lib/mdx.js
64
lib/mdx.js
@ -1,10 +1,10 @@
|
||||
import { MDXComponents } from '@/components/MDXComponents'
|
||||
import { bundleMDX } from 'mdx-bundler'
|
||||
import fs from 'fs'
|
||||
import matter from 'gray-matter'
|
||||
import { serialize } from 'next-mdx-remote/serialize'
|
||||
import path from 'path'
|
||||
import readingTime from 'reading-time'
|
||||
import visit from 'unist-util-visit'
|
||||
import codeTitles from './remark-code-title'
|
||||
import imgToJsx from './img-to-jsx'
|
||||
import getAllFilesRecursively from './utils/files'
|
||||
|
||||
@ -48,21 +48,45 @@ export async function getFileBySlug(type, slug) {
|
||||
? fs.readFileSync(mdxPath, 'utf8')
|
||||
: fs.readFileSync(mdPath, 'utf8')
|
||||
|
||||
const { data, content } = matter(source)
|
||||
const mdxSource = await serialize(content, {
|
||||
components: MDXComponents,
|
||||
mdxOptions: {
|
||||
remarkPlugins: [
|
||||
// https://github.com/kentcdodds/mdx-bundler#nextjs-esbuild-enoent
|
||||
if (process.platform === 'win32') {
|
||||
process.env.ESBUILD_BINARY_PATH = path.join(
|
||||
process.cwd(),
|
||||
'node_modules',
|
||||
'esbuild',
|
||||
'esbuild.exe'
|
||||
)
|
||||
} else {
|
||||
process.env.ESBUILD_BINARY_PATH = path.join(
|
||||
process.cwd(),
|
||||
'node_modules',
|
||||
'esbuild',
|
||||
'bin',
|
||||
'esbuild'
|
||||
)
|
||||
}
|
||||
|
||||
const { frontmatter, code } = await bundleMDX(source, {
|
||||
// mdx imports can be automatically source from the components directory
|
||||
cwd: path.join(process.cwd(), 'components'),
|
||||
xdmOptions(options) {
|
||||
// this is the recommended way to add custom remark/rehype plugins:
|
||||
// The syntax might look weird, but it protects you in case we add/remove
|
||||
// plugins in the future.
|
||||
options.remarkPlugins = [
|
||||
...(options.remarkPlugins ?? []),
|
||||
require('remark-slug'),
|
||||
require('remark-autolink-headings'),
|
||||
require('remark-code-titles'),
|
||||
require('remark-gfm'),
|
||||
codeTitles,
|
||||
[require('remark-footnotes'), { inlineNotes: true }],
|
||||
require('remark-math'),
|
||||
imgToJsx,
|
||||
],
|
||||
inlineNotes: true,
|
||||
rehypePlugins: [
|
||||
]
|
||||
options.rehypePlugins = [
|
||||
...(options.rehypePlugins ?? []),
|
||||
require('rehype-katex'),
|
||||
require('@mapbox/rehype-prism'),
|
||||
[require('rehype-prism-plus'), { ignoreMissing: true }],
|
||||
() => {
|
||||
return (tree) => {
|
||||
visit(tree, 'element', (node, index, parent) => {
|
||||
@ -73,17 +97,25 @@ export async function getFileBySlug(type, slug) {
|
||||
})
|
||||
}
|
||||
},
|
||||
],
|
||||
]
|
||||
return options
|
||||
},
|
||||
esbuildOptions: (options) => {
|
||||
options.loader = {
|
||||
...options.loader,
|
||||
'.js': 'jsx',
|
||||
}
|
||||
return options
|
||||
},
|
||||
})
|
||||
|
||||
return {
|
||||
mdxSource,
|
||||
mdxSource: code,
|
||||
frontMatter: {
|
||||
readingTime: readingTime(content),
|
||||
readingTime: readingTime(code),
|
||||
slug: slug || null,
|
||||
fileName: fs.existsSync(mdxPath) ? `${slug}.mdx` : `${slug}.md`,
|
||||
...data,
|
||||
...frontmatter,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
32
lib/remark-code-title.js
Normal file
32
lib/remark-code-title.js
Normal file
@ -0,0 +1,32 @@
|
||||
import visit from 'unist-util-visit'
|
||||
|
||||
module.exports = function (options) {
|
||||
return (tree) =>
|
||||
visit(tree, 'code', (node, index) => {
|
||||
const nodeLang = node.lang || ''
|
||||
let language = ''
|
||||
let title = ''
|
||||
|
||||
if (nodeLang.includes(':')) {
|
||||
language = nodeLang.slice(0, nodeLang.search(':'))
|
||||
title = nodeLang.slice(nodeLang.search(':') + 1, nodeLang.length)
|
||||
}
|
||||
|
||||
if (!title) {
|
||||
return
|
||||
}
|
||||
|
||||
const className = 'remark-code-title'
|
||||
|
||||
const titleNode = {
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: 'div',
|
||||
attributes: [{ type: 'mdxJsxAttribute', name: 'className', value: className }],
|
||||
children: [{ type: 'text', value: title }],
|
||||
data: { _xdmExplicitJsx: true },
|
||||
}
|
||||
|
||||
tree.children.splice(index, 0, titleNode)
|
||||
node.lang = language
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user