Skip to content

Vue 3

설치

bash
npm install @newtil/editor vue

사용

vue
<script setup>
import "@newtil/editor";                        // Custom Element 등록 (필수, 래퍼보다 먼저)
import { NewtilEditor } from "@newtil/editor/vue";
import { ref } from "vue";

const content = ref("");
</script>

<template>
  <NewtilEditor v-model="content" toolbar placeholder="여기에 입력..." />
</template>

WARNING

import "@newtil/editor" 는 Custom Element 를 전역 등록한다. Vue 래퍼보다 먼저 import 해야 한다.

Vue 가 <newtil-editor> 를 알 수 없는 컴포넌트로 경고할 수 있다. vite.config.ts 에서 무시 설정:

ts
export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag === "newtil-editor",
        },
      },
    }),
  ],
});

Props

정본은 src/vue/index.ts. React 래퍼와 대칭이 아니다 — Vue 래퍼에는 lang·messages·className·style prop 이 없다.

Prop타입기본값설명
modelValue (v-model)string""마크다운 양방향 바인딩
placeholderstring""빈 편집기 안내
readonlybooleanfalse읽기 전용
toolbarbooleanfalse상단 툴바
floatingToolbarbooleantruefalse 면 플로팅 툴바 숨김
onImageUpload(file: File) => Promise<string>이미지 업로드 훅
onDrawingSave(input: { png: Blob; data; previousSrc: string | null }) => Promise<string>그림판 저장 훅 — 그림판 연동
onDrawingLoad(src: string) => Promise<unknown>그림판 불러오기 훅

lang·messages·mode·empty-line-hint 는 래퍼 prop 이 아니다. 언어는 조상 lang/<html lang> 이 정하고, 그 외는 ref 의 element 로 직접 다룬다(element.messages = { … }, element.mode = "source").

Emits

이벤트Payload설명
update:modelValuestring (markdown)v-model 연동
change{ markdown, html }내용 변경
focus포커스
blur블러

Ref 로 직접 접근

vue
<script setup>
import { ref } from "vue";
const editorRef = ref(null);

function save() {
  console.log(editorRef.value?.markdown, editorRef.value?.html);
}
function toSource() {
  const el = editorRef.value?.element;        // 래퍼에 없는 것은 element 로
  if (el) el.mode = "source";
}
</script>

<template>
  <NewtilEditor ref="editorRef" toolbar />
  <button @click="save">저장</button>
</template>
필드타입설명
markdownstring현재 마크다운
htmlstring현재 HTML
elementHTMLElement | null<newtil-editor> DOM

이미지 · 그림판 훅

vue
<script setup>
async function uploadImage(file) {
  const form = new FormData(); form.append("file", file);
  const res = await fetch("/api/upload", { method: "POST", body: form });
  return (await res.json()).url;
}
async function saveDrawing({ png, data, previousSrc }) { /* PNG + JSON 저장 */ return "/upload/drawing-1.png"; }
async function loadDrawing(src) { /* JSON 곁파일 */ return null; }
</script>

<template>
  <NewtilEditor v-model="content" :on-image-upload="uploadImage"
    :on-drawing-save="saveDrawing" :on-drawing-load="loadDrawing" />
</template>