저번에는 저장된 마크다운 파일 기반으로 포스팅 리스트과 포스팅 페이지 라우팅을 만드는 기능을 추가했다.
이번 글에서는 마크다운으로 저장된 string 을 해당하는 React 엘리멘트로 변환시켜 HTML 내에서 렌더링될 수 있게 하는 기능에 대해 설명한다.
react-markdown 은 마크다운 파일의 string 을 React 엘리멘트로 변환해주는 핵심 기능을 제공해주는 라이브러리이다.
react-syntax-highlighter 는 필수는 아니지만 작성된 코드 스니펫을 보기 좋은 하이라이트 테마를 적용해주는 라이브러리로, 코드 적을 일이 많은 개발 블로그에서는 사용하면 좋다.
npm install react-markdown react-syntax-highlighter
이전에 작성한 포스팅 페이지에 설치한 react-markdown 을 적용할 것이다.
import { Params } from "next/dist/server/router"; import fs from "fs"; import ReactMarkdown from "react-markdown"; import { getBlogPostbySlug } from "lib/matter-util"; import { PostProps } from "types/blog"; import PostContainer from "container/PostContainer"; import CodeBlock from "components/markdown/CodeBlock"; const BlogPost = ({ frontMatter, content }: PostProps) => { if (!frontMatter) return false; return ( <PostContainer frontMatter={frontMatter}> <ReactMarkdown components={{ code: CodeBlock }}>{content}</ReactMarkdown> </PostContainer> ); }; export const getStaticProps = async ({ params }: Params) => { const post = await getBlogPostbySlug(params.slug); return { props: post, }; }; export const getStaticPaths = async () => { const files = fs.readdirSync("posts/blog"); const paths = files.map((fileName) => ({ params: { slug: fileName.replace(/\.md/, ""), }, })); return { paths, fallback: false, }; }; export default BlogPost;
import { Prism as SyntaxHighLighter } from "react-syntax-highlighter"; import { vscDarkPlus } from "react-syntax-highlighter/dist/cjs/styles/prism"; interface CodeBlockProps { inline?: boolean; className?: string; children: React.ReactNode; } const CodeBlock = ({ inline, className, children }: CodeBlockProps) => { const match = /language-(\w+)/.exec(className || ""); if (!inline && match) return ( <SyntaxHighLighter style={vscDarkPlus} language={match[1]} PreTag="div"> {children} </SyntaxHighLighter> ); else return <code className={className}>{children}</code>; }; export default CodeBlock;