mirror of
https://github.com/knadh/listmonk.git
synced 2025-01-19 21:05:10 +08:00
Replace Quill editor with TinyMCE
This commit is contained in:
parent
a97d81a8dc
commit
c09d2fcd5d
3 changed files with 51 additions and 198 deletions
5
frontend/package.json
vendored
5
frontend/package.json
vendored
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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
80
frontend/yarn.lock
vendored
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue