[Vue.js] tiptap Editor μ°λ
π tiptap Editor
μ΄ μλν°λ‘ μμ±λλ λ΄μ©μ Formμ textareaμ μ¨μ§λ κ²μ΄ μλκ³ divμ HTMLλ‘ μ¨μ§κ³ 미리 μ μλμ΄ μλ CSS Styleλ‘ ννλ₯Ό λ°λ‘λ°λ‘ 보μ¬μ£Όλ μμΈκ² κ°μ 보μ΄λ κ²μ΄μμ. λ λ리μ€λΌλκ² μ΄λ° λ°©μμ λ§νλκ²μ΄ μλκ° μκ°μ΄ λλ κ²μ΄μμ.
Tiptapμμλ κΈ°λ³Έμ μΌλ‘ CSSμ€νμΌμ΄ μ μ λμ΄ μμ§ μλ€κ³ ν©λλ€. λ³ΈμΈμ λ§κ² μ€μ μ ν΄μΌ νλ κ²μ΄μμ.
λ€λ§ μνλ‘ μ 곡νκ³ μλ cssλ₯Ό κ°μ Έλ€ μ¬μ©ν μλ μμ κ² κ°μ κ²μ΄μμ.
π½ μ€μΉ
β npm μ΄μ© μ€μΉ
npm install @tiptap/vue-3 @tiptap/starter-kit
β yarn μ΄μ© μ€μΉ
yarn add @tiptap/vue-3 @tiptap/starter-kit
β junyharang_dev_commnunity_client git:(master) β npm uninstall @tiptap/vue-3
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: junyharang_dev_commnunity_client@0.1.0
npm ERR! Found: vue@3.2.31
npm ERR! node_modules/vue
npm ERR! vue@"^3.2.13" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer vue@"^2.5.17" from tiptap@1.32.2
npm ERR! node_modules/tiptap
npm ERR! tiptap@"^1.32.2" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See /Users/juny/.npm/eresolve-report.txt for a full report.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/juny/.npm/_logs/2022-03-22T21_59_03_868Z-debug-0.log
β junyharang_dev_commnunity_client git:(master) β npm uninstall @tiptap/vue-3 --force
npm WARN using --force Recommended protections disabled.
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: tiptap@1.32.2
npm WARN Found: vue@3.2.31
npm WARN node_modules/vue
npm WARN peerOptional vue@"^2 || ^3.2.13" from @vue/babel-preset-app@5.0.1
npm WARN node_modules/@vue/babel-preset-app
npm WARN @vue/babel-preset-app@"^5.0.1" from @vue/cli-plugin-babel@5.0.1
npm WARN node_modules/@vue/cli-plugin-babel
npm WARN 5 more (@vue/server-renderer, vue-cookie-next, vue-router, vuex, the root project)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer vue@"^2.5.17" from tiptap@1.32.2
npm WARN node_modules/tiptap
npm WARN tiptap@"^1.32.2" from the root project
npm WARN 1 more (tiptap-extensions)
npm WARN
npm WARN Conflicting peer dependency: vue@2.6.14
npm WARN node_modules/vue
npm WARN peer vue@"^2.5.17" from tiptap@1.32.2
npm WARN node_modules/tiptap
npm WARN tiptap@"^1.32.2" from the root project
npm WARN 1 more (tiptap-extensions)
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: tiptap-extensions@1.35.2
npm WARN Found: vue@3.2.31
npm WARN node_modules/vue
npm WARN peerOptional vue@"^2 || ^3.2.13" from @vue/babel-preset-app@5.0.1
npm WARN node_modules/@vue/babel-preset-app
npm WARN @vue/babel-preset-app@"^5.0.1" from @vue/cli-plugin-babel@5.0.1
npm WARN node_modules/@vue/cli-plugin-babel
npm WARN 5 more (@vue/server-renderer, vue-cookie-next, vue-router, vuex, the root project)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer vue@"^2.5.17" from tiptap-extensions@1.35.2
npm WARN node_modules/tiptap-extensions
npm WARN tiptap-extensions@"^1.35.2" from the root project
npm WARN
npm WARN Conflicting peer dependency: vue@2.6.14
npm WARN node_modules/vue
npm WARN peer vue@"^2.5.17" from tiptap-extensions@1.35.2
npm WARN node_modules/tiptap-extensions
npm WARN tiptap-extensions@"^1.35.2" from the root project
added 113 packages, removed 54 packages, changed 23 packages, and audited 988 packages in 7s
104 packages are looking for funding
run `npm fund` for details
9 vulnerabilities (8 moderate, 1 high)
To address issues that do not require attention, run:
npm audit fix
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
β junyharang_dev_commnunity_client git:(master) β npm install @tiptap/vue-3 @tiptap/starter-kit
added 36 packages, and audited 1024 packages in 17s
128 packages are looking for funding
run `npm fund` for details
9 vulnerabilities (8 moderate, 1 high)
To address issues that do not require attention, run:
npm audit fix
To address all issues (including breaking changes), run:
npm audit fix --force
β junyharang_dev_commnunity_client git:(master) β
μ£Όλνλμ npmμ μ΄μ©ν΄μ μ€μΉλ₯Ό ν΄ μ€ κ²μ΄μμ.
π½ μ¬μ© λ°©λ²
<template>
<editor-content :editor="editor" />
</template>
<script>
import { Editor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
export default {
components: {
EditorContent,
},
data() {
return {
editor: null,
}
},
mounted() {
this.editor = new Editor({
content: '<p>I’m running Tiptap with Vue.js. π</p>',
extensions: [
StarterKit,
],
})
},
beforeUnmount() {
this.editor.destroy()
},
}
</script>
κΈ°λ³Έμ μΈ Codeλ μμ κ°μ΄ μ΄μ©ν μ μλλ°, component/Tiptap.vueμ κ°μ Componentλ₯Ό λ§λ€μ΄μ μμ μμ μ½λλ₯Ό μ λ ₯ν΄μ μ¬μ©ν μ μλ κ²μ΄μμ.
λ λ€λ₯Έ λ°©λ²μ Compositon APIλ₯Ό μ΄μ©νμ¬ `useEditor`λ₯Ό μ΄μ©ν μ μλ κ²μ΄μμ.
<template>
<editor-content :editor="editor" />
</template>
<script>
import { useEditor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
export default {
components: {
EditorContent,
},
setup() {
const editor = useEditor({
content: '<p>I’m running Tiptap with Vue.js. π</p>',
extensions: [
StarterKit,
],
})
return { editor }
},
}
</script>
μ£Όλνλμ μλμ κ°μ΄ μ΄μ©ν κ²μ΄μμ. μ΄μ λ§μΆμ΄μ λ΄μ©μ μμ±ν΄ λ³Ό κ²μ΄μμ.
<template>
<div class="editor" v-if="editor">
<menu-bar class="editor__header" :editor="editor" />
<!-- μμμ ν -->
<input
type="color"
@input="
editor
.chain()
.focus()
.setColor($event.target.value)
.run()
"
:value="editor.getAttributes('textStyle').color"
/>
<!-- ν°νΈ ν¬κΈ° -->
<floating-menu
class="floating-menu"
:tippy-options="{ duration: 100 }"
:editor="editor"
v-if="editor"
>
<button
@click="
editor
.chain()
.focus()
.toggleHeading({ level: 1 })
.run()
"
:class="{ 'is-active': editor.isActive('heading', { level: 1 }) }"
>
H1
</button>
<button
@click="
editor
.chain()
.focus()
.toggleHeading({ level: 2 })
.run()
"
:class="{ 'is-active': editor.isActive('heading', { level: 2 }) }"
>
H2
</button>
<button
@click="
editor
.chain()
.focus()
.toggleBulletList()
.run()
"
:class="{ 'is-active': editor.isActive('bulletList') }"
>
Bullet List
</button>
</floating-menu>
<!-- ν°νΈ μ ν -->
<editor-content class="editor__content" :editor="editor" />
</div>
</template>
<script>
import { Editor, EditorContent, FloatingMenu } from "@tiptap/vue-3";
import StarterKit from "@tiptap/starter-kit";
import TaskList from "@tiptap/extension-task-list";
import TaskItem from "@tiptap/extension-task-item";
import Highlight from "@tiptap/extension-highlight";
import CharacterCount from "@tiptap/extension-character-count";
import TextStyle from "@tiptap/extension-text-style";
import MenuBar from "@/components/tiptap/MenuBar.vue";
import { Color } from "@tiptap/extension-color";
export default {
components: {
EditorContent,
FloatingMenu,
MenuBar
},
data() {
return {
editor: null
};
},
mounted() {
this.editor = new Editor({
extensions: [
StarterKit,
Highlight,
TaskList,
TaskItem,
CharacterCount.configure({
limit: 10000
}),
TextStyle,
Color
],
content: `
<h2>
Hi there,
</h2>
<p>
this is a <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
</p>
<p>
Isn’t that great? And all of that is editable. But wait, there’s more. Let’s try a code block:
</p>
<p>
I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too.
</p>
<blockquote>
Wow, that’s amazing. Good work, boy! π
<br />
— Mom
</blockquote>
`
});
},
methods: {
beforeUnmount() {
this.editor.destroy();
}
}
};
</script>
μμ§ Extention Moduleμ μ€μΉνμ§ μμκΈ° λλ¬Έμ Errorκ° μκ² λ©λλ€.
π νμ₯ Module μ€μΉνκΈ°
Prosemirror Editorμ κ°μ μ΄μ tiptapμ κ°μ μ νμν κΈ°λ₯λ§ λΆλ¬μ μ΄μ©ν μ μλ€λ κ²μ΄μμ.
νμ₯ κΈ°λ₯μ μ΄μ©νκΈ° μν΄μλ νμ₯ Moduleμ μΆκ°λ‘ μ€μΉν΄μΌ νλ κ²μ΄μμ.
π½ μ€μΉ
β npm μ΄μ© μ€μΉ
npm install tiptap-extensions --save
β yarn μ΄μ© μ€μΉ
μ΄λ²μλ μ£Όλνλμ yarnμ μ΄μ©ν΄μ μ€μΉ ν΄ λ³Ό κ²μ΄μμ.
π½ μ¬μ© λ°©λ²
μ΅μ΄ μ€μΉν tiptapμ μΆκ°λ‘ extensionsλ₯Ό μ μ©νλ©΄ λλ κ²μ΄μμ.
import { Editor, EditorContent } from 'tiptap'
import { Heading } from 'tiptap-extensions'
const editor = new Editor({
extensions: [ new Heading(), ],
})
`extensions: [ new Heading() ]`μ²λΌ νμν κΈ°λ₯μ κ°μ²΄(μΈμ€ν΄μ€)λ₯Ό μΆκ°ν΄μ λΆλ¬μμ μ΄μ©νλ©΄ λλ κ²μ΄μμ.
λν κ° κΈ°λ₯μ μΈμ€ν΄μ€λ μμ λ§μ μ€μ μ μΆκ° / λ³κ²½ν μ μλ κ²μ΄μμ. κ·Έλμ λΆλ¬ μ¬ κΈ°λ₯μ μ€μ κ°λ μ μ΄ν΄λ΄μΌ Errorλ₯Ό μ΅μν ν μ μλ κ²μ΄μμ. `Heaing()`μ κ²½μ° μλμ κ°μ΄ `level` Option`λ μλ κ²μ΄μμ.
const editor = new Editor({
new Heading({
leve: [1, 2, 3],
}),
})
`tiptap-extensions`μλ λ€μν κΈ°λ₯λ€μ΄ μ€λΉ λμ΄ μλ κ²μ΄μμ.
import { Editor, EditorContent } from 'tiptap'
import { Bold, Italic, Link, HardBreak, Heading } from 'tiptap-extensions'
const editor = new Editor({
extensions: [
new Bold(),
new Italic(),
new Link(),
new HardBread(),
new Haading()
],
})
π½ νλ©΄
π¦ DevInquryReplyVO.java
μλ νμΈμ.
μ£Όλνλμ΄ μμ±ν λ΄μ©μ΄ λμμ΄ λμ
¨μΌλ©΄ μ’κ² μ΅λλ€!
νΉμλΌλ μ λͺ»λ μ λ³΄κ° μλ€λ©΄ λκΈμ μμ€ν νΌλλ°± λΆν λλ¦¬κ² μ΅λλ€!
'μ£Όλνλ'μ Blog κΈμ λ°λ‘ 보κ΄νμμ§ λ§μκ³ , 'μ£Όλνλ' Blogμμ μ¬λ¬λΆμ νμ κΈ°λ€λ¦¬κ³ μμΌλ μ΄ κ³³μμ μ΄μ© ν΄ μ£Όμλ©΄ κ³ λ§κ² μ΅λλ€.
μΌλΆ μ 보λ₯Ό νΌκ°μ μ μ 리λ₯Ό νκ³ μ νμ€ λλ λ°λμ μλμ κ°μ΄ μΆμ²λ₯Ό λ¨κ²¨ μ£ΌμκΈ° λ°λΌκ² μ΅λλ€.
μΆμ² : μ£Όλνλ κ°λ° Blog - '[Blog URL]'
β 2022. 'μ£Όλνλ' all rights reserved.
junyharang8592@gmail.com