Next.js 14

[ Next.js 14 ] quill-image-resize 이미지 스타일 유지 안되는 문제 ( Image styles not being retained in quill-image-resize ) , code-block highlight

ToMakeSure 2024. 12. 11. 16:39
반응형

react-quill 이미지

 

.ql-editor blockquote {
  border-left: 4px solid #ccc; /* 좌측 강조선 */
  margin: 0;
  padding: 10px 15px !important;
  color: #555;
  background-color: #f9f9f9;
  font-style: italic;
  font-size: medium;
}

.ql-syntax {
  background-color: #f4f4f4 !important; /* 배경색 */
  padding: 15px !important; /* 여백 */
  font-family: "Courier New", Courier, monospace !important;
  color: #555 !important;
  font-size: small;
}

 

"use client";

import { useMemo } from "react";
import dynamic from "next/dynamic";
import ImageResize from "quill-image-resize";
import "react-quill/dist/quill.snow.css";
import hljs from "highlight.js";
import "highlight.js/styles/github.css";

hljs.configure({
  languages: ["javascript", "ruby", "python", "java", "cpp", "kotlin", "sql"],
});

// ReactQuill을 동적으로 import하여 서버 측 렌더링 비활성화
const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });

if (typeof window !== "undefined") {
  const { Quill } = require("react-quill");

  // 기존 이미지 포맷 가져오기
  var BaseImageFormat = Quill.import("formats/image");

  // 이미지 포맷 속성 정의
  const ImageFormatAttributesList = [
    "alt",
    "height",
    "width",
    "style",
    "align",
  ];

  // 이미지 포맷 클래스 확장
  class ImageFormat extends BaseImageFormat {
    static formats(domNode: any) {
      return ImageFormatAttributesList.reduce(function (
        formats: any,
        attribute
      ) {
        if (domNode.hasAttribute(attribute)) {
          formats[attribute] = domNode.getAttribute(attribute);
        }
        return formats;
      },
      {});
    }
    format(name: string, value: any) {
      if (ImageFormatAttributesList.indexOf(name) > -1) {
        if (value) {
          this.domNode.setAttribute(name, value);
        } else {
          this.domNode.removeAttribute(name);
        }
      } else {
        super.format(name, value);
      }
    }
  }

  // 확장된 이미지 포맷 등록
  Quill.register(ImageFormat, true);
  Quill.register("modules/imageResize", ImageResize);
}

export default function Editor({
  value,
  onChange,
}: {
  value: string;
  onChange: Function;
}) {
  // ReactQuill 모듈과 포맷을 useMemo로 메모이제이션
  const quillModules = useMemo(
    () => ({
      syntax: {
        highlight: (text: any) => hljs.highlightAuto(text).value,
      },

      toolbar: [
        [{ header: "1" }, { header: "2" }, { font: [] }],
        [{ size: [] }],
        ["bold", "italic", "underline", "strike", "blockquote", "code-block"],
        [
          { list: "ordered" },
          { list: "bullet" },
          { indent: "-1" },
          { indent: "+1" },
        ],
        [{ color: [] }, { background: [] }],
        ["link", "image"],
        ["clean"],
      ],
      imageResize: {},
      clipboard: {
        matchVisual: false, // 기본적으로 비주얼 데이터를 줄이는 옵션
      },
    }),
    []
  );

  const quillFormats = useMemo(
    () => [
      "header",
      "font",
      "size",
      "bold",
      "italic",
      "underline",
      "strike",
      "blockquote",
      "list",
      "bullet",
      "indent",
      "link",
      "image",
      "color",
      "background",
      "width",
      "style",
      "code-block",
    ],
    []
  );

  return (
    <div className="flex pb-10 relative">
      <ReactQuill
        style={{ width: "100%", minHeight: 300, maxHeight: 700 }}
        value={value}
        onChange={(e: any) => onChange(e)}
        modules={quillModules}
        formats={quillFormats}
      />
    </div>
  );
}
반응형