메인 컨텐츠로 이동
버전: 2.0.0-beta.21

MDX 플러그인

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

  • image 구문(![](https://youtu.be/yKNxeF4KMsY))을 사용해 유튜브 동영상을 삽입하려면 어떻게 해야 하나요?
  • 소셜 카드처럼 자체 라인에 있는 링크 스타일을 다르게 지정하려면 어떻게 해야 하나요?
  • 모든 페이지에 저작권 표시를 하려면 어떻게 하나요?

해결책은 MDX 플러그인을 만드는 겁니다! MDX는 마크다운 파일을 구문분석하고 JSX로 변환하는 방식을 사용자가 지정할 수 있는 내장 플러그인 시스템이 있습니다. MDX 플러그인의 세 가지 일반적인 사용 사례는 다음과 같습니다.

  • 기존 remark plugins 또는 rehype plugins을 사용합니다.
  • 기존 MDX 구문으로 생성된 요소를 변환하기 위한 remark/rehype 플러그인을 만듭니다.
  • MDX에 새로운 구문을 도입하기 위한 remark/rehype 플러그인을 만듭니다.

MDX 플레이그라운드에서 확인하고 있다면 MDX를 JSX로 변환 시 마크다운 AST(MDAST), 하이퍼텍스트 AST(HAST) 두 개의 중간 단계가 있다는 것을 확인할 수 있습니다. MDX 플러그인 또한 두 가지 형태입니다.

  • Remark: 마크다운 AST를 처리합니다.
  • Rehype: 하이퍼텍스트 AST를 처리합니다.

플러그인을 사용해 프로젝트에서 가장 일반적으로 사용하는 JSX 요소를 좀 더 짧은 구문으로 만들 수 있습니다. 도큐사우루스에서 사용하는 준수하항 구문은 Remark plugin으로 만들어지며 여러분도 비슷한 사례에 이를 적용할 수 있습니다.

기본 플러그인

도큐사우루스는 마크다운 처리를 위해 몇 가지 기본 Remark 플러그인을 사용합니다. 이런 플러그인은 다음 작업을 처리합니다.

  • 컨텐츠 테이블 생성
  • 각 제목에 링크 추가
  • 이미지와 링크를 require() 호출로 변환

이들은 모두 Remark 플러그인의 일반적인 사용 사례이며 여러분이 원하는 형태의 플러그인 개발 시 참고할 수 있습니다.

플러그인 설치하기

MDX 플러그인은 npm 패키지 형태로 제공됩니다. npm을 사용해 다른 npm 패키지처럼 설치할 수 있습니다. math 플러그인이라면 아래와 같이 설치합니다.

참고

최근 Remark/Rehype 생태계는 도큐사우루스에서 아직 지원하지 않는 새로운 자바스크립트 모듈 시스템인 ES 모듈로 마이그레이션하는 추세가 있습니다. ESM을 공식적으로 지원하기 전에는 설치된 플러그인 버전이 CommonJS와 호환되는지 확인하세요. 또는 rehype-katex 설치 튜토리얼에서 해결책으로 동적 import() 사용에 대한 가이드를 찾아볼 수 있습니다.

remark-mathrehype-katex는 어떻게 다릅니까?

Remark와 Rehype가 어떻게 다른지 궁금하시다면 여기 좋은 예가 있습니다. 마크다운 AST에서 동작하는 remark-math$...$와 같은 텍스트를 인식합니다. 그리고 JSX에서는 콘텐츠는 건드리지 않은 채 <span class="math math-inline">...</span> 형태로 변환합니다. 렌더링 시에 수학 공식은 추출해 분리합니다. 즉 Rehype 플러그인을 교체하기만 하면 MathJax(rehype-mathjax을 포함한)와 같은 다른 수학 렌더러로 KaTeX\KaTeX을 바꿀 수 있습니다.

하이퍼텍스트 AST에서 동작하는 rehype-katex은 모든 것을 HTML 태그 형태로 변환합니다. math 클래스로 모든 요소를 탐색하고 KaTeX\KaTeX로 콘텐츠를 구문 분석하고 실제 HTML로 변환합니다.

그런 다음 docusaurus.config.js에서 플러그인 또는 사전 설정 구성을 플러그인 옵션에 추가합니다.

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] 구문이 그러한 항목입니다.

docusaurus.config.js
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
remarkPlugins: [math],
rehypePlugins: [
[katex, {strict: false}],
],
},
},
],
],
};

플러그인이 지원하는 옵션에 대해서는 플러그인 문서를 참고해야 합니다.

새로운 rehype/remark 플러그인 만들기

요구사항을 충족하는 기존 패키지가 없다면 새로운 MDX 플러그인을 만들 수 있습니다.

참고

아래 설명은 플러그인 생성에 대한 포괄적인 가이드는 아니며 도큐사우루스에서 작업하는 방식에 대한 예시일 뿐입니다. 작업 방식에 대한 상세한 설명은 Remark 또는 Rehype 문서를 참고하세요.

예를 들어 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에서 플러그인을 가져와 다른 설치된 플러그인처럼 사용할 수 있습니다!

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를 처리해야 한다면 beforeDefaultRemarkPluginsbeforeDefaultRehypePlugins를 사용하세요.

docusaurus.config.js
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
beforeDefaultRemarkPlugins: [sectionPrefix],
},
},
],
],
};

이렇게 하면 생성된 목차에 Section X. 접두사가 포함됩니다.