본문 바로가기
개발/React

리액트 - 마크다운을 HTML로 변환하기 (Convert Markdown to HTML in React)

by 피로물든딸기 2023. 7. 10.
반응형

리액트 전체 링크

 

참고

- 깃허브 RESTful API로 파일 편집기 만들기

- 깃허브 RESTful API 한글 깨짐 현상 해결하기

- 깃허브 마크다운 스타일 적용하기

- Toast UI 에디터로 깃허브 마크다운 저장하기

 

마크다운으로 만든 내용을 HTML로 변환해서 react에 보여주자.

먼저 react-markdown을 다운로드 받는다.

npm install react-markdown

 

깃허브 파일 편집기를 참고하여 코드를 아래와 같이 수정한다.

먼저, repo와 path는 아래와 같이 초기화한다.

  const [repo, setRepo] = useState("auto-test");
  const [path, setPath] = useState("README.md");

 

여기서 불러올 내용은 아래 링크의 README.md이다. 

https://github.com/bloodstrawberry/auto-test/blob/main/README.md

 

불러온 마크다운을 통째로 ReactMarkdown에 넣어주기만 하면 된다.

<ReactMarkdown>{contents}</ReactMarkdown>

 

README.md를 불러오면 textarea에는 마크다운을 작성한 텍스트가 그대로 나타나지만,

그 아래(ReactMarkdown)에는 README.md가 html 형식으로 출력되는 것을 알 수 있다.

 

전체 코드는 다음과 같다.

import React, { useState } from "react";

import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import { TextField } from "@mui/material";
import { Textarea } from "@mui/joy";
import { Octokit } from "@octokit/rest";
import { ReactMarkdown } from "react-markdown/lib/react-markdown";

let myKey = "...";

const App = () => {
  const [repo, setRepo] = useState("auto-test");
  const [path, setPath] = useState("README.md");
  const [contents, setContents] = useState("");

  const getSHA = async (octokit) => {
    const result = await octokit.request(
      `GET /repos/bloodstrawberry/${repo}/contents/${path}`,
      {
        owner: "bloodstrawberry",
        repo: `${repo}`,
        path: `${path}`,
      }
    );

    return result.data.sha;
  };

  const fileWrite = async () => {
    const octokit = new Octokit({
      auth: myKey,
    });

    const currentSHA = await getSHA(octokit);
    const result = await octokit.request(
      `PUT /repos/bloodstrawberry/${repo}/contents/${path}`,
      {
        owner: "bloodstrawberry",
        repo: `${repo}`,
        path: `${path}`,
        message: "commit message!",
        sha: currentSHA,
        committer: {
          name: "bloodstrawberry",
          email: "bloodstrawberry@github.com",
        },
        content: `${btoa(unescape(encodeURIComponent(`${contents}`)))}`,
        headers: {
          "X-GitHub-Api-Version": "2022-11-28",
        },
      }
    );

    console.log(result.status);
  };

  const fileRead = async () => {
    const octokit = new Octokit({
      auth: myKey,
    });

    const result = await octokit.request(
      `GET /repos/bloodstrawberry/${repo}/contents/${path}`,
      {
        owner: "bloodstrawberry",
        repo: `${repo}`,
        path: `${path}`,
        encoding: "utf-8",
        decoding: "utf-8",
      }
    );

    setContents(decodeURIComponent(escape(window.atob(result.data.content))));
  };

  return (
    <div>
      <h1>깃허브 파일 편집기</h1>
      <Stack sx={{ m: 5 }} spacing={2} direction="row">
        <Button variant="outlined" color="primary" onClick={fileRead}>
          불러오기
        </Button>
        <Button variant="outlined" color="secondary" onClick={fileWrite}>
          저장하기
        </Button>
      </Stack>
      <Stack sx={{ m: 5 }} spacing={2} direction="row">
        <TextField
          id="outlined-required"
          label="repository"
          value={repo}
          onChange={(e) => setRepo(e.target.value)}
        />
        <TextField
          id="outlined-required"
          label="filePath"
          value={path}
          onChange={(e) => setPath(e.target.value)}
        />
      </Stack>
      <Stack sx={{ m: 5 }}>
        <Textarea
          name="Primary"
          placeholder="Type in here…"
          variant="outlined"
          color="primary"
          value={contents}
          onChange={(e) => setContents(e.target.value)}
        />
      </Stack>
      <Stack sx={{ m: 2 }}>
        <ReactMarkdown>{contents}</ReactMarkdown>
      </Stack>
    </div>
  );
};

export default App;
반응형

댓글