Syntax Highlighting
예전부터 다른 개발자분들의 블로그나 Hashnode에서 게시글 내의 코드가 구문 강조되어 있는 것을 볼 수 있었습니다.
관련된 라이브러리를 찾아보니 다양한 라이브러리가 있는 것을 알 수 있었고, 그 중에서 Prism를 사용해 보기로 하였습니다.
1. Rehype plugin
처음으로 사용한 방법은 Next blog template에 있는 rehype plugin을 사용하는 방법이었습니다.
next-mdx-remote의 serialize 함수의 옵션으로 rehype plugin을 사용할 수 있었고, 그 중에서 MDX Syntax highlighting 페이지에서 예제로 제시된 @mapbox/rehype-prism을 사용해보기로 하였습니다.
// [post].tsx
import { serialize } from 'next-mdx-remote/serialize';
import rehypePrism from '@mapbox/rehype-prism';
const mdxSource = await serialize(content, {
scope: data,
mdxOptions: { rehypePlugins: [rehypePrism] },
});
이 방법에는 문제가 있었습니다.
@mapbox/rehype-prism plugin이 TypeScript를 지원하지 않았습니다.
다른 Rehype 나 Remark plugin도 찾아보았지만, 특별히 TypeScript를 지원하는 경우를 찾지 못 했습니다.
임시 방편으로 global module로 정의하여 동작하게 할 수는 있었지만, 아무래도 찝찝한 기분이었습니다.
// global.d.ts
declare module '@mapbox/rehype-prism';
2. React Hook
두번째로 찾게 된 방법이 React의 useEffect hook을 사용하는 방법이었습니다.
import React, { useEffect } from 'react';
import Prism from 'prismjs';
import 'prismjs/themes/prism-tomorrow.css';
import './styles.css';
export default function Code({ code, language }) {
useEffect(() => {
Prism.highlightAll();
}, []);
return (
<div className="Code">
<pre>
<code className={`language-${language}`}>{code}</code>
</pre>
</div>
);
}
출처 - DEV
위의 코드를 적용하여, 구문 강조를 적용할 수 있었습니다.
// [post].tsx
import { useEffect } from 'react';
import Prism from 'prismjs';
import 'prismjs/components/prism-typescript.min';
import 'prismjs/components/prism-jsx.min';
import 'prismjs/components/prism-tsx.min';
export default function Post() {
useEffect(() => {
Prism.highlightAll();
}, []);
}
// _app.tsx
import 'prismjs/themes/prism-tomorrow.css';
Summary
두번째 방법을 통해서 Prism를 적용할 수 있었지만, 아직 해결되지 않은 부분이 있었습니다.
// [post].tsx
import 'prismjs/components/prism-typescript.min';
import 'prismjs/components/prism-jsx.min';
import 'prismjs/components/prism-tsx.min';
이처럼 사용할 언어를 미리 import 해야하는 점이었습니다.
다행히 Prism의 plugin으로 autoloader가 있긴 했지만, webpack 설정의 문제인지 찾아낸 언어의 스크립트 파일을 불러오지 못 하는 것을 확인했습니다.
일단은 Prism에 명시된 기본 언어인 markup, css, js와 jsx, ts, tsx로 사용에 지장은 없었지만, 차후에 autoloader를 사용하는 법을 확인해야겠습니다.