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

)을 사용해 유튜브 동영상을 삽입하려면 어떻게 해야 하나요? - 소셜 카드처럼 자체 라인에 있는 링크 스타일을 다르게 지정하려면 어떻게 해야 하나요?
- 모든 페이지에 저작권 표시를 하려면 어떻게 하나요?
해결책은 MDX 플러그인을 만드는 겁니다! MDX는 마크다운 파일을 구문분석하고 JSX로 변환하는 방식을 사용자가 지정할 수 있는 내장 플러그인 시스템이 있습니다. MDX 플러그인의 세 가지 일반적인 사용 사례는 다음과 같습니다.
- 기존 remark plugins 또는 rehype plugins을 사용합니다.
- 기존 MDX 구문으로 생성된 요소를 변환하기 위한 remark/rehype 플러그인을 만듭니다.
- MDX에 새로운 구문을 도입하기 위한 remark/rehype 플러그인을 만듭니다.
MDX 플레이그라운드에서 확인하고 있다면 MDX를 JSX로 변환 시 마크다운 AST(MDAST), 하이퍼텍스트 AST(HAST) 두 개의 중간 단계가 있다는 것을 확인할 수 있습니다. MDX 플러그인 또한 두 가지 형태입니다.
플러그인을 사용해 프로젝트에서 가장 일반적으로 사용하는 JSX 요소를 좀 더 짧은 구문으로 만들 수 있습니다. 도큐사우루스에서 사용하는 준수 사항 구문은 Remark 플러그인으로 만들어지며 여러분도 여러분만의 준수 사항을 위한 플러그인을 사용할 수 있습니다.
기본 플러그인
도큐사우루스는 마크다운 처리를 위해 몇 가지 기본 Remark 플러그인을 사용합니다. 이런 플러그인은 다음 작업을 처리합니다.
- 컨텐츠 테이블 생성
- 각 제목에 링크 추가
- 이미지와 링크를
require()
호출로 변환 - …
이들은 모두 Remark 플러그인의 일반적인 사용 사례이며 여러분이 원하는 형태의 플러그인 개발 시 참고할 수 있습니다.
플러그인 설치하기
MDX 플러그인은 npm 패키지 형태로 제공됩니다. npm을 사용해 다른 npm 패키지처럼 설치할 수 있습니다. math 플러그인이라면 아래와 같이 설치합니다.
- npm
- Yarn
- pnpm
npm install --save [email protected] [email protected]
yarn add [email protected] [email protected]
pnpm add [email protected] [email protected]
최근 Remark/Rehype 생태계는 도큐사우루스에서 아직 지원하지 않는 새로운 자바스크립트 모듈 시스템인 ES 모듈로 마이그레이션하는 추세가 있습니다. ESM을 공식적으로 지원하기 전에는 설치된 플러그인 버전이 CommonJS와 호환되는지 확인하세요. 또는 rehype-katex
설치 튜토리얼에서 해결책으로 동적 import()
사용에 대한 가이드를 찾아볼 수 있습니다.
remark-math
와 rehype-katex
는 어떻게 다릅니까?
Remark와 Rehype가 어떻게 다른지 궁금하시다면 여기 좋은 예가 있습니다. 마크다운 AST에서 동작하는 remark-math
는 $...$
와 같은 텍스트를 인식합니다. 그리고 JSX에서는 콘텐츠는 건드리지 않은 채 <span class="math math-inline">...</span>
형태로 변환합니다. 렌더링 시에 수학 공식은 추출해 분리합니다. 즉 Rehype 플러그인을 교체하기만 하면 MathJax(rehype-mathjax
을 포함한)와 같은 다른 수학 렌더러로 을 바꿀 수 있습니다.
하이퍼텍스트 AST에서 동작하는 rehype-katex
은 모든 것을 HTML 태그 형태로 변환합니다. math
클래스로 모든 요소를 탐색하고 로 콘텐츠를 구문 분석하고 실제 HTML로 변환합니다.
그런 다음 docusaurus.config.js
에서 플러그인 또는 사전 설정 구성을 플러그인 옵션에 추가합니다.
const math = require('remark-math');
const katex = require('rehype-katex');
module.exports = {
title: 'Docusaurus',
tagline: 'Build optimized websites quickly, focus on your content',
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
remarkPlugins: [math],
rehypePlugins: [katex],
},
},
],
],
};
플러그인 설정하기
일부 플러그인은 설정이나 옵션 기능을 지원합니다. 아래 설정에서 [plugin, pluginOptions]
구문이 그러한 항목입니다.
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
remarkPlugins: [math],
rehypePlugins: [
[katex, {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.
접두사가 포함됩니다.