From 809fca73a014449bc8aa7fe5fa00098242414345 Mon Sep 17 00:00:00 2001
From: the-djmaze <>
Date: Mon, 5 Feb 2024 14:10:58 +0100
Subject: [PATCH] Extract WYSIWYG code from Html.js into HtmlEditor.js
---
dev/Common/Html.js | 163 +----------------------------------
dev/Common/HtmlEditor.js | 163 +++++++++++++++++++++++++++++++++++
dev/External/User/ko.js | 2 +-
dev/Settings/User/General.js | 2 +-
dev/View/Popup/Compose.js | 3 +-
5 files changed, 168 insertions(+), 165 deletions(-)
create mode 100644 dev/Common/HtmlEditor.js
diff --git a/dev/Common/Html.js b/dev/Common/Html.js
index b2d929afa..08dc2b559 100644
--- a/dev/Common/Html.js
+++ b/dev/Common/Html.js
@@ -721,168 +721,7 @@ export const
.replace(/\n/g, '
');
blockquoteSwitcher();
return tmpl.innerHTML.trim();
- },
-
- WYSIWYGS = ko.observableArray();
-
-WYSIWYGS.push({
- name: 'Squire',
- construct: (owner, container, onReady) => onReady(new SquireUI(container))
-});
-
-rl.registerWYSIWYG = (name, construct) => WYSIWYGS.push({name, construct});
-
-export class HtmlEditor {
- /**
- * @param {Object} element
- * @param {Function=} onBlur
- * @param {Function=} onReady
- * @param {Function=} onModeChange
- */
- constructor(element, onReady = null, onModeChange = null, onBlur = null) {
- this.blurTimer = 0;
-
- this.onBlur = onBlur;
- this.onModeChange = onModeChange;
-
- if (element) {
- onReady = onReady ? [onReady] : [];
- this.onReady = fn => onReady.push(fn);
- // TODO: make 'which' user configurable
- const which = SettingsUserStore.editorWysiwyg(),
- wysiwyg = WYSIWYGS.find(item => which == item.name) || WYSIWYGS.find(item => 'Squire' == item.name);
-// const wysiwyg = WYSIWYGS.find(item => 'Squire' == item.name);
- wysiwyg.construct(this, element, editor => setTimeout(()=>{
- this.editor = editor;
- editor.on('blur', () => this.blurTrigger());
- editor.on('focus', () => clearTimeout(this.blurTimer));
- editor.on('mode', () => {
- this.blurTrigger();
- this.onModeChange?.(!this.isPlain());
- });
- this.onReady = fn => fn();
- onReady.forEach(fn => fn());
- },1));
- }
- }
-
- blurTrigger() {
- if (this.onBlur) {
- clearTimeout(this.blurTimer);
- this.blurTimer = setTimeout(() => this.onBlur?.(), 200);
- }
- }
-
- /**
- * @returns {boolean}
- */
- isHtml() {
- return this.editor ? !this.isPlain() : false;
- }
-
- /**
- * @returns {boolean}
- */
- isPlain() {
- return this.editor ? 'plain' === this.editor.mode : false;
- }
-
- /**
- * @returns {void}
- */
- clearCachedSignature() {
- this.onReady(() => this.editor.execCommand('insertSignature', {
- clearCache: true
- }));
- }
-
- /**
- * @param {string} signature
- * @param {bool} html
- * @param {bool} insertBefore
- * @returns {void}
- */
- setSignature(signature, html, insertBefore = false) {
- this.onReady(() => this.editor.execCommand('insertSignature', {
- isHtml: html,
- insertBefore: insertBefore,
- signature: signature
- }));
- }
-
- /**
- * @param {boolean=} wrapIsHtml = false
- * @returns {string}
- */
- getData() {
- let result = '';
- if (this.editor) {
- try {
- if (this.isPlain()) {
- result = this.editor.getPlainData();
- } else {
- result = this.editor.getData();
- }
- } catch (e) {} // eslint-disable-line no-empty
- }
- return result;
- }
-
- /**
- * @returns {string}
- */
- getDataWithHtmlMark() {
- return (this.isHtml() ? ':HTML:' : '') + this.getData();
- }
-
- modeWysiwyg() {
- this.onReady(() => this.editor.setMode('wysiwyg'));
- }
- modePlain() {
- this.onReady(() => this.editor.setMode('plain'));
- }
-
- setHtmlOrPlain(text) {
- text.startsWith(':HTML:')
- ? this.setHtml(text.slice(6))
- : this.setPlain(text);
- }
-
- setData(mode, data) {
- this.onReady(() => {
- const editor = this.editor;
- this.clearCachedSignature();
- try {
- editor.setMode(mode);
- if (this.isPlain()) {
- editor.setPlainData(data);
- } else {
- editor.setData(data);
- }
- } catch (e) { console.error(e); }
- });
- }
-
- setHtml(html) {
- this.setData('wysiwyg', html/*.replace(/
]*><\/p>/gi, '')*/); - } - - setPlain(txt) { - this.setData('plain', txt); - } - - focus() { - this.onReady(() => this.editor.focus()); - } - - blur() { - this.onReady(() => this.editor.blur()); - } - - clear() { - this.onReady(() => this.isPlain() ? this.setPlain('') : this.setHtml('')); - } -} + }; rl.Utils = { htmlToPlain: htmlToPlain, diff --git a/dev/Common/HtmlEditor.js b/dev/Common/HtmlEditor.js new file mode 100644 index 000000000..0bbfdbdea --- /dev/null +++ b/dev/Common/HtmlEditor.js @@ -0,0 +1,163 @@ +import { SettingsUserStore } from 'Stores/User/Settings'; + +export const + WYSIWYGS = ko.observableArray(); + +WYSIWYGS.push({ + name: 'Squire', + construct: (owner, container, onReady) => onReady(new SquireUI(container)) +}); + +rl.registerWYSIWYG = (name, construct) => WYSIWYGS.push({name, construct}); + +export class HtmlEditor { + /** + * @param {Object} element + * @param {Function=} onBlur + * @param {Function=} onReady + * @param {Function=} onModeChange + */ + constructor(element, onReady = null, onModeChange = null, onBlur = null) { + this.blurTimer = 0; + + this.onBlur = onBlur; + this.onModeChange = onModeChange; + + if (element) { + onReady = onReady ? [onReady] : []; + this.onReady = fn => onReady.push(fn); + // TODO: make 'which' user configurable + const which = SettingsUserStore.editorWysiwyg(), + wysiwyg = WYSIWYGS.find(item => which == item.name) || WYSIWYGS.find(item => 'Squire' == item.name); +// const wysiwyg = WYSIWYGS.find(item => 'Squire' == item.name); + wysiwyg.construct(this, element, editor => setTimeout(()=>{ + this.editor = editor; + editor.on('blur', () => this.blurTrigger()); + editor.on('focus', () => clearTimeout(this.blurTimer)); + editor.on('mode', () => { + this.blurTrigger(); + this.onModeChange?.(!this.isPlain()); + }); + this.onReady = fn => fn(); + onReady.forEach(fn => fn()); + },1)); + } + } + + blurTrigger() { + if (this.onBlur) { + clearTimeout(this.blurTimer); + this.blurTimer = setTimeout(() => this.onBlur?.(), 200); + } + } + + /** + * @returns {boolean} + */ + isHtml() { + return this.editor ? !this.isPlain() : false; + } + + /** + * @returns {boolean} + */ + isPlain() { + return this.editor ? 'plain' === this.editor.mode : false; + } + + /** + * @returns {void} + */ + clearCachedSignature() { + this.onReady(() => this.editor.execCommand('insertSignature', { + clearCache: true + })); + } + + /** + * @param {string} signature + * @param {bool} html + * @param {bool} insertBefore + * @returns {void} + */ + setSignature(signature, html, insertBefore = false) { + this.onReady(() => this.editor.execCommand('insertSignature', { + isHtml: html, + insertBefore: insertBefore, + signature: signature + })); + } + + /** + * @param {boolean=} wrapIsHtml = false + * @returns {string} + */ + getData() { + let result = ''; + if (this.editor) { + try { + if (this.isPlain()) { + result = this.editor.getPlainData(); + } else { + result = this.editor.getData(); + } + } catch (e) {} // eslint-disable-line no-empty + } + return result; + } + + /** + * @returns {string} + */ + getDataWithHtmlMark() { + return (this.isHtml() ? ':HTML:' : '') + this.getData(); + } + + modeWysiwyg() { + this.onReady(() => this.editor.setMode('wysiwyg')); + } + modePlain() { + this.onReady(() => this.editor.setMode('plain')); + } + + setHtmlOrPlain(text) { + text.startsWith(':HTML:') + ? this.setHtml(text.slice(6)) + : this.setPlain(text); + } + + setData(mode, data) { + this.onReady(() => { + const editor = this.editor; + this.clearCachedSignature(); + try { + editor.setMode(mode); + if (this.isPlain()) { + editor.setPlainData(data); + } else { + editor.setData(data); + } + } catch (e) { console.error(e); } + }); + } + + setHtml(html) { + this.setData('wysiwyg', html/*.replace(/
]*><\/p>/gi, '')*/); + } + + setPlain(txt) { + this.setData('plain', txt); + } + + focus() { + this.onReady(() => this.editor.focus()); + } + + blur() { + this.onReady(() => this.editor.blur()); + } + + clear() { + this.onReady(() => this.isPlain() ? this.setPlain('') : this.setHtml('')); + } +} diff --git a/dev/External/User/ko.js b/dev/External/User/ko.js index 7affba8d5..78dc965eb 100644 --- a/dev/External/User/ko.js +++ b/dev/External/User/ko.js @@ -1,7 +1,7 @@ import 'External/ko'; import ko from 'ko'; import { RFC822 } from 'Common/File'; -import { HtmlEditor } from 'Common/Html'; +import { HtmlEditor } from 'Common/HtmlEditor'; import { timeToNode } from 'Common/Translator'; import { doc, elementById, addEventsListeners, dropdowns, leftPanelDisabled } from 'Common/Globals'; import { EmailAddressesComponent } from 'Component/EmailAddresses'; diff --git a/dev/Settings/User/General.js b/dev/Settings/User/General.js index 3c2584c5b..cb1cdc73b 100644 --- a/dev/Settings/User/General.js +++ b/dev/Settings/User/General.js @@ -5,7 +5,7 @@ import { SaveSettingStatus } from 'Common/Enums'; import { LayoutSideView, LayoutBottomView } from 'Common/EnumsUser'; import { setRefreshFoldersInterval } from 'Common/Folders'; import { Settings, SettingsGet } from 'Common/Globals'; -import { WYSIWYGS } from 'Common/Html'; +import { WYSIWYGS } from 'Common/HtmlEditor'; import { isArray } from 'Common/Utils'; import { addSubscribablesTo, addComputablesTo } from 'External/ko'; import { i18n, translateTrigger, translatorReload, convertLangName } from 'Common/Translator'; diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 336e33f94..35a33fc1f 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -11,7 +11,8 @@ import { } from 'Common/EnumsUser'; import { pInt, isArray, arrayLength, b64Encode } from 'Common/Utils'; -import { encodeHtml, HtmlEditor, htmlToPlain } from 'Common/Html'; +import { encodeHtml, htmlToPlain } from 'Common/Html'; +import { HtmlEditor } from 'Common/HtmlEditor'; import { koArrayWithDestroy, addObservablesTo, addComputablesTo, addSubscribablesTo } from 'External/ko'; import { UNUSED_OPTION_VALUE } from 'Common/Consts';