반응형
참고
리액트에서 HTML의 요소(Toast UI Editor Viewer)를 .pdf로 다운로드 받아 보자.
링크에서 실제로 에디터를 편집하고 다운로드 받아볼 수 있다.
여기서는 html2pdf.js를 사용한다.
npm install html2pdf.js --legacy-peer-deps
구현
다운로드하고 싶은 영역을 아래와 같이 id로 추가한다. (pdf-download)
<div id="pdf-download" className="toast-editor-viewer"></div>
버튼을 추가해 아래 메서드를 실행하면 원하는 요소를 pdf로 다운로드 받을 수 있다.
옵션은 아래 내용을 참고하자.
const downloadPDF = () => {
const element = document.getElementById("pdf-download"); // PDF로 변환할 요소 선택
html2pdf(element, {
filename: "Toast_Editor.pdf", // default : file.pdf
html2canvas: { scale: 2 }, // 캡처한 이미지의 크기를 조절, 값이 클수록 더 선명하다.
jsPDF: {
format: "b4", // 종이 크기 형식
orientation: "portrait", // or landscape : 가로
},
callback: () => {
console.log("PDF 다운로드 완료");
},
});
};
전체 코드는 다음과 같다.
import React, { useEffect, useRef, useState } from "react";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
// Toast UI Editor
import "@toast-ui/editor/dist/toastui-editor.css";
import "@toast-ui/editor/dist/toastui-editor-viewer.css"; // Viewer css
import { Editor } from "@toast-ui/react-editor";
import Viewer from "@toast-ui/editor/dist/toastui-editor-viewer";
// Dark Theme 적용
// import '@toast-ui/editor/dist/toastui-editor.css';
// import '@toast-ui/editor/dist/theme/toastui-editor-dark.css';
// Color Syntax Plugin
import "tui-color-picker/dist/tui-color-picker.css";
import "@toast-ui/editor-plugin-color-syntax/dist/toastui-editor-plugin-color-syntax.css";
import colorSyntax from "@toast-ui/editor-plugin-color-syntax";
// Table Merged Cell Plugin
import "@toast-ui/editor-plugin-table-merged-cell/dist/toastui-editor-plugin-table-merged-cell.css";
import tableMergedCell from "@toast-ui/editor-plugin-table-merged-cell";
import html2pdf from 'html2pdf.js';
const colorSyntaxOptions = {
preset: [
"#333333", "#666666", "#FFFFFF", "#EE2323", "#F89009", "#009A87", "#006DD7", "#8A3DB6",
"#781B33", "#5733B1", "#953B34", "#FFC1C8", "#FFC9AF", "#9FEEC3", "#99CEFA", "#C1BEF9",
],
};
const CONTENT_KEY = "CONTENT_KEY";
const ToastEditor = () => {
const editorRef = useRef(null);
const [editMode, setEditMode] = useState(false);
let initData = `# 제목
***~~<span style="color: #EE2323">내용</span>~~***
* [x] 체크박스
* [ ] 체크박스 2`;
const handleSave = () => {
let markDownContent = editorRef.current.getInstance().getMarkdown();
let htmlContent = editorRef.current.getInstance().getHTML();
console.log(markDownContent);
console.log(htmlContent);
localStorage.setItem(CONTENT_KEY, markDownContent);
};
useEffect(() => {
let item = localStorage.getItem(CONTENT_KEY);
if (editMode === false) {
const viewer = new Viewer({
el: document.querySelector(".toast-editor-viewer"),
viewer: true,
height: "400px",
usageStatistics: false, // 통계 수집 거부
plugins: [tableMergedCell],
});
if (item) viewer.setMarkdown(item);
else viewer.setMarkdown(initData);
}
if (item) {
if (editorRef.current) editorRef.current.getInstance().setMarkdown(item);
} else {
if (editorRef.current)
editorRef.current.getInstance().setMarkdown(initData);
}
}, [editMode]);
const downloadPDF = () => {
const element = document.getElementById("pdf-download"); // PDF로 변환할 요소 선택
html2pdf(element, {
filename: "Toast_Editor.pdf", // default : file.pdf
html2canvas: { scale: 2 }, // 캡처한 이미지의 크기를 조절, 값이 클수록 더 선명하다.
jsPDF: {
format: "b4", // 종이 크기 형식
orientation: "portrait", // or landscape : 가로
},
callback: () => {
console.log("PDF 다운로드 완료");
},
});
};
return (
<div>
<Box sx={{ m: 2 }}>
<h1>Toast UI Editor</h1>
<Button
variant="outlined"
color="secondary"
sx={{ m: 1 }}
onClick={() => setEditMode(!editMode)}
>
{editMode ? "취소하기" : "편집하기"}
</Button>
<Button
variant="outlined"
color="primary"
sx={{ m: 1 }}
onClick={handleSave}
disabled={editMode === false}
>
저장하기
</Button>
<Button
variant="outlined"
color="warning"
sx={{ m: 1 }}
onClick={downloadPDF}
>
PDF Download
</Button>
{editMode === false && <div id="pdf-download" className="toast-editor-viewer"></div>}
{editMode === true && (
<Editor
ref={editorRef}
// initialValue={initContents}
height="400px"
placeholder="Please Enter Text."
previewStyle="tab" // or vertical
initialEditType="wysiwyg" // or markdown
// hideModeSwitch={true} // 하단 숨기기
toolbarItems={[
// 툴바 옵션 설정
["heading", "bold", "italic", "strike"],
["hr", "quote"],
["ul", "ol", "task", "indent", "outdent"],
["table", /* "image", */ "link"],
["code", "codeblock"],
]}
//theme="dark"
//useCommandShortcut={false} // 키보드 입력 컨트롤 방지 ex ctrl z 등
usageStatistics={false} // 통계 수집 거부
plugins={[[colorSyntax, colorSyntaxOptions], tableMergedCell]}
/>
)}
</Box>
</div>
);
};
export default ToastEditor;
반응형
댓글