설치 및 기본 사용법
Shiki는 다양한 테마와 언어에 대해 코드 하이라이팅을 제공하는 도구입니다. Markdown 파일을 HTML로 변환할 때 코드 블록에 서버사이드 하이라이팅을 적용하여 클라이언트 부담 없이 정확한 색상 출력을 얻을 수 있습니다.
설치
먼저, 프로젝트에 Shiki와 관련된 패키지를 설치합니다. 아래 명령어를 사용하여 @shikijs/rehype를 설치할 수 있습니다.
npm i -D @shikijs/rehype
사용법
Shiki를 사용하려면 unified와 함께 remark와 rehype 시리즈의 플러그인을 사용하여 Markdown 파일을 처리하고, HTML로 변환합니다. 다음은 기본적인 사용 예제입니다.
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import rehypeShiki from '@shikijs/rehype';
const file = await unified()
.use(remarkParse) // Markdown을 파싱
.use(remarkRehype) // HTML로 변환
.use(rehypeShiki, {
// 단일 테마
// theme: 'vitesse-light' // 단일 테마 사용
// 다중 테마
themes: {
light: 'vitesse-light', // 라이트 테마
dark: 'vitesse-dark' // 다크 테마
}
})
.use(rehypeStringify) // HTML 문자열로 변환
.process(await fs.readFile('./input.md')); // Markdown 파일을 읽고 처리
이 코드는 input.md라는 파일을 읽어와서, 해당 파일의 코드 블록에 Shiki를 사용해 라이트/다크 테마를 적용한 후, HTML로 변환합니다.
Shiki 인스턴스 관리
기본적으로 @shikijs/rehype의 기본 내보내기(default export)는 getSingletonHighlighter에서 공유되는 Shiki 인스턴스를 사용합니다. 이는 여러 프로세스에서 인스턴스가 지속됩니다. 그러나 Shiki 하이라이터의 수명 주기를 완전히 제어하고 싶다면, @shikijs/rehype/core의 세분화된 번들(Fine-grained Bundle)을 사용할 수 있습니다.
세분화된 번들 사용법
Shiki의 전체 번들 대신, 필요한 부분만 불러와 사용하고 싶다면 rehypeShikiFromHighlighter를 사용할 수 있습니다. 다음은 세분화된 번들을 사용하는 예제입니다.
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import rehypeShikiFromHighlighter from '@shikijs/rehype/core';
import { createHighlighterCore } from 'shiki/core';
const highlighter = await createHighlighterCore({
themes: [
import('shiki/themes/vitesse-light.mjs') // 라이트 테마
],
langs: [
import('shiki/langs/javascript.mjs') // JavaScript 언어 하이라이팅
],
loadWasm: import('shiki/wasm') // WASM 파일 로드
});
const raw = await fs.readFile('./input.md');
const file = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeShikiFromHighlighter, highlighter, {
themes: {
light: 'vitesse-light',
dark: 'vitesse-dark'
}
})
.use(rehypeStringify)
.processSync(raw); // 동기적으로 처리 가능
이 예제에서는 필요한 테마와 언어만 선택적으로 불러와서 사용할 수 있습니다. 이는 번들 크기를 줄이고, 더 나은 성능을 제공할 수 있습니다.