MDX 플러그인
간혹 마크다운 구문을 확장하거나 변경할 수 있습니다. 예를 들면 아래와 같은 형식입니다.
- image 구문(

)을 사용해 유튜브 동영상을 삽입하려면 어떻게 해야 하나요? - 소셜 카드처럼 자체 라인에 있는 링크 스타일을 다르게 지정하려면 어떻게 해야 하나요?
- 모든 페이지에 저작권 표시를 하려면 어떻게 하나요?
해결책은 MDX 플러그인을 만드는 겁니다! MDX는 마크다운 파일을 구문분석하고 JSX로 변환하는 방식을 사용자가 지정할 수 있는 내장 플러그인 시스템이 있습니다. MDX 플러그인의 세 가지 일반적인 사용 사례는 다음과 같습니다.
- 기존 remark plugins 또는 rehype plugins을 사용합니다.
- 기존 MDX 구문으로 생성된 요소를 변환하기 위한 remark/rehype 플러그인을 만듭니다.
- MDX에 새로운 구문을 도입하기 위한 remark/rehype 플러그인을 만듭니다.
If you play with the MDX playground, you would notice that the MDX transpilation has two intermediate steps: Markdown AST (MDAST), and Hypertext AST (HAST), before arriving at the final JSX output. MDX 플러그인 또한 두 가지 형태입니다.
플러그인을 사용해 프로젝트에서 가장 일반적으로 사용하는 JSX 요소를 좀 더 짧은 구문으로 만들 수 있습니다. 도큐사우루스에서 사용하는 준수 사항 구문은 Remark 플러그인으로 만들어지며 여러분도 여러분만의 준수 사항을 위한 플러그인을 사용할 수 있습니다.
기본 플러그인
도큐사우루스는 마크다운 처리를 위해 몇 가지 기본 Remark 플러그인을 사용합니다. 이런 플러그인은 다음 작업을 처리합니다.
- 컨텐츠 테이블 생성
- 각 제목에 링크 추가
- 이미지와 링크를
require()
호출로 변환 - …
이들은 모두 Remark 플러그인의 일반적인 사용 사례이며 여러분이 원하는 형태의 플러그인 개발 시 참고할 수 있습니다.
플러그인 설치하기
MDX 플러그인은 npm 패키지 형태로 제공됩니다. npm을 사용해 다른 npm 패키지처럼 설치할 수 있습니다. math 플러그인이라면 아래와 같이 설치합니다.
- npm
- Yarn
- pnpm
npm install --save remark-math@5 rehype-katex@6
yarn add remark-math@5 rehype-katex@6
pnpm add remark-math@5 rehype-katex@6
How are remark-math
and rehype-katex
different?
In case you are wondering how Remark and Rehype are different, here is a good example. remark-math
operates on the Markdown AST, where it sees text like $...$
, and all it does is transform that to the JSX <span class="math math-inline">...</span>
without doing too much with the content. This decouples the extraction of math formulae from their rendering, which means you can swap out with other math renderers, like MathJax (with rehype-mathjax
), just by replacing the Rehype plugin.
Next, the rehype-katex
operates on the Hypertext AST where everything has been converted to HTML-like tags already. It traverses all the elements with math
class and uses to parse and render the content to actual HTML.
Many official Remark/Rehype plugins are using ES Modules, a new JavaScript module system, which Docusaurus doesn't support yet. To work around this issue, we recommend to use dynamic import()
inside an async
config creation function.
Next, add them to the plugin options through plugin or preset config in docusaurus.config.js
, using dynamic import()
:
module.exports = async function createConfigAsync() {
return {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
path: 'docs',
remarkPlugins: [(await import('remark-math')).default],
rehypePlugins: [(await import('rehype-katex')).default],
},
},
],
],
};
};
플러그인 설정하기
일부 플러그인은 설정이나 옵션 기능을 지원합니다. 아래 설정에서 [plugin, pluginOptions]
구문이 그러한 항목입니다.
module.exports = async function createConfigAsync() {
return {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
rehypePlugins: [
[(await import('rehype-katex')).default, {strict: false}],
],
},
},
],
],
};
};
플러그인이 지원하는 옵션에 대해서는 플러그인 문서를 참고해야 합니다.
새로운 rehype/remark 플러그인 만들기
요구사항을 충족하는 기존 패키지가 없다면 새로운 MDX 플러그인을 만들 수 있습니다.
예를 들어 h2
로 작성한 항목 앞에 Section X.
형태 의 접두사를 붙이도록 플러그인을 만들 수 있습니다. 먼저 플러그인 소스 파일을 생성합니다. 별도의 npm 패키지로 배포하고 위에서 설명한 대로 설치할 수 있습니다. src/remark/section-prefix.js
파일로 작성할 겁니다. remark/rehype 플러그인은 options
값을 받아서 AST에서 처리한 transformer
를 반환하는 함수일 뿐입니다.
const visit = require('unist-util-visit');
const plugin = (options) => {
const transformer = async (ast) => {
let number = 1;
visit(ast, 'heading', (node) => {
if (node.depth === 2 && node.children.length > 0) {
node.children.unshift({
type: 'text',
value: `Section ${number}. `,
});
number++;
}
});
};
return transformer;
};
module.exports = plugin;
이제 docusaurus.config.js
에서 플러그인을 가져와 다른 설치된 플러그인처럼 사용할 수 있습니다!
const sectionPrefix = require('./src/remark/section-prefix');
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
remarkPlugins: [sectionPrefix],
},
},
],
],
};
transformer
에는 현재 마크다운 파일 경로에 접근해야 하는 경우 유용한 두 번째 매개변수 vfile
이 있습니다.
const plugin = (options) => {
const transformer = async (ast, vfile) => {
ast.children.unshift({
type: 'text',
value: `The current file path is ${vfile.path}`,
});
};
return transformer;
};
예를 들어 우리의 transformImage
플러그인은 해당 매개변수를 사용해 상대 이미지 참조를 require()
호출로 변환합니다.
도큐사우루스의 기본 플러그인은 사용자 정의 remark 플러그인보다 먼저 동작합니다. 때문에 require()
호출 시 이미지 또는 링크는 JSX로 변환됩 니다. 예를 들어 위의 예에서 모든 h2
제목에 Section X.
접두사가 붙더라도 생성된 목차는 달라지지 않습니다. 사용자 정의 플러그인보다 TOC-generating 플러그인이 호출되기 때문입니다. 기본 플러그인보다 먼저 MDAST를 처리해야 한다면 beforeDefaultRemarkPlugins
와 beforeDefaultRehypePlugins
를 사용하세요.
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
beforeDefaultRemarkPlugins: [sectionPrefix],
},
},
],
],
};
이렇게 하면 생성된 목차에 Section X.
접두사가 포함됩니다.