mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-12-24 08:04:16 +08:00
Bugfix: CKEditor failed to load
This commit is contained in:
parent
3599c4c745
commit
65032e3b89
5 changed files with 205 additions and 248 deletions
|
@ -1,79 +1,4 @@
|
|||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
const CKEditorDefaultConfig = {
|
||||
'title': false,
|
||||
'stylesSet': false,
|
||||
'customConfig': '',
|
||||
'contentsCss': '',
|
||||
'toolbarGroups': [
|
||||
{ name: 'spec' },
|
||||
{ name: 'styles' },
|
||||
{ name: 'basicstyles', groups: ['basicstyles', 'cleanup', 'bidi'] },
|
||||
{ name: 'colors' },
|
||||
{ name: 'paragraph', groups: ['list', 'indent', 'blocks', 'align'] },
|
||||
{ name: 'links' },
|
||||
{ name: 'insert' },
|
||||
{ name: 'document', groups: ['mode', 'document', 'doctools'] },
|
||||
{ name: 'others' }
|
||||
],
|
||||
|
||||
'removePlugins': 'liststyle',
|
||||
'removeButtons': 'Format,Undo,Redo,Cut,Copy,Paste,Anchor,Strike,Subscript,Superscript,Image,SelectAll,Source',
|
||||
'removeDialogTabs': 'link:advanced;link:target;image:advanced;images:advanced',
|
||||
|
||||
'extraPlugins': 'plain,signature',
|
||||
|
||||
'allowedContent': true,
|
||||
'extraAllowedContent': true,
|
||||
|
||||
'fillEmptyBlocks': false,
|
||||
'ignoreEmptyParagraph': true,
|
||||
'disableNativeSpellChecker': false,
|
||||
|
||||
'colorButton_enableAutomatic': false,
|
||||
'colorButton_enableMore': true,
|
||||
|
||||
'font_defaultLabel': 'Arial',
|
||||
'fontSize_defaultLabel': '13',
|
||||
'fontSize_sizes': '10/10px;12/12px;13/13px;14/14px;16/16px;18/18px;20/20px;24/24px;28/28px;36/36px;48/48px'
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
htmlEditorLangsMap = {
|
||||
'ar_sa': 'ar-sa',
|
||||
'bg_bg': 'bg',
|
||||
'cs_CZ': 'cs',
|
||||
'de_de': 'de',
|
||||
'el_gr': 'el',
|
||||
'es_es': 'es',
|
||||
'et_ee': 'et',
|
||||
'fr_fr': 'fr',
|
||||
'hu_hu': 'hu',
|
||||
'is_is': 'is',
|
||||
'it_it': 'it',
|
||||
'ja_jp': 'ja',
|
||||
'ko_kr': 'ko',
|
||||
'lt_lt': 'lt',
|
||||
'lv_lv': 'lv',
|
||||
'fa_ir': 'fa',
|
||||
'nb_no': 'nb',
|
||||
'nl_nl': 'nl',
|
||||
'pl_pl': 'pl',
|
||||
'pt_br': 'pt-br',
|
||||
'pt_pt': 'pt',
|
||||
'ro_ro': 'ro',
|
||||
'ru_ru': 'ru',
|
||||
'sk_sk': 'sk',
|
||||
'sl_si': 'sl',
|
||||
'sv_se': 'sv',
|
||||
'tr_tr': 'tr',
|
||||
'uk_ua': 'uk',
|
||||
'zh_cn': 'zh-cn',
|
||||
'zh_tw': 'zh'
|
||||
};
|
||||
import { createCKEditor } from 'External/CKEditor.js';
|
||||
|
||||
class HtmlEditor {
|
||||
editor;
|
||||
|
@ -218,14 +143,6 @@ class HtmlEditor {
|
|||
}
|
||||
}
|
||||
|
||||
replaceHtml(find, replaceHtml) {
|
||||
if (this.editor && this.__inited && 'wysiwyg' === this.editor.mode) {
|
||||
try {
|
||||
this.editor.setData(this.editor.getData().replace(find, replaceHtml));
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
}
|
||||
|
||||
setPlain(plain, focus) {
|
||||
if (this.editor && this.__inited) {
|
||||
this.clearCachedSignature();
|
||||
|
@ -258,82 +175,23 @@ class HtmlEditor {
|
|||
this.resize();
|
||||
|
||||
this.onReady && this.onReady();
|
||||
},
|
||||
initFunc = () => {
|
||||
if (window.CKEDITOR) {
|
||||
const config = CKEditorDefaultConfig,
|
||||
language = rl.settings.get('Language'),
|
||||
allowSource = !!rl.settings.app('allowHtmlEditorSourceButton'),
|
||||
biti = !!rl.settings.app('allowHtmlEditorBitiButtons');
|
||||
|
||||
if ((allowSource || !biti) && !config.toolbarGroups.__cfgInited) {
|
||||
config.toolbarGroups.__cfgInited = true;
|
||||
|
||||
if (allowSource) {
|
||||
config.removeButtons = config.removeButtons.replace(',Source', '');
|
||||
}
|
||||
|
||||
if (!biti) {
|
||||
config.removePlugins += (config.removePlugins ? ',' : '') + 'bidi';
|
||||
}
|
||||
}
|
||||
|
||||
config.enterMode = CKEDITOR.ENTER_BR;
|
||||
config.shiftEnterMode = CKEDITOR.ENTER_P;
|
||||
|
||||
config.language = htmlEditorLangsMap[(language || 'en').toLowerCase()] || 'en';
|
||||
if (CKEDITOR.env) {
|
||||
CKEDITOR.env.isCompatible = true;
|
||||
}
|
||||
|
||||
this.editor = CKEDITOR.appendTo(this.element, config);
|
||||
|
||||
this.editor.on('key', event => !(event && event.data && 'Tab' == event.data.key));
|
||||
|
||||
if (window.FileReader) {
|
||||
this.editor.on('drop', (event) => {
|
||||
if (0 < event.data.dataTransfer.getFilesCount()) {
|
||||
const file = event.data.dataTransfer.getFile(0);
|
||||
if (file && event.data.dataTransfer.id && file.type && file.type.match(/^image/i)) {
|
||||
const id = event.data.dataTransfer.id,
|
||||
imageId = `[img=${id}]`,
|
||||
reader = new FileReader();
|
||||
|
||||
reader.onloadend = () => {
|
||||
if (reader.result) {
|
||||
this.replaceHtml(imageId, `<img src="${reader.result}" />`);
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
event.data.dataTransfer.setData('text/html', imageId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.editor.on('instanceReady', onReady);
|
||||
}
|
||||
else if (window.Squire) {
|
||||
this.editor = new SquireUI(this.element, this.editor);
|
||||
setTimeout(onReady,1);
|
||||
}
|
||||
|
||||
if (this.editor) {
|
||||
this.editor.on('blur', () => this.blurTrigger());
|
||||
this.editor.on('focus', () => this.blurTimer && clearTimeout(this.blurTimer));
|
||||
this.editor.on('mode', () => {
|
||||
this.blurTrigger();
|
||||
this.onModeChange && this.onModeChange('plain' !== this.editor.mode);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (window.CKEDITOR || window.Squire) {
|
||||
initFunc();
|
||||
if (window.CKEDITOR) {
|
||||
this.editor = createCKEditor(this.element);
|
||||
this.editor.on('instanceReady', onReady);
|
||||
} else {
|
||||
window.__initEditor = initFunc;
|
||||
this.editor = new SquireUI(this.element, this.editor);
|
||||
setTimeout(onReady,1);
|
||||
}
|
||||
|
||||
if (this.editor) {
|
||||
this.editor.on('blur', () => this.blurTrigger());
|
||||
this.editor.on('focus', () => this.blurTimer && clearTimeout(this.blurTimer));
|
||||
this.editor.on('mode', () => {
|
||||
this.blurTrigger();
|
||||
this.onModeChange && this.onModeChange('plain' !== this.editor.mode);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
133
dev/External/CKEditor.js
vendored
Normal file
133
dev/External/CKEditor.js
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
const config = {
|
||||
'title': false,
|
||||
'stylesSet': false,
|
||||
'customConfig': '',
|
||||
'contentsCss': '',
|
||||
'toolbarGroups': [
|
||||
{ name: 'spec' },
|
||||
{ name: 'styles' },
|
||||
{ name: 'basicstyles', groups: ['basicstyles', 'cleanup', 'bidi'] },
|
||||
{ name: 'colors' },
|
||||
{ name: 'paragraph', groups: ['list', 'indent', 'blocks', 'align'] },
|
||||
{ name: 'links' },
|
||||
{ name: 'insert' },
|
||||
{ name: 'document', groups: ['mode', 'document', 'doctools'] },
|
||||
{ name: 'others' }
|
||||
],
|
||||
|
||||
'removePlugins': 'liststyle',
|
||||
'removeButtons': 'Format,Undo,Redo,Cut,Copy,Paste,Anchor,Strike,Subscript,Superscript,Image,SelectAll,Source',
|
||||
'removeDialogTabs': 'link:advanced;link:target;image:advanced;images:advanced',
|
||||
|
||||
'extraPlugins': 'plain,signature',
|
||||
|
||||
'allowedContent': true,
|
||||
'extraAllowedContent': true,
|
||||
|
||||
'fillEmptyBlocks': false,
|
||||
'ignoreEmptyParagraph': true,
|
||||
'disableNativeSpellChecker': false,
|
||||
|
||||
'colorButton_enableAutomatic': false,
|
||||
'colorButton_enableMore': true,
|
||||
|
||||
'font_defaultLabel': 'Arial',
|
||||
'fontSize_defaultLabel': '13',
|
||||
'fontSize_sizes': '10/10px;12/12px;13/13px;14/14px;16/16px;18/18px;20/20px;24/24px;28/28px;36/36px;48/48px'
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
htmlEditorLangsMap = {
|
||||
'ar_sa': 'ar-sa',
|
||||
'bg_bg': 'bg',
|
||||
'cs_CZ': 'cs',
|
||||
'de_de': 'de',
|
||||
'el_gr': 'el',
|
||||
'es_es': 'es',
|
||||
'et_ee': 'et',
|
||||
'fr_fr': 'fr',
|
||||
'hu_hu': 'hu',
|
||||
'is_is': 'is',
|
||||
'it_it': 'it',
|
||||
'ja_jp': 'ja',
|
||||
'ko_kr': 'ko',
|
||||
'lt_lt': 'lt',
|
||||
'lv_lv': 'lv',
|
||||
'fa_ir': 'fa',
|
||||
'nb_no': 'nb',
|
||||
'nl_nl': 'nl',
|
||||
'pl_pl': 'pl',
|
||||
'pt_br': 'pt-br',
|
||||
'pt_pt': 'pt',
|
||||
'ro_ro': 'ro',
|
||||
'ru_ru': 'ru',
|
||||
'sk_sk': 'sk',
|
||||
'sl_si': 'sl',
|
||||
'sv_se': 'sv',
|
||||
'tr_tr': 'tr',
|
||||
'uk_ua': 'uk',
|
||||
'zh_cn': 'zh-cn',
|
||||
'zh_tw': 'zh'
|
||||
};
|
||||
|
||||
export function createCKEditor(element)
|
||||
{
|
||||
const language = rl.settings.get('Language'),
|
||||
allowSource = !!rl.settings.app('allowHtmlEditorSourceButton'),
|
||||
biti = !!rl.settings.app('allowHtmlEditorBitiButtons');
|
||||
|
||||
if ((allowSource || !biti) && !config.toolbarGroups.__cfgInited) {
|
||||
config.toolbarGroups.__cfgInited = true;
|
||||
|
||||
if (allowSource) {
|
||||
config.removeButtons = config.removeButtons.replace(',Source', '');
|
||||
}
|
||||
|
||||
if (!biti) {
|
||||
config.removePlugins += (config.removePlugins ? ',' : '') + 'bidi';
|
||||
}
|
||||
}
|
||||
|
||||
config.enterMode = CKEDITOR.ENTER_BR;
|
||||
config.shiftEnterMode = CKEDITOR.ENTER_P;
|
||||
|
||||
config.language = htmlEditorLangsMap[(language || 'en').toLowerCase()] || 'en';
|
||||
if (CKEDITOR.env) {
|
||||
CKEDITOR.env.isCompatible = true;
|
||||
}
|
||||
|
||||
const editor = CKEDITOR.appendTo(element, config);
|
||||
|
||||
editor.on('key', event => !(event && event.data && 'Tab' == event.data.key));
|
||||
|
||||
if (window.FileReader) {
|
||||
editor.on('drop', event => {
|
||||
if (0 < event.data.dataTransfer.getFilesCount()) {
|
||||
const file = event.data.dataTransfer.getFile(0);
|
||||
if (file && event.data.dataTransfer.id && file.type && file.type.match(/^image/i)) {
|
||||
const id = event.data.dataTransfer.id,
|
||||
imageId = `[img=${id}]`,
|
||||
reader = new FileReader();
|
||||
|
||||
reader.onloadend = () => {
|
||||
if (reader.result) {
|
||||
if ('wysiwyg' === editor.mode) {
|
||||
try {
|
||||
editor.setData(editor.getData().replace(imageId, `<img src="${reader.result}" />`));
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
event.data.dataTransfer.setData('text/html', imageId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return editor;
|
||||
}
|
123
dev/boot.js
123
dev/boot.js
|
@ -60,13 +60,18 @@ const
|
|||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = doc.createElement('script');
|
||||
script.onload = () => resolve();
|
||||
script.onload = () => {
|
||||
p.set(pStep += step);
|
||||
resolve();
|
||||
};
|
||||
script.onerror = () => reject(new Error(src));
|
||||
script.src = src;
|
||||
// script.async = true;
|
||||
doc.head.append(script);
|
||||
});
|
||||
},
|
||||
|
||||
step = 100 / 7,
|
||||
p = win.progressJs = {
|
||||
set: percent => progress.style.width = Math.min(percent, 100) + '%',
|
||||
end: () => {
|
||||
|
@ -84,10 +89,11 @@ if (!navigator || !navigator.cookieEnabled) {
|
|||
doc.location.href = './?/NoCookie';
|
||||
}
|
||||
|
||||
let container = doc.querySelector('.progressjs'),
|
||||
let pStep = 0,
|
||||
container = doc.querySelector('.progressjs'),
|
||||
progress = doc.querySelector('.progressjs-inner'),
|
||||
|
||||
RL_APP_DATA_STORAGE = {};
|
||||
RL_APP_DATA = {};
|
||||
|
||||
win.rl = {
|
||||
hash: {
|
||||
|
@ -95,8 +101,8 @@ win.rl = {
|
|||
get: () => storage().getItem(STORAGE_KEY) || null,
|
||||
// setHash
|
||||
set: () => {
|
||||
storage().setItem(STORAGE_KEY, RL_APP_DATA_STORAGE && RL_APP_DATA_STORAGE[AUTH_KEY]
|
||||
? RL_APP_DATA_STORAGE[AUTH_KEY] : '');
|
||||
storage().setItem(STORAGE_KEY, RL_APP_DATA && RL_APP_DATA[AUTH_KEY]
|
||||
? RL_APP_DATA[AUTH_KEY] : '');
|
||||
setTimestamp();
|
||||
},
|
||||
// clearHash
|
||||
|
@ -114,96 +120,63 @@ win.rl = {
|
|||
return false;
|
||||
}
|
||||
},
|
||||
data: () => RL_APP_DATA_STORAGE,
|
||||
data: () => RL_APP_DATA,
|
||||
adminArea: () => options.admin,
|
||||
settings: {
|
||||
get: name => null == RL_APP_DATA_STORAGE[name] ? null : RL_APP_DATA_STORAGE[name],
|
||||
set: (name, value) => RL_APP_DATA_STORAGE[name] = value,
|
||||
get: name => null == RL_APP_DATA[name] ? null : RL_APP_DATA[name],
|
||||
set: (name, value) => RL_APP_DATA[name] = value,
|
||||
app: name => {
|
||||
const APP_SETTINGS = RL_APP_DATA_STORAGE.System || {};
|
||||
const APP_SETTINGS = RL_APP_DATA.System || {};
|
||||
return null == APP_SETTINGS[name] ? null : APP_SETTINGS[name];
|
||||
},
|
||||
capa: name => null != name && Array.isArray(RL_APP_DATA_STORAGE.Capa) && RL_APP_DATA_STORAGE.Capa.includes(name)
|
||||
capa: name => null != name && Array.isArray(RL_APP_DATA.Capa) && RL_APP_DATA.Capa.includes(name)
|
||||
},
|
||||
setWindowTitle: title => {
|
||||
title = null == title ? '' : '' + title;
|
||||
if (RL_APP_DATA_STORAGE.Title) {
|
||||
title += (title ? ' - ' : '') + RL_APP_DATA_STORAGE.Title;
|
||||
if (RL_APP_DATA.Title) {
|
||||
title += (title ? ' - ' : '') + RL_APP_DATA.Title;
|
||||
}
|
||||
doc.title = null == title ? '' : '' + title;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {mixed} appData
|
||||
* @returns {void}
|
||||
*/
|
||||
win.__initAppData = appData => {
|
||||
RL_APP_DATA_STORAGE = appData;
|
||||
initData: appData => {
|
||||
RL_APP_DATA = appData;
|
||||
|
||||
rl.hash.set();
|
||||
rl.hash.set();
|
||||
|
||||
if (appData) {
|
||||
if (appData.NewThemeLink) {
|
||||
eId('app-theme-link').href = appData.NewThemeLink;
|
||||
}
|
||||
|
||||
appData.IncludeCss && writeCSS(appData.IncludeCss);
|
||||
|
||||
if (appData.IncludeBackground) {
|
||||
const img = appData.IncludeBackground.replace('{{USER}}', rl.hash.get() || '0');
|
||||
if (img) {
|
||||
htmlCL.add('UserBackground');
|
||||
doc.body.style.backgroundImage = "url("+img+")";
|
||||
if (appData) {
|
||||
if (appData.NewThemeLink) {
|
||||
eId('app-theme-link').href = appData.NewThemeLink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
appData &&
|
||||
appData.TemplatesLink &&
|
||||
appData.LangLink &&
|
||||
appData.StaticLibJsLink &&
|
||||
appData.StaticAppJsLink
|
||||
) {
|
||||
p.set(5);
|
||||
appData.IncludeCss && writeCSS(appData.IncludeCss);
|
||||
|
||||
loadScript(appData.StaticLibJsLink)
|
||||
.then(() => {
|
||||
p.set(20);
|
||||
return Promise.all([loadScript(appData.TemplatesLink), loadScript(appData.LangLink)]);
|
||||
})
|
||||
.then(() => {
|
||||
p.set(30);
|
||||
return loadScript(appData.StaticAppJsLink);
|
||||
})
|
||||
.then(() => {
|
||||
p.set(50);
|
||||
return appData.PluginsLink ? loadScript(appData.PluginsLink) : Promise.resolve();
|
||||
})
|
||||
.then(() => {
|
||||
if (win.__APP_BOOT) {
|
||||
p.set(70);
|
||||
win.__APP_BOOT(() => showError());
|
||||
} else {
|
||||
showError();
|
||||
if (appData.IncludeBackground) {
|
||||
const img = appData.IncludeBackground.replace('{{USER}}', rl.hash.get() || '0');
|
||||
if (img) {
|
||||
htmlCL.add('UserBackground');
|
||||
doc.body.style.backgroundImage = "url("+img+")";
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
}
|
||||
|
||||
loadScript(appData.StaticLibJsLink)
|
||||
.then(() => Promise.all([loadScript(appData.TemplatesLink), loadScript(appData.LangLink)]))
|
||||
.then(() => loadScript(appData.StaticAppJsLink))
|
||||
.then(() => appData.PluginsLink ? loadScript(appData.PluginsLink) : Promise.resolve())
|
||||
.then(() =>
|
||||
// Enable the old CKEditor?
|
||||
(appData.Auth && appData.StaticEditorJsLink)
|
||||
? loadScript(appData.StaticEditorJsLink)
|
||||
: Promise.resolve()
|
||||
)
|
||||
.then(() => win.__APP_BOOT ? win.__APP_BOOT(showError) : showError())
|
||||
.catch(e => {
|
||||
showError();
|
||||
throw e;
|
||||
})
|
||||
.then(() => {
|
||||
// Enable the old CKEditor
|
||||
if (appData.Auth && appData.StaticEditorJsLink) {
|
||||
loadScript(appData.StaticEditorJsLink).then(() => {
|
||||
win.__initEditor && win.__initEditor();
|
||||
win.__initEditor = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
showError();
|
||||
} else {
|
||||
showError();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1007,9 +1007,11 @@ class ServiceActions
|
|||
$this->oActions->SetSpecAuthToken($sAuthAccountHash);
|
||||
}
|
||||
|
||||
$sResult = $this->compileAppData($this->oActions->AppData($bAdmin,
|
||||
0 === \strpos($sAdd, 'mobile'), '1' === \substr($sAdd, -1),
|
||||
$sAuthAccountHash), false);
|
||||
$sResult = 'rl.initData('
|
||||
.\json_encode($this->oActions->AppData($bAdmin,
|
||||
0 === \strpos($sAdd, 'mobile'), '1' === \substr($sAdd, -1),
|
||||
$sAuthAccountHash))
|
||||
.');';
|
||||
|
||||
$this->Logger()->Write($sResult, \MailSo\Log\Enumerations\Type::INFO, 'APPDATA');
|
||||
|
||||
|
@ -1092,13 +1094,4 @@ class ServiceActions
|
|||
($bWrapByScriptTag ? '</script>' : '')
|
||||
;
|
||||
}
|
||||
|
||||
private function compileAppData(array $aAppData, bool $bWrapByScriptTag = true) : string
|
||||
{
|
||||
return
|
||||
($bWrapByScriptTag ? '<script type="text/javascript" data-cfasync="false">' : '').
|
||||
'if(window.__initAppData){window.__initAppData('.\json_encode($aAppData).');}'.
|
||||
($bWrapByScriptTag ? '</script>' : '')
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
8
vendors/ckeditor-plugins/signature/plugin.js
vendored
8
vendors/ckeditor-plugins/signature/plugin.js
vendored
|
@ -1,5 +1,5 @@
|
|||
|
||||
(function(CKEDITOR, $) {
|
||||
(function(CKEDITOR) {
|
||||
|
||||
'use strict';
|
||||
|
||||
|
@ -10,10 +10,10 @@
|
|||
isEmptyText = false,
|
||||
newLine = (isHtml ? '<br />' : "\n"),
|
||||
clearHtmlLine = function(html) {
|
||||
return $.trim(editor.__textUtils.htmlToPlain(html));
|
||||
return editor.__textUtils.htmlToPlain(html).trim();
|
||||
};
|
||||
|
||||
isEmptyText = !$.trim(text);
|
||||
isEmptyText = !text.trim();
|
||||
if (!isEmptyText && isHtml)
|
||||
{
|
||||
isEmptyText = !clearHtmlLine(text);
|
||||
|
@ -138,4 +138,4 @@
|
|||
}
|
||||
});
|
||||
|
||||
}(CKEDITOR, $));
|
||||
}(CKEDITOR));
|
||||
|
|
Loading…
Reference in a new issue