Hanbbi's DevLog

Simple Memo

Github pages 블로그 Markdown 불러오기

2023-03-12

Markdown을 통해 블로그를 작성하는 이유

  • 머리말을 따로 설정해 route 링크를 설정해주거나 제목, 날짜, 카테고리, 등을 설정하여 블로그 탐색을 용이하게 해줄 수 있다.
  • Markdown을 repository에 저장함으로써 githubAPI 등을 이용한 데이터 조회를 가능하게 한다.

필요한 패키지

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 파일 안에 있다고 가정

1. [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"; // Link, table, checklist 등의 형식을 표현할 수 있게 해줌
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,
    },
  };
};

2. SyntaxHighlighter style 설정

SyntaxHighlighter 내부의 코드블록 style을 이용하기 위해서는 그에 맞는 소스를 가져와야 한다.

에러가 발생하는 ...dist/esm/styles/prism

import { darcula } from "react-syntax-highlighter/dist/esm/styles/prism";

image

정상 작동하는 imports ...dist/cjs/styles/prism

import { darcula } from "react-syntax-highlighter/dist/cjs/styles/prism";

image

import { dark } from "react-syntax-highlighter/dist/cjs/styles/prism";

image

import { vsDark } from "react-syntax-highlighter/dist/cjs/styles/prism";

image

원하는 스타일을 SyntaxHighlighter style에 넣어주면 된다.

Markdown content(내용)는 ReactMarkdown 컴포넌트의 className을 통해 수정해줄 수 있다.

3. Markdown 파일 생성

// 파일명 : first-post.md
--- 머리말
title: First-Post
date: "2023-02-28" <- 숫자만 사용하면 newDate()처럼 생성되어 타입 오류 발생 가능

---

# Deploy and test

test

Markdown 파일의 데이터를 불러올때, 머리말을 이용한 metaTag 설정이나 제목 등을 자유롭게 설정할 수 있다.

파일 생성 후 해당 링크 접속 시 정상적으로 접속이 가능해진다.

ex

localhost:3000/first-post

url은 [slug].tsx 파일이 위치한 경로에 따라 달라질 수 있다. (nextjs 라우팅 방식)

Simple Memo 카테고리의 다른 글

    COMMENTS