728x90
필요한 패키지
yarn add gray-matter # 문자열이나 파일에서 머리말을 구문 분석, 파일에서 메타데이터와 내용 등 추출 시 사용
yarn add marked
yarn add @types/marked # 타입스크립트의 경우
yarn add react-markdown # <div dangerouslySetInnerHTML={createMarkup()} />과 유사함
yarn add remark-gfm # 마크다운 문법이 다양하게 적용될 수 있도록 도와주는 플러그인
yarn add react-syntax-highlighter
yarn add @types/react-syntax-highlighter # 타입스크립트의 경우
참조
https://yarnpkg.com/package/react-markdown
https://yarnpkg.com/package/react-syntax-highlighter
- posting 파일들은 src 파일 안에 있다고 가정 -
// [slug].tsx 파일 생성
import { GetStaticPaths, GetStaticProps } from "next";
import { join } from "path";
import fs from "fs/promises";
import matter from "gray-matter";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
// import { darcula } from "react-syntax-highlighter/dist/esm/styles/prism"; - 에러 발생
import { dark } from "react-syntax-highlighter/dist/cjs/styles/prism";
import { vsDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
import { darcula } from "react-syntax-highlighter/dist/cjs/styles/prism";
interface Props {
title: string;
date: string;
content: string;
}
export default function BlogPost({ title, date, content }: Props) {
return (
<div>
<h1>{title}</h1>
<p>{date}</p>
<ReactMarkdown
className="markdown"
remarkPlugins={[remarkGfm]}
components={{
code({ inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || "");
return !inline && match ? (
<SyntaxHighlighter
language={match[1]}
PreTag="pre"
{...props}
// style={dark}
style={darcula}
// style={vsDark}
>
{String(children).replace(/\n$/, "")}
</SyntaxHighlighter>
) : (
<code className={className} {...props}>
{children}
</code>
);
},
}}
>
{content}
</ReactMarkdown>
</div>
);
}
// 파일명을 통해 url 생성
export const getStaticPaths: GetStaticPaths = async () => {
const postsDirectory = join(process.cwd() + "src" + "/posting", "blog");
const filenames = await fs.readdir(postsDirectory);
const paths = filenames.map(filename => ({
params: { slug: filename.replace(/\.md$/, "") },
}));
return { paths, fallback: false };
};
// url에 해당하는 파일명을 찾아 matter로 데이터 추출
export const getStaticProps: GetStaticProps<Props> = async ({ params }) => {
const slug = params?.slug as string;
const filePath = join(process.cwd() + "src" + "/posting", "blog", `${slug}.md`);
const fileContents = await fs.readFile(filePath, "utf8");
const { data, content } = matter(fileContents);
return {
props: {
title: data.title,
date: data.date,
content,
},
};
};
SyntaxHighlighter 내부의 style을 이용하기 위해서는 그에 맞는 소스를 가져와야 한다.
에러가 발생하는 ...dist/esm/styles/prism
import { darcula } from "react-syntax-highlighter/dist/esm/styles/prism";
에러가 발생하지 않는 imports
import { darcula } from "react-syntax-highlighter/dist/cjs/styles/prism";
import { dark } from "react-syntax-highlighter/dist/cjs/styles/prism";
import { vsDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
스타일 등은 <ReactMarkdown />의 className을 통해 수정해줄 수 있다.
markdown 파일 생성
// 파일명 : first-post.md
---
title: First-Post
date: "2023-02-28" <- 숫자만 사용하면 newDate()처럼 생성되어 타입 오류 발생 가능
---
# Deploy and test
holollollo
```javascript
const fn = () => {
return "hi"
}
```
파일 생성 후 해당 링크 접속 시 정상적으로 접속 가능해진다.
ex. localhost:3000/first-post
url은 [slug].tsx 파일이 위치한 경로에 따라 달라질 수 있다. (nextjs 라우팅 방식)
728x90
'개발일지 > github' 카테고리의 다른 글
[Github] 깃허브 토큰을 이용한 GithubAPI 사용 (0) | 2023.03.31 |
---|---|
utterances를 이용한 Nextjs Github blog 댓글 기능 구현 (0) | 2023.03.15 |
GithubAPI를 이용한 repository 정보 불러오기 (0) | 2023.03.15 |
깃허브 블로그 만들기 (0) | 2023.03.15 |
댓글