Next.js rehype-pretty-code로 syntax highlight 적용하기
Next.js로 마크다운 형식의 블로그를 제작하던 중 발견한 이슈
remarkGfm(마크다운 스타일 적용 플러그인)
까지 적용을 했는데도 코드블럭에 syntax highlight가 적용이 안되어있고- 인라인 코드 부분에 백틱이 보이고 있다.
심히 거슬리니 고쳐봅시다
목표
- 마크다운 내부의 코드블럭에 rehypePrettyCode 을 사용하여 syntax highlight를 적용
- 인라인 코드 스타일링 수정
next-mdx-remote를 이미 사용하고 있다는 전제 하에 설명하고 있습니다
rehype-pretty-code 설치
yarn add rehype-pretty-code shiki
마크다운 컴포넌트 내부에 적용
<MDXRemote
source={content}
options:{{
mdxOptions: {
remarkPlugins: [
remarkGfm,
//...other remark plugins
],
rehypePlugins:[rehypePrettyCode,prettyCodeOptions](rehypePrettyCode,prettyCodeOptions),
},
}}
/>
플러그인 옵션 설정하기 및 스타일링
rehype-pretty-code
는 다양한 옵션들을 제공하는데, 그 중에서도 현재 사용하고 있는 몇가지 기본 옵션들을 간단하게 짚어보자.
1. 스타일 설정
This library is unstyled. This means it does not provide a CSS file that applies styling by default. Rather, it provides logical attributes that you use to apply the styling yourself.
공식 문서에도 설명되어있다시피, rehype-pretty-code는 별도로 스타일링이 적용이 되어있지 않다. 나는 globals.css
파일에 아래와 같이 설정을 해주었다.
...
.prose {
...
/*==Code Block==*/
figure[data-rehype-pretty-code-figure] {
@apply my-5;
}
pre {
@apply p-5;
/* 행간 축소 */
span[data-line] {
@apply inline-block leading-snug;
}
/* 자동 줄바꿈 */
code {
@apply whitespace-pre-wrap;
}
}
}
2. 테마 설정
rehype-pretty-code
의 syntax highlight 기능은 Shiki 라는 syntax highlighter을 통해서 제공하고 있다. 테마 또한 마찬가지로 Shiki
에서 제공하는 테마를 사용하는 방법이 있고, 아니면 vscode에서 원하는 테마를 JSON 파일로 제공하는 방법이 있다.
내가 VSC에서 주로 사용하는 테마는 이미 Shiki에서 제공을 하고 있어서, 바로 설정을 해주었다
...
const prettyCodeOptions = {
theme: 'tokyo-night'
}
만약 Shiki에서 제공하는 테마가 아닌 다른 vscode 테마를 사용하고 싶다면, 해당 테마의 JSON파일을 긁어와 아래와 같은 방법으로 사용하면 된다.
const prettyCodeOptions = {
theme: JSON.parse(readFileSync("public/code_themes/NightOwl.json", "utf-8")),
};
다크모드 여부에 따라 각각 다른 테마를 사용하는 것도 가능하다.
const prettyCodeOptions = {
dark: 'dark-theme',
light: 'light-theme'
}
3. 줄 번호 표시
코드블럭 좌측에 줄번호를 표시할 수 있다.
```js showLineNumbers
```
이런식으로 코드블럭 생성 시 showLineNumbers
를 같이 넘겨주면 좌측에 줄 번호가 표시된다.
console.log("hi");
console.log("hihi");
html 변환 결과를 보면, <code>
태그 내부에 data-line
에 대한 속성들이 추가되어있는걸 확인할 수 있다.
줄 번호 또한 별도의 스타일링이 필요한데, 나는 공식문서에 있는 내용과 동일하게 설정해주었다.
code[data-line-numbers] {
counter-reset: line;
}
code[data-line-numbers] > [data-line]::before {
counter-increment: line;
content: counter(line);
/* Other styling */
display: inline-block;
width: 0.75rem;
margin-right: 2rem;
text-align: right;
color: gray;
}
code[data-line-numbers-max-digits="2"] > [data-line]::before {
width: 1.25rem;
}
code[data-line-numbers-max-digits="3"] > [data-line]::before {
width: 1.75rem;
}
code[data-line-numbers-max-digits="4"] > [data-line]::before {
width: 2.25rem;
}
만약, 특정 번호를 시작으로 줄번호를 넘기고 싶은 경우에는 showLineNumbers{n}
이런식으로 값을 넘겨주면 된다.
```js showLineNumbers{5}
console.log('test show numbers')
```
4. 코드블럭 타이틀 설정
코드블럭 위에 제목을 달아줄 수 있다. title="your title here"
이런식으로 스트링 형식으로 감싸주기만 하면 끝!
```js title="Title 설정"
```
//codes
html 변환 결과를 확인해보면, title
을 설정한 블럭만 <figcaption data-rehype-pretty-code-title ...>
이라는 태그가 하나 더 생성된 것을 확인할 수 있는데, 이걸 사용해서 스타일을 적용할 수 있다.
figcaption[data-rehype-pretty-code-title] {
@apply rounded-t-md bg-[var(--codeblock-background)] px-5 py-2 font-mono text-sm italic;
}
figcaption[data-rehype-pretty-code-title] + pre {
@apply mt-0 rounded-t-none;
}
5. 인라인 코드 스타일 설정
인라인 코드에 백틱이 여전히 나타나는 문제는 아래와 같이 ::before
, ::after
속성에 display: none
(여기서는 tailwind.css 문법을 사용하니까 hidden
)을 적용시켜 안 보이게 가려주었다.
/*==Inline Code==*/
:not(pre) > code {
@apply rounded-sm border bg-[image:var(--background-alt)] px-1 font-medium text-[var(--inline-code-color)];
}
:not(pre) > code::before,
:not(pre) > code::after {
@apply hidden;
}
이 외에도 더 많은 옵션에 대한 설명은
에서 확인할 수 있다. 정말 정리를 잘 해주셔서 많은 도움을 받았습니다...감사합니다....