Replace Quill editor with TinyMCE

This commit is contained in:
Heiko Salmon 2021-09-19 14:47:07 +02:00 committed by Kailash Nadh
parent a97d81a8dc
commit c09d2fcd5d
3 changed files with 51 additions and 198 deletions

View file

@ -9,6 +9,7 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@tinymce/tinymce-vue": "^3",
"axios": "^0.21.1",
"buefy": "^0.9.10",
"c3": "^0.7.20",
@ -17,13 +18,11 @@
"dayjs": "^1.10.4",
"humps": "^2.0.1",
"qs": "^6.10.1",
"quill": "^1.3.7",
"quill-delta": "^4.2.2",
"textversionjs": "^1.1.3",
"tinymce": "^5.9.2",
"turndown": "^7.0.0",
"vue": "^2.6.12",
"vue-i18n": "^8.22.2",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.2.0",
"vuex": "^3.6.2"
},

View file

@ -31,16 +31,27 @@
</div>
<!-- wsywig //-->
<quill-editor
:class="{'fullscreen': isEditorFullscreen}"
v-if="form.format === 'richtext'"
<tiny-mce
v-model="form.body"
ref="quill"
:options="options"
v-if="form.format === 'richtext'"
:disabled="disabled"
:placeholder="$t('campaigns.contentHelp')"
@change="onEditorChange($event)"
@ready="onEditorReady($event)"
:init="{
height: 500,
menubar: false,
plugins: [
'lists', 'link', 'image', 'charmap', 'anchor',
'fullscreen', 'table', 'code', 'wordcount', 'hr',
],
toolbar: 'undo redo | formatselect fontsizeselect | bold italic backcolor | ' +
'alignleft aligncenter alignright alignjustify | ' +
'bullist numlist table | outdent indent | removeformat | link hr',
skin: false,
content_css: false,
content_style: 'body { font-family: \'Helvetica Neue\', \'Segoe UI\', Helvetica, sans-serif; font-size: 15px; line-height: 26px; color: #444; }' +
'img { max-width: 100%; }'+
'a { color: #0055d4; }'+
'a:hover { color: #111; }'
}"
/>
<!-- raw html editor //-->
@ -73,54 +84,35 @@
</template>
<script>
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.core.css';
import { quillEditor, Quill } from 'vue-quill-editor';
import CodeFlask from 'codeflask';
import TurndownService from 'turndown';
import { colors } from '../constants';
import 'tinymce';
import 'tinymce/icons/default';
import 'tinymce/themes/silver';
import 'tinymce/skins/ui/oxide/skin.css';
import 'tinymce/plugins/code';
import 'tinymce/plugins/link';
import 'tinymce/plugins/lists';
import 'tinymce/plugins/table';
import 'tinymce/plugins/hr';
import 'tinymce/plugins/wordcount';
import 'tinymce/plugins/charmap';
import 'tinymce/plugins/image';
import 'tinymce/plugins/anchor';
import 'tinymce/plugins/fullscreen';
import TinyMce from '@tinymce/tinymce-vue';
import CampaignPreview from './CampaignPreview.vue';
import Media from '../views/Media.vue';
// Setup Quill to use inline CSS style attributes instead of classes.
Quill.register(Quill.import('attributors/attribute/direction'), true);
Quill.register(Quill.import('attributors/style/align'), true);
Quill.register(Quill.import('attributors/style/background'), true);
Quill.register(Quill.import('attributors/style/color'), true);
Quill.register(Quill.import('formats/indent'), true);
const quillFontSizes = Quill.import('attributors/style/size');
quillFontSizes.whitelist = ['11px', '13px', '22px', '32px'];
Quill.register(quillFontSizes, true);
// Sanitize {{ TrackLink "xxx" }} quotes to backticks.
const regLink = new RegExp(/{{(\s+)?TrackLink(\s+)?"(.+?)"(\s+)?}}/);
const Link = Quill.import('formats/link');
Link.sanitize = (l) => l.replace(regLink, '{{ TrackLink `$3`}}');
const turndown = new TurndownService();
// Custom class to override the default indent behaviour to get inline CSS
// style instead of classes.
class IndentAttributor extends Quill.import('parchment').Attributor.Style {
multiplier = 30;
add(node, value) {
return super.add(node, `${value * this.multiplier}px`);
}
value(node) {
return parseFloat(super.value(node)) / this.multiplier || undefined;
}
}
export default {
components: {
Media,
CampaignPreview,
quillEditor,
TinyMce,
},
props: {
@ -153,49 +145,6 @@ export default {
// where the caret may be lost.
lastSel: null,
// Quill editor options.
options: {
placeholder: this.$t('campaigns.contentHelp'),
modules: {
keyboard: {
bindings: {
esc: {
key: 27,
handler: () => {
this.onToggleFullscreen(true);
},
},
},
},
toolbar: {
container: [
[{ header: [1, 2, 3, false] }],
['bold', 'italic', 'underline', 'strike', 'blockquote', 'code'],
[{ color: [] }, { background: [] }, { size: quillFontSizes.whitelist }],
[
{ list: 'ordered' },
{ list: 'bullet' },
{ indent: '-1' },
{ indent: '+1' },
],
[
{ align: '' },
{ align: 'center' },
{ align: 'right' },
{ align: 'justify' },
],
['link', 'image'],
['clean', 'fullscreen'],
],
handlers: {
image: this.onToggleMedia,
fullscreen: () => this.onToggleFullscreen(false),
},
},
},
},
// HTML editor.
flask: null,
};
@ -216,15 +165,6 @@ export default {
);
},
onEditorReady() {
this.isReady = true;
// Hack to focus the editor on page load.
this.$nextTick(() => {
window.setTimeout(() => this.$refs.quill.quill.focus(), 100);
});
},
onEditorChange() {
if (!this.isReady) {
return;
@ -243,9 +183,6 @@ export default {
<style>
.codeflask .codeflask__flatten { font-size: 15px; }
.codeflask .codeflask__lines { background: #fafafa; z-index: 10; }
.codeflask .token.tag { font-weight: bold; }
.codeflask .token.attr-name { color: #111; }
.codeflask .token.attr-value { color: ${colors.primary} !important; }
</style>
<div id="area"></area>
`;
@ -274,22 +211,9 @@ export default {
this.isPreviewing = !this.isPreviewing;
},
onToggleMedia() {
this.lastSel = this.$refs.quill.quill.getSelection();
this.isMediaVisible = !this.isMediaVisible;
},
onToggleFullscreen(onlyMinimize) {
if (onlyMinimize) {
if (!this.isEditorFullscreen) {
return;
}
}
this.isEditorFullscreen = !this.isEditorFullscreen;
},
onMediaSelect(m) {
this.$refs.quill.quill.insertEmbed(this.lastSel.index || 0, 'image', m.url);
// TODO: Embed image to TinyMce
console.log('onMediaSelect', m);
},
beautifyHTML(str) {
@ -400,17 +324,5 @@ export default {
this.onEditorChange();
},
},
mounted() {
// Initialize the Quill indentation plugin.
const levels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const multiplier = 30;
const indentStyle = new IndentAttributor('indent', 'margin-left', {
scope: Quill.import('parchment').Scope.BLOCK,
whitelist: levels.map((value) => `${value * multiplier}px`),
});
Quill.register(indentStyle);
},
};
</script>

80
frontend/yarn.lock vendored
View file

@ -1265,6 +1265,11 @@
resolved "https://registry.yarnpkg.com/@soda/get-current-script/-/get-current-script-1.0.1.tgz#f4afffcb36e069a801d5339c90499601c47a2516"
integrity sha512-zeOomWIE52M9JpYXlsR3iOf7TXTTmNQHnSbqjMsQZ5phzfAenHzL/1+vQ0ZoJfagocK11LNf8vnn2JG0ufRMUQ==
"@tinymce/tinymce-vue@^3":
version "3.2.8"
resolved "https://registry.yarnpkg.com/@tinymce/tinymce-vue/-/tinymce-vue-3.2.8.tgz#014571b52ec8fa83665a7fa887bf65140207de71"
integrity sha512-jEz+NZ0g+FZFz273OEUWz9QkwPMyjc5AJYyxOgu51O1Y5UaJ/6IUddXTX6A20mwCleEv5ebwNYdalviafx4fnA==
"@types/body-parser@*":
version "1.19.0"
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
@ -3012,11 +3017,6 @@ clone@^1.0.2:
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
clone@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
coa@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3"
@ -4629,11 +4629,6 @@ eventemitter2@^6.4.2:
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.4.tgz#aa96e8275c4dbeb017a5d0e03780c65612a1202b"
integrity sha512-HLU3NDY6wARrLCEwyGKRBvuWYyvW6mHYv72SJJAH3iJN3a6eVUvkjFkcxah1bcTgGVBBrFdIopBJPhCQFMLyXw==
eventemitter3@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-2.0.3.tgz#b5e1079b59fb5e1ba2771c0a993be060a58c99ba"
integrity sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=
eventemitter3@^4.0.0:
version "4.0.4"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384"
@ -4792,7 +4787,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
assign-symbols "^1.0.0"
is-extendable "^1.0.1"
extend@^3.0.2, extend@~3.0.2:
extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
@ -4850,16 +4845,6 @@ fast-deep-equal@^3.1.3:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-diff@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==
fast-diff@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
fast-glob@^2.2.6:
version "2.2.7"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d"
@ -6597,11 +6582,6 @@ lodash.defaultsdeep@^4.6.1:
resolved "https://registry.yarnpkg.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz#512e9bd721d272d94e3d3a63653fa17516741ca6"
integrity sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash.kebabcase@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"
@ -7511,11 +7491,6 @@ param-case@2.1.x:
dependencies:
no-case "^2.2.0"
parchment@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/parchment/-/parchment-1.1.4.tgz#aeded7ab938fe921d4c34bc339ce1168bc2ffde5"
integrity sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==
parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
@ -8266,36 +8241,6 @@ querystringify@^2.1.1:
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
quill-delta@^3.6.2:
version "3.6.3"
resolved "https://registry.yarnpkg.com/quill-delta/-/quill-delta-3.6.3.tgz#b19fd2b89412301c60e1ff213d8d860eac0f1032"
integrity sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==
dependencies:
deep-equal "^1.0.1"
extend "^3.0.2"
fast-diff "1.1.2"
quill-delta@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/quill-delta/-/quill-delta-4.2.2.tgz#015397d046e0a3bed087cd8a51f98c11a1b8f351"
integrity sha512-qjbn82b/yJzOjstBgkhtBjN2TNK+ZHP/BgUQO+j6bRhWQQdmj2lH6hXG7+nwwLF41Xgn//7/83lxs9n2BkTtTg==
dependencies:
fast-diff "1.2.0"
lodash.clonedeep "^4.5.0"
lodash.isequal "^4.5.0"
quill@^1.3.4, quill@^1.3.7:
version "1.3.7"
resolved "https://registry.yarnpkg.com/quill/-/quill-1.3.7.tgz#da5b2f3a2c470e932340cdbf3668c9f21f9286e8"
integrity sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==
dependencies:
clone "^2.1.1"
deep-equal "^1.0.1"
eventemitter3 "^2.0.3"
extend "^3.0.2"
parchment "^1.1.4"
quill-delta "^3.6.2"
ramda@~0.27.1:
version "0.27.1"
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9"
@ -9579,6 +9524,11 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tinymce@^5.9.2:
version "5.9.2"
resolved "https://registry.yarnpkg.com/tinymce/-/tinymce-5.9.2.tgz#c56a1d7800ac23026fbe6e0fcf444c0f157ccafe"
integrity sha512-/dHTsbxo0YwLvB5krRqiw/qHEm04/k6l0dvAQ3hO5oNw4e9QalKcUQCdr+g/b/FWcsUMP6scvKmm8MX50/j3Cg==
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@ -10033,14 +9983,6 @@ vue-loader@^15.9.2:
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"
vue-quill-editor@^3.0.6:
version "3.0.6"
resolved "https://registry.yarnpkg.com/vue-quill-editor/-/vue-quill-editor-3.0.6.tgz#1f85646211d68a31a80a72cb7f45bb2f119bc8fb"
integrity sha512-g20oSZNWg8Hbu41Kinjd55e235qVWPLfg4NvsLW6d+DhgBTFbEuMpcWlUdrD6qT3+Noim6DRu18VLM9lVShXOQ==
dependencies:
object-assign "^4.1.1"
quill "^1.3.4"
vue-router@^3.2.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.3.2.tgz#0099de402edb2fe92f9711053ab5a2156f239cad"