Created
March 3, 2021 10:12
-
-
Save Aymkdn/9f993c5cfe8476f718c4fd2fd7bda1f0 to your computer and use it in GitHub Desktop.
TipTap TextColor extension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this is a simplified example using Vuetify v1 and TipTap v1 | |
<template> | |
<div> | |
<editor-menu-bar :editor="editor" v-else> | |
<div class="menubar" slot-scope="{ commands, isActive }"> | |
<v-tooltip top> | |
<button :class="{ 'menubar__button':true, 'is-active': isActive.bold() }" @click="commands.bold" slot="activator"> | |
<v-icon>format_bold</v-icon> | |
</button> | |
<span>Bold</span> | |
</v-tooltip> | |
<v-tooltip top> | |
<button :class="{ 'menubar__button':true, 'is-active': isActive.italic() }" @click="commands.italic" slot="activator"> | |
<v-icon>format_italic</v-icon> | |
</button> | |
<span>Italic</span> | |
</v-tooltip> | |
<v-tooltip top> | |
<v-menu slot="activator"> | |
<button :class="{ 'menubar__button':true }" style="margin-top:-18px" slot="activator"> | |
<v-icon>format_color_text</v-icon> | |
</button> | |
<v-list> | |
<v-list-tile :key="color" v-for="color in colors" @click="applyTextColor(commands, color)"> | |
<v-list-tile-title>{{color}}</v-list-tile-title> | |
</v-list-tile> | |
</v-list> | |
</v-menu> | |
<span>Text Color</span> | |
</v-tooltip> | |
<v-tooltip top> | |
<button :class="{ 'menubar__button':true, 'is-active': isActive.bullet_list() }" @click="commands.bullet_list" slot="activator"> | |
<v-icon>format_list_bulleted</v-icon> | |
</button> | |
<span>Bullet List</span> | |
</v-tooltip> | |
<v-tooltip top> | |
<button :class="{ 'menubar__button':true, 'is-active': isActive.ordered_list() }" @click="commands.ordered_list" slot="activator"> | |
<v-icon>format_list_numbered</v-icon> | |
</button> | |
<span>Ordered List</span> | |
</v-tooltip> | |
<v-tooltip top> | |
<button :class="{ 'menubar__button':true, 'is-active': isActive.link() }" @click="commands.link" slot="activator"> | |
<v-icon>link</v-icon> | |
</button> | |
<span>Link</span> | |
</v-tooltip> | |
<v-tooltip top> | |
<button class="menubar__button" @click="commands.undo" slot="activator"> | |
<v-icon>undo</v-icon> | |
</button> | |
<span>Undo</span> | |
</v-tooltip> | |
<v-tooltip top> | |
<button class="menubar__button" @click="commands.redo" slot="activator"> | |
<v-icon>redo</v-icon> | |
</button> | |
<span>Redo</span> | |
</v-tooltip> | |
</div> | |
</editor-menu-bar> | |
<editor-content :editor="editor" class="height-row-3" /> | |
</div> | |
</template> | |
<script> | |
// Import the editor | |
import { Editor, EditorContent, EditorMenuBar } from 'tiptap' | |
import Vue from 'vue' | |
import { | |
Bold, | |
Italic, | |
OrderedList, | |
BulletList, | |
ListItem, | |
Link, | |
History | |
} from 'tiptap-extensions' | |
import TextColor from './tiptap-textcolor.js' | |
export default { | |
components: { | |
EditorContent, | |
EditorMenuBar | |
}, | |
data() { | |
return { | |
editor: null, | |
} | |
}, | |
computed:{ | |
colors () { | |
return [ | |
'black', | |
'green', | |
'red', | |
'blue', | |
'purple' | |
] | |
} | |
}, | |
methods:{ | |
applyTextColor (commands, color) { | |
commands.textcolor({ color: color }); | |
} | |
}, | |
mounted() { | |
this.editor = new Editor({ | |
content: "", | |
disablePasteRules:true, | |
disableInputRules:true, | |
extensions:[ | |
new Bold(), | |
new Italic(), | |
new TextColor(), | |
new OrderedList(), | |
new BulletList(), | |
new ListItem(), | |
new Link(), | |
new History() | |
] | |
}) | |
}, | |
beforeDestroy() { | |
this.editor.destroy() | |
} | |
} | |
</script> | |
<style> | |
.menubar { | |
-webkit-transition:visibility .2s .4s,opacity .2s .4s; | |
transition:visibility .2s .4s,opacity .2s .4s; | |
width: 90%; | |
border: 1px solid #CCC; | |
background-color: #EEE; | |
padding: 3px 0 0 5px; | |
} | |
.menubar.is-hidden { | |
visibility:hidden; | |
opacity:0 | |
} | |
.menubar.is-focused { | |
visibility:visible; | |
opacity:1; | |
-webkit-transition:visibility .2s,opacity .2s; | |
transition:visibility .2s,opacity .2s | |
} | |
.menubar__button { | |
font-weight:700; | |
display:-webkit-inline-box; | |
display:-ms-inline-flexbox; | |
display:inline-flex; | |
background:rgba(0,0,0,0); | |
border:0; | |
color:#000; | |
padding:.2rem .5rem; | |
margin-right:.2rem; | |
border-radius:3px; | |
cursor:pointer | |
} | |
.menubar__button:hover { | |
background-color:rgba(0,0,0,.05) | |
} | |
.menubar__button.is-active { | |
background-color:rgba(0,0,0,.1) | |
} | |
/* make the area resizable */ | |
.ProseMirror { | |
resize:vertical; | |
} | |
/* different height depending of the number of rows defined */ | |
.height-row-1 > div[contenteditable] { height:35px } | |
.height-row-2 > div[contenteditable] { height:70px } | |
.height-row-3 > div[contenteditable] { height:105px } | |
.height-row-4 > div[contenteditable] { height:140px } | |
.height-row-5 > div[contenteditable] { height:175px } | |
.height-row-6 > div[contenteditable] { height:210px } | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Mark } from 'tiptap' | |
import { updateMark, markInputRule, markPasteRule } from 'tiptap-commands' | |
export default class TextColor extends Mark { | |
get name() { | |
return 'textcolor' | |
} | |
get schema() { | |
return { | |
attrs: { | |
color: { | |
default: 'black' | |
} | |
}, | |
parseDOM: [ | |
{ | |
tag: 'span', | |
getAttrs: dom => { | |
return { | |
color: dom.style.color | |
} | |
} | |
} | |
], | |
toDOM: (node) => { | |
return ['span', { | |
style: `color:${node.attrs.color}` | |
}, 0] | |
} | |
} | |
} | |
keys({ type }) { | |
return { | |
'Mod-c': updateMark(type), | |
} | |
} | |
commands({ type }) { | |
return attrs => updateMark(type, attrs); | |
} | |
inputRules({ type }) { | |
return [ | |
markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, type), | |
] | |
} | |
pasteRules({ type }) { | |
return [ | |
markPasteRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)/g, type), | |
] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment