suneditor 3.0.0-alpha.2 → 3.0.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +4 -3
- package/CONTRIBUTING.md +4 -2
- package/README.md +19 -11
- package/README_V3_TEMP.md +705 -0
- package/dist/suneditor.min.css +1 -0
- package/dist/suneditor.min.js +1 -0
- package/example.md +587 -0
- package/package.json +15 -9
- package/src/assets/icons/_default.js +166 -131
- package/src/assets/{suneditor-content.css → suneditor-contents.css} +182 -45
- package/src/assets/suneditor.css +1195 -556
- package/src/assets/variables.css +138 -0
- package/src/core/base/eventHandlers/handler_toolbar.js +35 -14
- package/src/core/base/eventHandlers/handler_ww_clipboard.js +29 -4
- package/src/core/base/eventHandlers/handler_ww_dragDrop.js +59 -15
- package/src/core/base/eventHandlers/handler_ww_key_input.js +426 -212
- package/src/core/base/eventHandlers/handler_ww_mouse.js +108 -32
- package/src/core/base/eventManager.js +540 -209
- package/src/core/base/events.js +616 -320
- package/src/core/base/history.js +93 -39
- package/src/core/class/char.js +29 -13
- package/src/core/class/component.js +332 -145
- package/src/core/class/format.js +671 -509
- package/src/core/class/html.js +504 -290
- package/src/core/class/menu.js +114 -47
- package/src/core/class/nodeTransform.js +111 -66
- package/src/core/class/offset.js +409 -105
- package/src/core/class/selection.js +220 -108
- package/src/core/class/shortcuts.js +68 -8
- package/src/core/class/toolbar.js +106 -116
- package/src/core/class/ui.js +330 -0
- package/src/core/class/viewer.js +178 -74
- package/src/core/editor.js +489 -384
- package/src/core/section/actives.js +118 -22
- package/src/core/section/constructor.js +504 -170
- package/src/core/section/context.js +28 -23
- package/src/core/section/documentType.js +561 -0
- package/src/editorInjector/_classes.js +19 -5
- package/src/editorInjector/_core.js +71 -7
- package/src/editorInjector/index.js +63 -1
- package/src/helper/converter.js +137 -19
- package/src/helper/dom/domCheck.js +294 -0
- package/src/helper/dom/domQuery.js +609 -0
- package/src/helper/dom/domUtils.js +533 -0
- package/src/helper/dom/index.js +12 -0
- package/src/helper/env.js +42 -19
- package/src/helper/index.js +7 -4
- package/src/helper/keyCodeMap.js +183 -0
- package/src/helper/numbers.js +8 -8
- package/src/helper/unicode.js +5 -5
- package/src/langs/ckb.js +69 -3
- package/src/langs/cs.js +67 -1
- package/src/langs/da.js +68 -2
- package/src/langs/de.js +68 -3
- package/src/langs/en.js +29 -1
- package/src/langs/es.js +68 -3
- package/src/langs/fa.js +70 -2
- package/src/langs/fr.js +68 -2
- package/src/langs/he.js +68 -3
- package/src/langs/hu.js +226 -0
- package/src/langs/index.js +3 -2
- package/src/langs/it.js +65 -0
- package/src/langs/ja.js +68 -3
- package/src/langs/ko.js +66 -1
- package/src/langs/lv.js +68 -3
- package/src/langs/nl.js +68 -3
- package/src/langs/pl.js +68 -3
- package/src/langs/pt_br.js +65 -0
- package/src/langs/ro.js +69 -4
- package/src/langs/ru.js +68 -3
- package/src/langs/se.js +68 -3
- package/src/langs/tr.js +68 -0
- package/src/langs/ua.js +68 -3
- package/src/langs/ur.js +71 -6
- package/src/langs/zh_cn.js +69 -4
- package/src/modules/ApiManager.js +77 -54
- package/src/modules/Browser.js +667 -0
- package/src/modules/ColorPicker.js +162 -102
- package/src/modules/Controller.js +233 -136
- package/src/modules/Figure.js +913 -489
- package/src/modules/FileManager.js +141 -72
- package/src/modules/HueSlider.js +113 -61
- package/src/modules/Modal.js +292 -113
- package/src/modules/ModalAnchorEditor.js +380 -230
- package/src/modules/SelectMenu.js +270 -168
- package/src/modules/_DragHandle.js +2 -1
- package/src/modules/index.js +3 -3
- package/src/plugins/browser/audioGallery.js +83 -0
- package/src/plugins/browser/fileBrowser.js +103 -0
- package/src/plugins/browser/fileGallery.js +83 -0
- package/src/plugins/browser/imageGallery.js +81 -0
- package/src/plugins/browser/videoGallery.js +103 -0
- package/src/plugins/command/blockquote.js +40 -27
- package/src/plugins/command/exportPDF.js +134 -0
- package/src/plugins/command/fileUpload.js +226 -158
- package/src/plugins/command/list_bulleted.js +93 -47
- package/src/plugins/command/list_numbered.js +93 -47
- package/src/plugins/dropdown/align.js +66 -54
- package/src/plugins/dropdown/backgroundColor.js +76 -45
- package/src/plugins/dropdown/font.js +71 -47
- package/src/plugins/dropdown/fontColor.js +78 -46
- package/src/plugins/dropdown/formatBlock.js +74 -33
- package/src/plugins/dropdown/hr.js +102 -51
- package/src/plugins/dropdown/layout.js +37 -26
- package/src/plugins/dropdown/lineHeight.js +54 -38
- package/src/plugins/dropdown/list.js +60 -45
- package/src/plugins/dropdown/paragraphStyle.js +51 -30
- package/src/plugins/dropdown/table.js +1269 -777
- package/src/plugins/dropdown/template.js +38 -26
- package/src/plugins/dropdown/textStyle.js +43 -31
- package/src/plugins/field/mention.js +144 -82
- package/src/plugins/index.js +32 -6
- package/src/plugins/input/fontSize.js +161 -108
- package/src/plugins/input/pageNavigator.js +70 -0
- package/src/plugins/modal/audio.js +341 -169
- package/src/plugins/modal/drawing.js +530 -0
- package/src/plugins/modal/embed.js +886 -0
- package/src/plugins/modal/image.js +673 -358
- package/src/plugins/modal/link.js +100 -71
- package/src/plugins/modal/math.js +384 -168
- package/src/plugins/modal/video.js +693 -336
- package/src/plugins/popup/anchor.js +222 -0
- package/src/suneditor.js +54 -12
- package/src/themes/dark.css +85 -0
- package/src/typedef.js +86 -0
- package/types/assets/icons/_default.d.ts +152 -0
- package/types/core/base/eventHandlers/handler_toolbar.d.ts +41 -0
- package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +40 -0
- package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +35 -0
- package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +45 -0
- package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +39 -0
- package/types/core/base/eventManager.d.ts +377 -0
- package/types/core/base/events.d.ts +297 -0
- package/types/core/base/history.d.ts +81 -0
- package/types/core/class/char.d.ts +60 -0
- package/types/core/class/component.d.ts +259 -0
- package/types/core/class/format.d.ts +615 -0
- package/types/core/class/html.d.ts +377 -0
- package/types/core/class/menu.d.ts +118 -0
- package/types/core/class/nodeTransform.d.ts +93 -0
- package/types/core/class/offset.d.ts +512 -0
- package/types/core/class/selection.d.ts +188 -0
- package/types/core/class/shortcuts.d.ts +142 -0
- package/types/core/class/toolbar.d.ts +189 -0
- package/types/core/class/ui.d.ts +144 -0
- package/types/core/class/viewer.d.ts +140 -0
- package/types/core/editor.d.ts +606 -0
- package/types/core/section/actives.d.ts +46 -0
- package/types/core/section/constructor.d.ts +748 -0
- package/types/core/section/context.d.ts +45 -0
- package/types/core/section/documentType.d.ts +178 -0
- package/types/editorInjector/_classes.d.ts +41 -0
- package/types/editorInjector/_core.d.ts +92 -0
- package/types/editorInjector/index.d.ts +71 -0
- package/types/helper/converter.d.ts +150 -0
- package/types/helper/dom/domCheck.d.ts +182 -0
- package/types/helper/dom/domQuery.d.ts +214 -0
- package/types/helper/dom/domUtils.d.ts +211 -0
- package/types/helper/dom/index.d.ts +9 -0
- package/types/helper/env.d.ts +149 -0
- package/types/helper/index.d.ts +163 -0
- package/types/helper/keyCodeMap.d.ts +110 -0
- package/types/helper/numbers.d.ts +43 -0
- package/types/helper/unicode.d.ts +28 -0
- package/types/index.d.ts +0 -0
- package/{typings/Lang.d.ts → types/langs/_Lang.d.ts} +170 -103
- package/types/langs/ckb.d.ts +384 -0
- package/types/langs/cs.d.ts +384 -0
- package/types/langs/da.d.ts +384 -0
- package/types/langs/de.d.ts +384 -0
- package/types/langs/en.d.ts +384 -0
- package/types/langs/es.d.ts +384 -0
- package/types/langs/fa.d.ts +384 -0
- package/types/langs/fr.d.ts +384 -0
- package/types/langs/he.d.ts +384 -0
- package/types/langs/hu.d.ts +384 -0
- package/types/langs/index.d.ts +48 -0
- package/types/langs/it.d.ts +384 -0
- package/types/langs/ja.d.ts +384 -0
- package/types/langs/ko.d.ts +384 -0
- package/types/langs/lv.d.ts +384 -0
- package/types/langs/nl.d.ts +384 -0
- package/types/langs/pl.d.ts +384 -0
- package/types/langs/pt_br.d.ts +384 -0
- package/types/langs/ro.d.ts +384 -0
- package/types/langs/ru.d.ts +384 -0
- package/types/langs/se.d.ts +384 -0
- package/types/langs/tr.d.ts +384 -0
- package/types/langs/ua.d.ts +384 -0
- package/types/langs/ur.d.ts +384 -0
- package/types/langs/zh_cn.d.ts +384 -0
- package/types/modules/ApiManager.d.ts +125 -0
- package/types/modules/Browser.d.ts +326 -0
- package/types/modules/ColorPicker.d.ts +131 -0
- package/types/modules/Controller.d.ts +231 -0
- package/types/modules/Figure.d.ts +504 -0
- package/types/modules/FileManager.d.ts +202 -0
- package/types/modules/HueSlider.d.ts +136 -0
- package/types/modules/Modal.d.ts +117 -0
- package/types/modules/ModalAnchorEditor.d.ts +236 -0
- package/types/modules/SelectMenu.d.ts +194 -0
- package/types/modules/_DragHandle.d.ts +7 -0
- package/types/modules/index.d.ts +26 -0
- package/types/plugins/browser/audioGallery.d.ts +55 -0
- package/types/plugins/browser/fileBrowser.d.ts +64 -0
- package/types/plugins/browser/fileGallery.d.ts +55 -0
- package/types/plugins/browser/imageGallery.d.ts +51 -0
- package/types/plugins/browser/videoGallery.d.ts +57 -0
- package/types/plugins/command/blockquote.d.ts +28 -0
- package/types/plugins/command/exportPDF.d.ts +46 -0
- package/types/plugins/command/fileUpload.d.ts +156 -0
- package/types/plugins/command/list_bulleted.d.ts +56 -0
- package/types/plugins/command/list_numbered.d.ts +56 -0
- package/types/plugins/dropdown/align.d.ts +60 -0
- package/types/plugins/dropdown/backgroundColor.d.ts +63 -0
- package/types/plugins/dropdown/font.d.ts +54 -0
- package/types/plugins/dropdown/fontColor.d.ts +63 -0
- package/types/plugins/dropdown/formatBlock.d.ts +58 -0
- package/types/plugins/dropdown/hr.d.ts +81 -0
- package/types/plugins/dropdown/layout.d.ts +40 -0
- package/types/plugins/dropdown/lineHeight.d.ts +50 -0
- package/types/plugins/dropdown/list.d.ts +39 -0
- package/types/plugins/dropdown/paragraphStyle.d.ts +54 -0
- package/types/plugins/dropdown/table.d.ts +579 -0
- package/types/plugins/dropdown/template.d.ts +40 -0
- package/types/plugins/dropdown/textStyle.d.ts +41 -0
- package/types/plugins/field/mention.d.ts +102 -0
- package/types/plugins/index.d.ts +107 -0
- package/types/plugins/input/fontSize.d.ts +170 -0
- package/types/plugins/input/pageNavigator.d.ts +28 -0
- package/types/plugins/modal/audio.d.ts +269 -0
- package/types/plugins/modal/drawing.d.ts +246 -0
- package/types/plugins/modal/embed.d.ts +387 -0
- package/types/plugins/modal/image.d.ts +451 -0
- package/types/plugins/modal/link.d.ts +128 -0
- package/types/plugins/modal/math.d.ts +193 -0
- package/types/plugins/modal/video.d.ts +485 -0
- package/types/plugins/popup/anchor.d.ts +56 -0
- package/types/suneditor.d.ts +51 -0
- package/types/typedef-global.d.ts +144 -0
- package/src/core/class/notice.js +0 -42
- package/src/helper/domUtils.js +0 -1177
- package/src/modules/FileBrowser.js +0 -271
- package/src/plugins/command/exportPdf.js +0 -168
- package/src/plugins/fileBrowser/imageGallery.js +0 -81
- package/src/themes/test.css +0 -61
- package/typings/CommandPlugin.d.ts +0 -8
- package/typings/DialogPlugin.d.ts +0 -20
- package/typings/FileBrowserPlugin.d.ts +0 -30
- package/typings/Module.d.ts +0 -15
- package/typings/Plugin.d.ts +0 -42
- package/typings/SubmenuPlugin.d.ts +0 -8
- package/typings/_classes.d.ts +0 -17
- package/typings/_colorPicker.d.ts +0 -60
- package/typings/_core.d.ts +0 -55
- package/typings/align.d.ts +0 -5
- package/typings/audio.d.ts +0 -5
- package/typings/backgroundColor.d.ts +0 -5
- package/typings/blockquote.d.ts +0 -5
- package/typings/char.d.ts +0 -39
- package/typings/component.d.ts +0 -38
- package/typings/context.d.ts +0 -39
- package/typings/converter.d.ts +0 -33
- package/typings/dialog.d.ts +0 -28
- package/typings/domUtils.d.ts +0 -361
- package/typings/editor.d.ts +0 -7
- package/typings/editor.ts +0 -542
- package/typings/env.d.ts +0 -70
- package/typings/eventManager.d.ts +0 -37
- package/typings/events.d.ts +0 -262
- package/typings/fileBrowser.d.ts +0 -42
- package/typings/fileManager.d.ts +0 -67
- package/typings/font.d.ts +0 -5
- package/typings/fontColor.d.ts +0 -5
- package/typings/fontSize.d.ts +0 -5
- package/typings/format.d.ts +0 -191
- package/typings/formatBlock.d.ts +0 -5
- package/typings/history.d.ts +0 -48
- package/typings/horizontalRule.d.ts +0 -5
- package/typings/image.d.ts +0 -5
- package/typings/imageGallery.d.ts +0 -5
- package/typings/index.d.ts +0 -21
- package/typings/index.modules.d.ts +0 -11
- package/typings/index.plugins.d.ts +0 -58
- package/typings/lineHeight.d.ts +0 -5
- package/typings/link.d.ts +0 -5
- package/typings/list.d.ts +0 -5
- package/typings/math.d.ts +0 -5
- package/typings/mediaContainer.d.ts +0 -25
- package/typings/mention.d.ts +0 -5
- package/typings/node.d.ts +0 -57
- package/typings/notice.d.ts +0 -16
- package/typings/numbers.d.ts +0 -29
- package/typings/offset.d.ts +0 -24
- package/typings/options.d.ts +0 -589
- package/typings/paragraphStyle.d.ts +0 -5
- package/typings/resizing.d.ts +0 -141
- package/typings/selection.d.ts +0 -94
- package/typings/shortcuts.d.ts +0 -13
- package/typings/suneditor.d.ts +0 -9
- package/typings/table.d.ts +0 -5
- package/typings/template.d.ts +0 -5
- package/typings/textStyle.d.ts +0 -5
- package/typings/toolbar.d.ts +0 -32
- package/typings/unicode.d.ts +0 -25
- package/typings/video.d.ts +0 -5
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import _icons from '../../assets/icons/_default';
|
|
2
2
|
import _defaultLang from '../../langs/en';
|
|
3
3
|
import { CreateContext, CreateFrameContext } from './context';
|
|
4
|
-
import {
|
|
4
|
+
import { dom, numbers, converter, env } from '../../helper';
|
|
5
5
|
|
|
6
6
|
const _d = env._d;
|
|
7
|
-
const DEFAULT_BUTTON_LIST = [
|
|
7
|
+
const DEFAULT_BUTTON_LIST = [
|
|
8
|
+
['undo', 'redo'],
|
|
9
|
+
'|',
|
|
10
|
+
['bold', 'underline', 'italic', 'strike', '|', 'subscript', 'superscript'],
|
|
11
|
+
'|',
|
|
12
|
+
['removeFormat'],
|
|
13
|
+
'|',
|
|
14
|
+
['outdent', 'indent'],
|
|
15
|
+
'|',
|
|
16
|
+
['fullScreen', 'showBlocks', 'codeView'],
|
|
17
|
+
'|',
|
|
18
|
+
['preview', 'print']
|
|
19
|
+
];
|
|
8
20
|
|
|
9
21
|
const REQUIRED_FORMAT_LINE = 'div';
|
|
10
22
|
const REQUIRED_ELEMENT_WHITELIST = 'br|div';
|
|
11
23
|
const DEFAULT_ELEMENT_WHITELIST =
|
|
12
24
|
'p|pre|blockquote|h1|h2|h3|h4|h5|h6|ol|ul|li|hr|figure|figcaption|img|iframe|audio|video|source|table|thead|tbody|tr|th|td|caption|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup|code|svg|path|details|summary';
|
|
13
25
|
const DEFAULT_TEXT_STYLE_TAGS = 'strong|span|font|b|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label|code|summary';
|
|
14
|
-
|
|
26
|
+
|
|
27
|
+
const _video_audio_attr = '|controls|autoplay|loop|muted|poster|preload|playsinline|volume|crossorigin|disableRemotePlayback|controlsList';
|
|
28
|
+
const _iframe_attr = '|allowfullscreen|sandbox|loading|allow|referrerpolicy|frameborder|scrolling';
|
|
29
|
+
const DEFAULT_ATTRIBUTE_WHITELIST = 'contenteditable|target|href|title|download|rel|src|alt|class|type|colspan|rowspan' + _video_audio_attr + _iframe_attr;
|
|
15
30
|
|
|
16
31
|
const DEFAULT_FORMAT_LINE = 'P|H[1-6]|LI|TH|TD|DETAILS';
|
|
17
32
|
const DEFAULT_FORMAT_BR_LINE = 'PRE';
|
|
@@ -19,9 +34,12 @@ const DEFAULT_FORMAT_CLOSURE_BR_LINE = '';
|
|
|
19
34
|
const DEFAULT_FORMAT_BLOCK = 'BLOCKQUOTE|OL|UL|FIGCAPTION|TABLE|THEAD|TBODY|TR|CAPTION|DETAILS';
|
|
20
35
|
const DEFAULT_FORMAT_CLOSURE_BLOCK = 'TH|TD';
|
|
21
36
|
|
|
37
|
+
const DEFAULT_ALLOWED_EMPTY_NODE_LIST = '.se-component, pre, blockquote, hr, li, table, img, iframe, video, audio, canvas, details';
|
|
38
|
+
|
|
22
39
|
const DEFAULT_SIZE_UNITS = ['px', 'pt', 'em', 'rem'];
|
|
23
40
|
|
|
24
|
-
const DEFAULT_CLASS_NAME = '^__se__|^se-|^katex';
|
|
41
|
+
const DEFAULT_CLASS_NAME = '^__se__|^se-|^katex|^MathJax';
|
|
42
|
+
const DEFAULT_CLASS_MJX = 'mjx-container|mjx-math|mjx-mrow|mjx-mi|mjx-mo|mjx-mn|mjx-msup|mjx-mfrac|mjx-munderover';
|
|
25
43
|
const DEFAULT_EXTRA_TAG_MAP = { script: false, style: false, meta: false, link: false, '[a-z]+:[a-z]+': false };
|
|
26
44
|
|
|
27
45
|
const DEFAULT_TAG_STYLES = {
|
|
@@ -42,6 +60,7 @@ const DEFAULT_CONTENT_STYLES =
|
|
|
42
60
|
'margin|margin-block-end|margin-block-start|margin-bottom|margin-inline-end|margin-inline-start|margin-left|margin-right|margin-top|max-width|min-width|' +
|
|
43
61
|
'outline|overflow|' +
|
|
44
62
|
'position|padding|padding-bottom|padding-inline-start|padding-left|padding-right|padding-top|' +
|
|
63
|
+
'page-break-before|page-break-after|page-break-inside|' +
|
|
45
64
|
'rotate|rotateX|rotateY|' +
|
|
46
65
|
'table-layout|text-align|text-decoration|text-shadow|text-transform|top|' +
|
|
47
66
|
'text-indent|text-rendering|' +
|
|
@@ -52,8 +71,8 @@ const RETAIN_STYLE_MODE = ['repeat', 'always', 'none'];
|
|
|
52
71
|
|
|
53
72
|
export const RO_UNAVAILABD = [
|
|
54
73
|
'mode',
|
|
74
|
+
'type',
|
|
55
75
|
'externalLibs',
|
|
56
|
-
'keepStyleOnDelete',
|
|
57
76
|
'iframe',
|
|
58
77
|
'convertTextTags',
|
|
59
78
|
'textStyleTags',
|
|
@@ -87,23 +106,161 @@ export const RO_UNAVAILABD = [
|
|
|
87
106
|
];
|
|
88
107
|
|
|
89
108
|
/**
|
|
90
|
-
* @
|
|
91
|
-
* @
|
|
92
|
-
* @
|
|
93
|
-
* @
|
|
109
|
+
* @typedef {Object} EditorFrameOptions
|
|
110
|
+
* @property {string} [value=""] - Initial value for the editor.
|
|
111
|
+
* @property {string} [placeholder=""] - Placeholder text.
|
|
112
|
+
* @property {Object<string, string>} [editableFrameAttributes={}] - Attributes for the editable frame[.sun-editor-editable]. (e.g. [key]: value)
|
|
113
|
+
* @property {string} [width="100%"] - Width for the editor.
|
|
114
|
+
* @property {string} [minWidth=""] - Min width for the editor.
|
|
115
|
+
* @property {string} [maxWidth=""] - Max width for the editor.
|
|
116
|
+
* @property {string} [height="auto"] - Height for the editor.
|
|
117
|
+
* @property {string} [minHeight=""] - Min height for the editor.
|
|
118
|
+
* @property {string} [maxHeight=""] - Max height for the editor.
|
|
119
|
+
* @property {string} [editorStyle=""] - Style string of the top frame of the editor. (e.g. "border: 1px solid #ccc;").
|
|
120
|
+
* @property {boolean} [iframe=false] - Content will be placed in an iframe and isolated from the rest of the page.
|
|
121
|
+
* @property {boolean} [iframe_fullPage=false] - Allows the usage of HTML, HEAD, BODY tags and DOCTYPE declaration on the "iframe".
|
|
122
|
+
* @property {Object<string, string>} [iframe_attributes={}] - Attributes of the "iframe". (e.g. {'scrolling': 'no'})
|
|
123
|
+
* @property {string} [iframe_cssFileName="suneditor"] - Name or Array of the CSS file to apply inside the iframe.
|
|
124
|
+
* - You can also use regular expressions.
|
|
125
|
+
* - Applied by searching by filename in the link tag of document,
|
|
126
|
+
* - or put the URL value (".css" can be omitted).
|
|
127
|
+
* @property {boolean} [statusbar=true] - Enables the status bar.
|
|
128
|
+
* @property {boolean} [statusbar_showPathLabel=true] - Displays the current node structure to status bar.
|
|
129
|
+
* @property {boolean} [statusbar_resizeEnable=true] - Enables resize function of bottom status bar
|
|
130
|
+
* @property {boolean} [charCounter=false] - Shows the number of characters in the editor.
|
|
131
|
+
* - If the maxCharCount option has a value, it becomes true.
|
|
132
|
+
* @property {number} [charCounter_max] - The maximum number of characters allowed to be inserted into the editor.
|
|
133
|
+
* @property {string} [charCounter_label] - Text to be displayed in the "charCounter" area of the bottom bar. (e.g. "Characters : 20/200")
|
|
134
|
+
* @property {"char"|"byte"|"byte-html"} [charCounter_type="char"] - Defines the calculation method of the "charCounter" option.
|
|
135
|
+
* - 'char': Characters length.
|
|
136
|
+
* - 'byte': Binary data size of characters.
|
|
137
|
+
* - 'byte-html': Binary data size of the full HTML string.
|
|
94
138
|
*/
|
|
95
|
-
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @typedef {Object} EditorBaseOptions
|
|
142
|
+
* @property {Object<string, *>|Array<Object<string, *>>} [plugins] - Plugin configuration.
|
|
143
|
+
* @property {Array<string>} [excludedPlugins] - Plugin configuration.
|
|
144
|
+
* @property {Array<string[]|string>} [buttonList] - List of toolbar buttons, grouped by sub-arrays.
|
|
145
|
+
* @property {boolean} [v2Migration=false] - Enables migration mode for SunEditor v2.
|
|
146
|
+
* @property {boolean|{tagFilter: boolean, formatFilter: boolean, classFilter: boolean, styleNodeFilter: boolean, attrFilter: boolean, styleFilter: boolean}} [strictMode=true] - Enables strict filtering of tags, attributes, and styles.
|
|
147
|
+
* @property {"classic"|"inline"|"balloon"|"balloon-always"} [mode="classic"] - Toolbar mode: "classic", "inline", "balloon", "balloon-always".
|
|
148
|
+
* @property {string} [type=""] - Editor type: "document:header,page".
|
|
149
|
+
* @property {string} [theme=""] - Editor theme.
|
|
150
|
+
* @property {Object<string, string>} [lang] - Language configuration.
|
|
151
|
+
* @property {Array<string>} [fontSizeUnits=["px", "pt", "em", "rem"]] - Allowed font size units.
|
|
152
|
+
* @property {string} [allowedClassName] - Allowed class names.
|
|
153
|
+
* @property {boolean} [closeModalOutsideClick=false] - Closes modals when clicking outside.
|
|
154
|
+
* @property {boolean} [copyFormatKeepOn=false] - Keeps the format of the copied content.
|
|
155
|
+
* @property {boolean} [syncTabIndent=true] - Synchronizes tab indent with spaces.
|
|
156
|
+
* @property {boolean} [tabDisable=false] - Disables tab key input.
|
|
157
|
+
* @property {boolean} [autoLinkify] - Automatically converts URLs into hyperlinks. ("Link" plugin required)
|
|
158
|
+
* @property {Array<string>} [autoStyleify=["bold", "underline", "italic", "strike"]] - Styles applied automatically on text input.
|
|
159
|
+
* @property {Object<string, string|number>} [scrollToOptions={behavior: "auto", block: "nearest"}] - Configuration for scroll behavior when navigating editor content.
|
|
160
|
+
* @property {Object<string, string|number>} [componentScrollToOptions={behavior: "smooth", block: "center"}] - Configuration for scroll behavior when navigating components.
|
|
161
|
+
* @property {"repeat"|"always"|"none"} [retainStyleMode="repeat"] - This option determines how inline elements (such as <span>, <strong>, etc.) are handled when deleting text.
|
|
162
|
+
* - "repeat": Inline styles are retained unless the backspace key is repeatedly pressed. If the user continuously presses backspace, the styles will eventually be removed.
|
|
163
|
+
* - "none": Inline styles are not retained at all. When deleting text, the associated inline elements are immediately removed along with it.
|
|
164
|
+
* - "always": Inline styles persist indefinitely unless explicitly removed. Even if all text inside an inline element is deleted, the element itself remains until manually removed.
|
|
165
|
+
* @property {Object<string, boolean>} [allowedExtraTags={script: false, style: false, meta: false, link: false, "[a-z]+:[a-z]+": false}] - Specifies extra allowed or disallowed tags.
|
|
166
|
+
* @property {Object<string, (...args: *) => *>} [events={}] - Custom event handlers.
|
|
167
|
+
* @property {string} [__textStyleTags="strong|span|font|b|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label|code|summary"] - The basic tags that serves as the base for "textStyleTags"
|
|
168
|
+
* @property {string} [textStyleTags="strong|span|font|b|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label|code|summary"] - Additional text style tags.
|
|
169
|
+
* @property {Object<string, string>} [convertTextTags={bold: "strong", underline: "u", italic: "em", strike: "del", subscript: "sub", superscript: "sup"}] - Maps text styles to specific HTML tags.
|
|
170
|
+
* @property {Object<string, string>} [__tagStyles={'table|th|td': 'border|border-[a-z]+|background-color|text-align|float|font-weight|text-decoration|font-style', 'ol|ul': 'list-style-type'}] - The basic tags that serves as the base for "tagStyles"
|
|
171
|
+
* @property {Object<string, string>} [tagStyles={}] - Specifies allowed styles for HTML tags.
|
|
172
|
+
* @property {string} [spanStyles="font-family|font-size|color|background-color"] - Specifies allowed styles for the "span" tag.
|
|
173
|
+
* @property {string} [lineStyles="text-align|margin-left|margin-right|line-height"] - Specifies allowed styles for the "line" element (p..).
|
|
174
|
+
* @property {string} [textDirection="ltr"] - Text direction: "ltr" or "rtl".
|
|
175
|
+
* @property {Array<string>} [reverseButtons=['indent-outdent']] - An array of command pairs whose shortcut icons should be opposite each other, depending on the "textDirection" mode.
|
|
176
|
+
* @property {number} [historyStackDelayTime=400] - Delay time for history stack updates (ms).
|
|
177
|
+
* @property {string} [lineAttrReset=""] - Line properties that should be reset when changing lines (e.g. "id|name").
|
|
178
|
+
* @property {string} [printClass=""] - Class name for printing.
|
|
179
|
+
* @property {string} [defaultLine="p"] - Default line element when inserting new lines.
|
|
180
|
+
* @property {string} [__defaultElementWhitelist="br|div"] - Default allowed HTML elements. The default values are maintained.
|
|
181
|
+
* @property {string} [elementWhitelist=""] - Allowed HTML elements. Delimiter: "|" (e.g. "p|div", "*").
|
|
182
|
+
* @property {string} [elementBlacklist=""] - Disallowed HTML elements. Delimiter: "|" (e.g. "script|style").
|
|
183
|
+
* @property {string} [__defaultAttributeWhitelist] - Allowed attributes. Delimiter: "|" (e.g. "href|target").
|
|
184
|
+
* @property {Object<string, string>} [attributeWhitelist=""] - Allowed attributes. (e.g. {a: "href|target", img: "src|alt"}).
|
|
185
|
+
* @property {Object<string, string>} [attributeBlacklist=""] - Disallowed attributes. (e.g. {a: "href|target", img: "src|alt"}).
|
|
186
|
+
* @property {string} [__defaultFormatLine="P|DIV|H[1-6]|LI|TH|TD|DETAILS"] - Overrides the editor's default "line" element.
|
|
187
|
+
* @property {string} [formatLine="P|DIV|H[1-6]|LI|TH|TD|DETAILS"] - Specifies the editor's "line" elements.
|
|
188
|
+
* - (P, DIV, H[1-6], PRE, LI | class="__se__format__line_xxx")
|
|
189
|
+
* - "line" element also contain "brLine" element
|
|
190
|
+
* @property {string} [__defaultFormatBrLine="PRE"] - Overrides the editor's default "brLine" element.
|
|
191
|
+
* @property {string} [formatBrLine="PRE"] - Specifies the editor's "brLine" elements. (e.g. "PRE").
|
|
192
|
+
* - (PRE | class="__se__format__br_line_xxx")
|
|
193
|
+
* - "brLine" elements is included in the "line" element.
|
|
194
|
+
* - "brLine" elements's line break is "BR" tag.
|
|
195
|
+
* ※ Entering the Enter key in the space on the last line ends "brLine" and appends "line".
|
|
196
|
+
* @property {string} [__defaultFormatClosureBrLine=""] - Overrides the editor's default "closureBrLine" element.
|
|
197
|
+
* @property {string} [formatClosureBrLine=""] - Specifies the editor's "closureBrLine" elements.
|
|
198
|
+
* - (class="__se__format__br_line__closure_xxx")
|
|
199
|
+
* - "closureBrLine" elements is included in the "brLine".
|
|
200
|
+
* - "closureBrLine" elements's line break is "BR" tag.
|
|
201
|
+
* - ※ You cannot exit this format with the Enter key or Backspace key.
|
|
202
|
+
* - ※ Use it only in special cases. ([ex] format of table cells)
|
|
203
|
+
* @property {string} [__defaultFormatBlock="BLOCKQUOTE|OL|UL|FIGCAPTION|TABLE|THEAD|TBODY|TR|CAPTION|DETAILS"] - Overrides the editor's default "block" element.
|
|
204
|
+
* @property {string} [formatBlock="BLOCKQUOTE|OL|UL|FIGCAPTION|TABLE|THEAD|TBODY|TR|CAPTION|DETAILS"] - Specifies the editor's "block" elements.
|
|
205
|
+
* - (BLOCKQUOTE, OL, UL, FIGCAPTION, TABLE, THEAD, TBODY, TR, TH, TD | class="__se__format__block_xxx")
|
|
206
|
+
* - "block" is wrap the "line" and "component"
|
|
207
|
+
* @property {string} [__defaultFormatClosureBlock="TH|TD"] - Overrides the editor's default "closureBlock" element.
|
|
208
|
+
* @property {string} [formatClosureBlock="TH|TD"] - Specifies the editor's "closureBlock" elements.
|
|
209
|
+
* - (TH, TD | class="__se__format__block_closure_xxx")
|
|
210
|
+
* - "closureBlock" elements is included in the "block".
|
|
211
|
+
* - "closureBlock" element is wrap the "line" and "component"
|
|
212
|
+
* - ※ You cannot exit this format with the Enter key or Backspace key.
|
|
213
|
+
* - ※ Use it only in special cases. ([ex] format of table cells)
|
|
214
|
+
* @property {string} [allowedEmptyTags=".se-component, pre, blockquote, hr, li, table, img, iframe, video, audio, canvas, details"] - Allowed empty tags.
|
|
215
|
+
* @property {number|string} [toolbar_width="auto"] - Toolbar width.
|
|
216
|
+
* @property {Element|string} [toolbar_container] - Container element for the toolbar.
|
|
217
|
+
* @property {number} [toolbar_sticky=0] - Enables sticky toolbar with optional offset.
|
|
218
|
+
* @property {boolean} [toolbar_hide=false] - Hides toolbar initially.
|
|
219
|
+
* @property {Object} [subToolbar] - Sub-toolbar configuration.
|
|
220
|
+
* @property {Array<Array<string>>} [subToolbar.buttonList] - List of Sub-toolbar buttons, grouped by sub-arrays.
|
|
221
|
+
* @property {"balloon"|"balloon-always"} [subToolbar.mode="balloon"] - Sub-toolbar mode: "balloon", "balloon-always".
|
|
222
|
+
* @property {number|string} [subToolbar.width="auto"] - Sub-toolbar width.
|
|
223
|
+
* @property {Element|string} [statusbar_container] - Container element for the status bar.
|
|
224
|
+
* @property {boolean} [shortcutsHint=true] - Displays shortcut hints in tooltips.
|
|
225
|
+
* @property {boolean} [shortcutsDisable=false] - Disables keyboard shortcuts.
|
|
226
|
+
* @property {Object<string, Array<string>>} [shortcuts] - Custom keyboard shortcuts.
|
|
227
|
+
* @property {number} [fullScreenOffset=0] - Offset applied when entering fullscreen mode.
|
|
228
|
+
* @property {string} [previewTemplate] - Custom template for preview mode.
|
|
229
|
+
* @property {string} [printTemplate] - Custom template for print mode.
|
|
230
|
+
* @property {boolean} [componentAutoSelect=false] - Enables automatic selection of inserted components.
|
|
231
|
+
* @property {string} [defaultUrlProtocol] - Default URL protocol for links.
|
|
232
|
+
* @property {string} [allUsedStyles] - Specifies additional styles to the list of allowed styles. Delimiter: "|" (e.g. "color|background-color").
|
|
233
|
+
* @property {Object<string, string>} [icons] - Overrides the default icons.
|
|
234
|
+
* @property {string} [freeCodeViewMode=false] - Enables free code view mode.
|
|
235
|
+
* @property {boolean} [__lineFormatFilter=true] - Line format filter configuration.
|
|
236
|
+
* @property {boolean} [__pluginRetainFilter=true] - Plugin retain filter configuration.
|
|
237
|
+
* @property {Array<string>} [__listCommonStyle=["fontSize", "color", "fontFamily", "fontWeight", "fontStyle"]] - Defines the list of styles that are applied directly to the `<li>` element
|
|
238
|
+
* - when a text style is applied to the entire list item.
|
|
239
|
+
* - For example, when changing the font size or color of a list item (`<li>`),
|
|
240
|
+
* - these styles will be applied to the `<li>` tag instead of wrapping the content inside additional tags.
|
|
241
|
+
* @property {Object<string, *>} [externalLibs] - External libraries like CodeMirror or MathJax.
|
|
242
|
+
* @property {Object<string, *>} [PluginOptions] - Dynamic plugin options, where the key is the plugin name and the value is its configuration.
|
|
243
|
+
*/
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* @typedef {EditorBaseOptions & EditorFrameOptions} EditorInitOptions
|
|
247
|
+
*/
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* @description Creates a new SunEditor instance with specified options.
|
|
251
|
+
* @param {Array<{target: Element, key: *, options: EditorFrameOptions}>} editorTargets - Target element or multi-root object.
|
|
252
|
+
* @param {EditorInitOptions} options - Configuration options for the editor.
|
|
253
|
+
* @returns {Object<string, *>} - SunEditor instance with context, options, and DOM elements.
|
|
254
|
+
*/
|
|
255
|
+
function Constructor(editorTargets, options) {
|
|
96
256
|
if (typeof options !== 'object') options = {};
|
|
97
257
|
|
|
98
258
|
/** --- Plugins ------------------------------------------------------------------------------------------ */
|
|
99
259
|
const plugins = {};
|
|
100
260
|
if (options.plugins) {
|
|
261
|
+
const excludedPlugins = options.excludedPlugins || [];
|
|
101
262
|
const originPlugins = options.plugins;
|
|
102
|
-
const pluginsValues = Array.isArray(originPlugins.
|
|
103
|
-
? originPlugins
|
|
104
|
-
: Object.keys(originPlugins).map(function (name) {
|
|
105
|
-
return originPlugins[name];
|
|
106
|
-
});
|
|
263
|
+
const pluginsValues = (Array.isArray(originPlugins) ? originPlugins : Object.keys(originPlugins)).filter((name) => !excludedPlugins.includes(name)).map((name) => originPlugins[name]);
|
|
107
264
|
|
|
108
265
|
for (let i = 0, len = pluginsValues.length, p; i < len; i++) {
|
|
109
266
|
p = pluginsValues[i].default || pluginsValues[i];
|
|
@@ -112,39 +269,41 @@ const Constructor = function (editorTargets, options) {
|
|
|
112
269
|
}
|
|
113
270
|
|
|
114
271
|
/** --- options --------------------------------------------------------------- */
|
|
115
|
-
const optionMap = InitOptions(options, editorTargets);
|
|
272
|
+
const optionMap = InitOptions(options, editorTargets, plugins);
|
|
116
273
|
const o = optionMap.o;
|
|
117
274
|
const icons = optionMap.i;
|
|
118
275
|
const lang = optionMap.l;
|
|
119
|
-
const loadingBox =
|
|
276
|
+
const loadingBox = dom.utils.createElement('DIV', { class: 'se-loading-box sun-editor-common' }, '<div class="se-loading-effect"></div>');
|
|
120
277
|
|
|
121
278
|
/** --- carrier wrapper --------------------------------------------------------------- */
|
|
122
|
-
const editor_carrier_wrapper =
|
|
279
|
+
const editor_carrier_wrapper = dom.utils.createElement('DIV', { class: 'sun-editor sun-editor-carrier-wrapper sun-editor-common' + o.get('_themeClass') + (o.get('_rtl') ? ' se-rtl' : '') });
|
|
123
280
|
// menuTray
|
|
124
|
-
const menuTray =
|
|
281
|
+
const menuTray = dom.utils.createElement('DIV', { class: 'se-menu-tray' });
|
|
125
282
|
editor_carrier_wrapper.appendChild(menuTray);
|
|
126
283
|
// focus temp element
|
|
127
|
-
const focusTemp =
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
284
|
+
const focusTemp = /** @type {HTMLInputElement} */ (
|
|
285
|
+
dom.utils.createElement('INPUT', {
|
|
286
|
+
class: '__se__focus__temp__',
|
|
287
|
+
style: 'position: fixed !important; top: -10000px !important; left: -10000px !important; display: block !important; width: 0 !important; height: 0 !important; margin: 0 !important; padding: 0 !important;'
|
|
288
|
+
})
|
|
289
|
+
);
|
|
131
290
|
focusTemp.tabIndex = 0;
|
|
132
291
|
editor_carrier_wrapper.appendChild(focusTemp);
|
|
133
292
|
|
|
134
293
|
// modal
|
|
135
|
-
const modal =
|
|
136
|
-
const modal_back =
|
|
137
|
-
const modal_inner =
|
|
294
|
+
const modal = dom.utils.createElement('DIV', { class: 'se-modal sun-editor-common' });
|
|
295
|
+
const modal_back = dom.utils.createElement('DIV', { class: 'se-modal-back', style: 'display: none;' });
|
|
296
|
+
const modal_inner = dom.utils.createElement('DIV', { class: 'se-modal-inner', style: 'display: none;' });
|
|
138
297
|
modal.appendChild(modal_back);
|
|
139
298
|
modal.appendChild(modal_inner);
|
|
140
299
|
editor_carrier_wrapper.appendChild(modal);
|
|
141
300
|
|
|
142
301
|
// loding box, resizing back
|
|
143
|
-
editor_carrier_wrapper.appendChild(
|
|
302
|
+
editor_carrier_wrapper.appendChild(dom.utils.createElement('DIV', { class: 'se-back-wrapper' }));
|
|
144
303
|
editor_carrier_wrapper.appendChild(loadingBox.cloneNode(true));
|
|
145
304
|
|
|
146
305
|
// drag cursor
|
|
147
|
-
const dragCursor =
|
|
306
|
+
const dragCursor = dom.utils.createElement('DIV', { class: 'se-drag-cursor' });
|
|
148
307
|
editor_carrier_wrapper.appendChild(dragCursor);
|
|
149
308
|
|
|
150
309
|
// set carrier wrapper
|
|
@@ -163,7 +322,7 @@ const Constructor = function (editorTargets, options) {
|
|
|
163
322
|
} else if (/balloon/i.test(o.get('mode'))) {
|
|
164
323
|
toolbar.className += ' se-toolbar-balloon';
|
|
165
324
|
toolbar.style.width = o.get('toolbar_width');
|
|
166
|
-
toolbar.appendChild(
|
|
325
|
+
toolbar.appendChild(dom.utils.createElement('DIV', { class: 'se-arrow' }));
|
|
167
326
|
}
|
|
168
327
|
|
|
169
328
|
/** --- subToolbar --------------------------------------------------------------- */
|
|
@@ -174,7 +333,7 @@ const Constructor = function (editorTargets, options) {
|
|
|
174
333
|
// subbar mode must be balloon-*
|
|
175
334
|
subbar.className += ' se-toolbar-balloon se-toolbar-sub';
|
|
176
335
|
subbar.style.width = o.get('toolbar.sub_width');
|
|
177
|
-
subbar.appendChild(
|
|
336
|
+
subbar.appendChild(dom.utils.createElement('DIV', { class: 'se-arrow' }));
|
|
178
337
|
}
|
|
179
338
|
|
|
180
339
|
/** frame - root set - start -------------------------------------------------------------- */
|
|
@@ -185,12 +344,12 @@ const Constructor = function (editorTargets, options) {
|
|
|
185
344
|
let default_status_bar = null;
|
|
186
345
|
for (let i = 0, len = editorTargets.length; i < len; i++) {
|
|
187
346
|
const editTarget = editorTargets[i];
|
|
188
|
-
const to = editTarget.
|
|
189
|
-
const top_div =
|
|
190
|
-
const container =
|
|
191
|
-
const editor_div =
|
|
347
|
+
const to = optionMap.frameMap.get(editTarget.key);
|
|
348
|
+
const top_div = dom.utils.createElement('DIV', { class: 'sun-editor' + o.get('_themeClass') + (to.get('_rtl') ? ' se-rtl' : '') });
|
|
349
|
+
const container = dom.utils.createElement('DIV', { class: 'se-container' });
|
|
350
|
+
const editor_div = dom.utils.createElement('DIV', { class: 'se-wrapper' + (o.get('type') === 'document' ? ' se-type-document' : '') });
|
|
192
351
|
|
|
193
|
-
container.appendChild(
|
|
352
|
+
container.appendChild(dom.utils.createElement('DIV', { class: 'se-toolbar-shadow' }));
|
|
194
353
|
|
|
195
354
|
// init element
|
|
196
355
|
const initElements = _initTargetElements(editTarget.key, o, top_div, to);
|
|
@@ -201,22 +360,22 @@ const Constructor = function (editorTargets, options) {
|
|
|
201
360
|
let textarea = initElements.codeView;
|
|
202
361
|
|
|
203
362
|
// line breaker
|
|
204
|
-
const line_breaker_t =
|
|
205
|
-
const line_breaker_b =
|
|
363
|
+
const line_breaker_t = dom.utils.createElement('DIV', { class: 'se-line-breaker-component se-line-breaker-component-t', title: lang.insertLine }, icons.line_break);
|
|
364
|
+
const line_breaker_b = dom.utils.createElement('DIV', { class: 'se-line-breaker-component se-line-breaker-component-b', title: lang.insertLine }, icons.line_break);
|
|
206
365
|
|
|
207
366
|
editor_div.appendChild(line_breaker_t);
|
|
208
367
|
editor_div.appendChild(line_breaker_b);
|
|
209
368
|
|
|
210
369
|
// append container
|
|
211
370
|
if (placeholder_span) editor_div.appendChild(placeholder_span);
|
|
212
|
-
container.appendChild(
|
|
371
|
+
container.appendChild(dom.utils.createElement('DIV', { class: 'se-toolbar-sticky-dummy' }));
|
|
213
372
|
container.appendChild(editor_div);
|
|
214
373
|
|
|
215
374
|
// statusbar
|
|
216
375
|
if (statusbar) {
|
|
217
376
|
if (statusbarContainer) {
|
|
218
377
|
if (!default_status_bar) {
|
|
219
|
-
statusbarContainer.appendChild(
|
|
378
|
+
statusbarContainer.appendChild(dom.utils.createElement('DIV', { class: 'sun-editor' + o.get('_themeClass') }, statusbar));
|
|
220
379
|
default_status_bar = statusbar;
|
|
221
380
|
}
|
|
222
381
|
} else {
|
|
@@ -231,7 +390,7 @@ const Constructor = function (editorTargets, options) {
|
|
|
231
390
|
const key = editTarget.key || null;
|
|
232
391
|
|
|
233
392
|
// code view - wrapper
|
|
234
|
-
const codeWrapper =
|
|
393
|
+
const codeWrapper = dom.utils.createElement('DIV', { class: 'se-code-wrapper' }, textarea);
|
|
235
394
|
codeWrapper.style.setProperty('display', 'none', 'important');
|
|
236
395
|
editor_div.appendChild(codeWrapper);
|
|
237
396
|
|
|
@@ -240,29 +399,46 @@ const Constructor = function (editorTargets, options) {
|
|
|
240
399
|
// not used code mirror
|
|
241
400
|
if (textarea === codeMirrorEl) {
|
|
242
401
|
// add line nubers
|
|
243
|
-
const codeNumbers =
|
|
402
|
+
const codeNumbers = dom.utils.createElement('TEXTAREA', { class: 'se-code-view-line', readonly: 'true' }, null);
|
|
244
403
|
codeWrapper.insertBefore(codeNumbers, textarea);
|
|
245
404
|
} else {
|
|
246
405
|
textarea = codeMirrorEl;
|
|
247
406
|
}
|
|
248
407
|
|
|
408
|
+
// document type
|
|
409
|
+
const documentTypeInner = { inner: null, page: null, pageMirror: null };
|
|
410
|
+
if (o.get('type-options').includes('header')) {
|
|
411
|
+
documentTypeInner.inner = dom.utils.createElement('DIV', { class: 'se-document-lines', style: `height: ${to.get('height')};` }, '<div class="se-document-lines-inner"></div>');
|
|
412
|
+
}
|
|
413
|
+
if (o.get('type-options').includes('page')) {
|
|
414
|
+
documentTypeInner.page = dom.utils.createElement('DIV', { class: 'se-document-page' }, null);
|
|
415
|
+
documentTypeInner.pageMirror = dom.utils.createElement(
|
|
416
|
+
'DIV',
|
|
417
|
+
{
|
|
418
|
+
class: 'sun-editor-editable se-document-page-mirror-a4',
|
|
419
|
+
style: `position: absolute; width: 21cm; columns: 21cm; border: 0; overflow: hidden; height: auto; top: -10000px; left: -10000px;`
|
|
420
|
+
},
|
|
421
|
+
null
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
|
|
249
425
|
// set container
|
|
250
426
|
top_div.appendChild(container);
|
|
251
427
|
rootKeys.push(key);
|
|
252
|
-
frameRoots.set(key, CreateFrameContext(editTarget, top_div, wysiwyg_div, codeWrapper, textarea, default_status_bar || statusbar, key));
|
|
428
|
+
frameRoots.set(key, CreateFrameContext({ target: editTarget.target, key: editTarget.key, options: to }, top_div, wysiwyg_div, codeWrapper, textarea, default_status_bar || statusbar, documentTypeInner, key));
|
|
253
429
|
}
|
|
254
430
|
/** frame - root set - end -------------------------------------------------------------- */
|
|
255
431
|
|
|
256
432
|
// toolbar container
|
|
257
433
|
const toolbar_container = o.get('toolbar_container');
|
|
258
434
|
if (toolbar_container) {
|
|
259
|
-
const top_div =
|
|
260
|
-
const container =
|
|
435
|
+
const top_div = dom.utils.createElement('DIV', { class: 'sun-editor' + o.get('_themeClass') + (o.get('_rtl') ? ' se-rtl' : '') });
|
|
436
|
+
const container = dom.utils.createElement('DIV', { class: 'se-container' });
|
|
261
437
|
container.appendChild(toolbar);
|
|
262
438
|
if (subbar) container.appendChild(subbar);
|
|
263
439
|
top_div.appendChild(container);
|
|
264
440
|
toolbar_container.appendChild(top_div);
|
|
265
|
-
toolbar_container.appendChild(
|
|
441
|
+
toolbar_container.appendChild(dom.utils.createElement('DIV', { class: 'se-toolbar-sticky-dummy' }));
|
|
266
442
|
} else {
|
|
267
443
|
const rootContainer = frameRoots.get(rootId).get('container');
|
|
268
444
|
rootContainer.insertBefore(toolbar, rootContainer.firstElementChild);
|
|
@@ -285,30 +461,74 @@ const Constructor = function (editorTargets, options) {
|
|
|
285
461
|
pluginCallButtons_sub: sub_main ? sub_main.pluginCallButtons : [],
|
|
286
462
|
responsiveButtons_sub: sub_main ? sub_main.responsiveButtons : []
|
|
287
463
|
};
|
|
288
|
-
}
|
|
464
|
+
}
|
|
289
465
|
|
|
290
466
|
/**
|
|
291
467
|
* @description Create shortcuts desc span.
|
|
292
468
|
* @param {string} command Command string
|
|
293
|
-
* @param {Array
|
|
294
|
-
* @param {Element} button Command button element
|
|
295
|
-
* @param {Map} keyMap Map to store shortcut key info
|
|
469
|
+
* @param {Array<string>} values options.shortcuts[command]
|
|
470
|
+
* @param {Element|null} button Command button element
|
|
471
|
+
* @param {Map<string, *>} keyMap Map to store shortcut key info
|
|
296
472
|
* @param {Array} rc "_reverseCommandArray" option
|
|
297
473
|
* @param {Array} reverseKeys Reverse key array
|
|
298
474
|
*/
|
|
299
475
|
export function CreateShortcuts(command, button, values, keyMap, rc, reverseKeys) {
|
|
300
476
|
if (!values || values.length < 2) return;
|
|
301
|
-
const tooptip = button
|
|
477
|
+
const tooptip = button?.querySelector('.se-tooltip-text');
|
|
478
|
+
|
|
479
|
+
for (let i = 0, a, v, c, s, edge, space, enter, textTrigger, plugin, method, t, k, r, _i; i < values.length; i += 2 + _i) {
|
|
480
|
+
_i = 0;
|
|
481
|
+
a = values[i].split('+');
|
|
482
|
+
|
|
483
|
+
plugin = null;
|
|
484
|
+
method = a.at(-1).trim?.();
|
|
485
|
+
if (method.startsWith('~')) {
|
|
486
|
+
plugin = command;
|
|
487
|
+
method = a.pop().trim().substring(1);
|
|
488
|
+
} else if (method.startsWith('p~')) {
|
|
489
|
+
const a_ = a.pop().trim().substring(2).split('.');
|
|
490
|
+
plugin = a_[0];
|
|
491
|
+
method = a_[1];
|
|
492
|
+
} else if (method.startsWith('$')) {
|
|
493
|
+
_i = 1;
|
|
494
|
+
method = values[i + 2];
|
|
495
|
+
} else {
|
|
496
|
+
method = '';
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
c = s = edge = space = enter = textTrigger = v = null;
|
|
500
|
+
for (const a_ of a) {
|
|
501
|
+
switch (a_.trim()) {
|
|
502
|
+
case 'c':
|
|
503
|
+
c = true;
|
|
504
|
+
break;
|
|
505
|
+
case '!':
|
|
506
|
+
edge = true;
|
|
507
|
+
break;
|
|
508
|
+
case 's':
|
|
509
|
+
s = true;
|
|
510
|
+
break;
|
|
511
|
+
case '_':
|
|
512
|
+
space = true;
|
|
513
|
+
break;
|
|
514
|
+
case '=':
|
|
515
|
+
textTrigger = true;
|
|
516
|
+
break;
|
|
517
|
+
case '/':
|
|
518
|
+
enter = true;
|
|
519
|
+
break;
|
|
520
|
+
default:
|
|
521
|
+
v = a_;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
302
524
|
|
|
303
|
-
|
|
304
|
-
v = values[i];
|
|
305
|
-
s = /^s/i.test(v);
|
|
306
|
-
k = numbers.get(v) + (s ? 1000 : 0);
|
|
525
|
+
k = c ? v + (s ? '1000' : '') : v;
|
|
307
526
|
if (!keyMap.has(k)) {
|
|
308
527
|
r = rc.indexOf(command);
|
|
309
528
|
r = r === -1 ? '' : numbers.isOdd(r) ? rc[r + 1] : rc[r - 1];
|
|
310
529
|
if (r) reverseKeys.push(k);
|
|
311
|
-
|
|
530
|
+
|
|
531
|
+
keyMap.set(k, { c, s, edge, space, enter, textTrigger, plugin, command, method, r, type: button?.getAttribute('data-type'), button, key: k });
|
|
312
532
|
}
|
|
313
533
|
|
|
314
534
|
if (!(t = values[i + 1])) continue;
|
|
@@ -317,13 +537,15 @@ export function CreateShortcuts(command, button, values, keyMap, rc, reverseKeys
|
|
|
317
537
|
}
|
|
318
538
|
|
|
319
539
|
function _addTooltip(tooptipBtn, shift, shortcut) {
|
|
320
|
-
tooptipBtn.appendChild(
|
|
540
|
+
tooptipBtn.appendChild(dom.utils.createElement('SPAN', { class: 'se-shortcut' }, env.cmdIcon + (shift ? env.shiftIcon : '') + '+<span class="se-shortcut-key">' + shortcut + '</span>'));
|
|
321
541
|
}
|
|
322
542
|
|
|
323
543
|
/**
|
|
544
|
+
* @private
|
|
324
545
|
* @description Returns a new object with merge "a" and "b"
|
|
325
|
-
* @param {Object}
|
|
326
|
-
* @
|
|
546
|
+
* @param {Object<*, *>} a object
|
|
547
|
+
* @param {Object<*, *>} b object
|
|
548
|
+
* @returns {Object<*, *>} new object
|
|
327
549
|
*/
|
|
328
550
|
function _mergeObject(a, b) {
|
|
329
551
|
return [a, b].reduce((_default, _new) => {
|
|
@@ -336,11 +558,20 @@ function _mergeObject(a, b) {
|
|
|
336
558
|
|
|
337
559
|
/**
|
|
338
560
|
* @description Initialize options
|
|
339
|
-
* @param {
|
|
340
|
-
* @param {Array
|
|
341
|
-
* @
|
|
561
|
+
* @param {EditorInitOptions} options Configuration options for the editor.
|
|
562
|
+
* @param {Array<{target: Element, key: *, options: EditorFrameOptions}>} editorTargets Target textarea
|
|
563
|
+
* @param {Object<string, *>} plugins Plugins object
|
|
564
|
+
* @returns {{o: Map<string, *>, i: Object<string, string>, l: Object<string, string>, v: string, buttons: Array<string[]|string>, subButtons: Array<string[]|string>, statusbarContainer: Element|null, frameMap: Map<*, *>}}
|
|
565
|
+
* - o: options
|
|
566
|
+
* - i: icons
|
|
567
|
+
* - l: lang
|
|
568
|
+
* - v: value
|
|
569
|
+
* - buttons: Toolbar button list
|
|
570
|
+
* - subButtons: Sub-Toolbar button list
|
|
571
|
+
* - statusbarContainer: statusbar container
|
|
572
|
+
* - frameMap: converted options map
|
|
342
573
|
*/
|
|
343
|
-
export function InitOptions(options, editorTargets) {
|
|
574
|
+
export function InitOptions(options, editorTargets, plugins) {
|
|
344
575
|
const buttonList = options.buttonList || DEFAULT_BUTTON_LIST;
|
|
345
576
|
const o = new Map();
|
|
346
577
|
|
|
@@ -349,7 +580,11 @@ export function InitOptions(options, editorTargets) {
|
|
|
349
580
|
if (!options.toolbar_container && !/inline|balloon/i.test(options.mode)) throw Error('[SUNEDITOR.create.fail] In multi root, The "mode" option cannot be "classic" without using the "toolbar_container" option.');
|
|
350
581
|
}
|
|
351
582
|
|
|
583
|
+
// migration data-.+
|
|
584
|
+
o.set('v2Migration', !!options.v2Migration);
|
|
585
|
+
|
|
352
586
|
/** Base */
|
|
587
|
+
o.set('buttons', new Set(buttonList.toString().split(',')));
|
|
353
588
|
const modeValue = options.strictMode !== false;
|
|
354
589
|
o.set('strictMode', {
|
|
355
590
|
tagFilter: modeValue,
|
|
@@ -358,13 +593,32 @@ export function InitOptions(options, editorTargets) {
|
|
|
358
593
|
styleNodeFilter: modeValue,
|
|
359
594
|
attrFilter: modeValue,
|
|
360
595
|
styleFilter: modeValue,
|
|
361
|
-
...options.strictMode
|
|
596
|
+
...(typeof options.strictMode === 'boolean' ? {} : options.strictMode)
|
|
362
597
|
});
|
|
598
|
+
o.set('freeCodeViewMode', !!options.freeCodeViewMode);
|
|
599
|
+
o.set('__lineFormatFilter', options.__lineFormatFilter ?? true);
|
|
600
|
+
o.set('__pluginRetainFilter', options.__pluginRetainFilter ?? true);
|
|
363
601
|
o.set('mode', options.mode || 'classic'); // classic, inline, balloon, balloon-always
|
|
602
|
+
o.set('type', options.type?.split(':')[0] || ''); // document:header,page
|
|
603
|
+
o.set('theme', options.theme || '');
|
|
604
|
+
o.set('_themeClass', options.theme ? ` se-theme-${options.theme}` : '');
|
|
605
|
+
o.set('type-options', options.type?.split(':')[1] || '');
|
|
364
606
|
o.set('externalLibs', options.externalLibs || {});
|
|
365
|
-
o.set('keepStyleOnDelete', !!options.keepStyleOnDelete);
|
|
366
607
|
o.set('fontSizeUnits', Array.isArray(options.fontSizeUnits) && options.fontSizeUnits.length > 0 ? options.fontSizeUnits.map((v) => v.toLowerCase()) : DEFAULT_SIZE_UNITS);
|
|
367
608
|
o.set('allowedClassName', new RegExp(`${options.allowedClassName && typeof options.allowedClassName === 'string' ? options.allowedClassName + '|' : ''}${DEFAULT_CLASS_NAME}`));
|
|
609
|
+
o.set('closeModalOutsideClick', !!options.closeModalOutsideClick);
|
|
610
|
+
|
|
611
|
+
// format
|
|
612
|
+
o.set('copyFormatKeepOn', !!options.copyFormatKeepOn);
|
|
613
|
+
o.set('syncTabIndent', options.syncTabIndent ?? true);
|
|
614
|
+
|
|
615
|
+
// auto convert on paste
|
|
616
|
+
o.set('autoLinkify', options.autoLinkify ?? !!plugins.link);
|
|
617
|
+
o.set('autoStyleify', Array.isArray(options.autoStyleify) ? options.autoStyleify : ['bold', 'underline', 'italic', 'strike']);
|
|
618
|
+
|
|
619
|
+
// scroll options
|
|
620
|
+
o.set('scrollToOptions', { behavior: 'auto', block: 'nearest', ...options.scrollToOptions });
|
|
621
|
+
o.set('componentScrollToOptions', { behavior: 'smooth', block: 'center', ...options.componentScrollToOptions });
|
|
368
622
|
|
|
369
623
|
let retainStyleMode = options.retainStyleMode;
|
|
370
624
|
if (typeof retainStyleMode === 'string' && !RETAIN_STYLE_MODE.includes(retainStyleMode)) {
|
|
@@ -448,6 +702,7 @@ export function InitOptions(options, editorTargets) {
|
|
|
448
702
|
// text direction
|
|
449
703
|
o.set('textDirection', typeof options.textDirection !== 'string' ? 'ltr' : options.textDirection);
|
|
450
704
|
o.set('_rtl', o.get('textDirection') === 'rtl');
|
|
705
|
+
// An array of key codes generated with the reverseButtons option, used to reverse the action for a specific key combination.
|
|
451
706
|
o.set('reverseCommands', ['indent-outdent'].concat(options.reverseButtons || []));
|
|
452
707
|
o.set('_reverseCommandArray', ('-' + o.get('reverseCommands').join('-')).split('-'));
|
|
453
708
|
if (numbers.isEven(o.get('_reverseCommandArray').length)) {
|
|
@@ -456,16 +711,17 @@ export function InitOptions(options, editorTargets) {
|
|
|
456
711
|
|
|
457
712
|
// etc
|
|
458
713
|
o.set('historyStackDelayTime', typeof options.historyStackDelayTime === 'number' ? options.historyStackDelayTime : 400);
|
|
459
|
-
o.set('_editableClass', 'sun-editor-editable' + (o.get('_rtl') ? ' se-rtl' : ''));
|
|
714
|
+
o.set('_editableClass', 'sun-editor-editable' + o.get('_themeClass') + (o.get('_rtl') ? ' se-rtl' : '') + (o.get('type') === 'document' ? ' se-type-document-editable' : ''));
|
|
460
715
|
o.set('lineAttrReset', ['id'].concat(options.lineAttrReset && typeof options.lineAttrReset === 'string' ? options.lineAttrReset.toLowerCase().split('|') : []));
|
|
461
|
-
o.set('printClass', typeof options.printClass === 'string' ? options.printClass : null);
|
|
716
|
+
o.set('printClass', typeof options.printClass === 'string' ? options.printClass + ' ' + o.get('_editableClass') : null);
|
|
462
717
|
|
|
463
718
|
/** whitelist, blacklist */
|
|
464
719
|
// default line
|
|
465
720
|
o.set('defaultLine', typeof options.defaultLine === 'string' && options.defaultLine.length > 0 ? options.defaultLine : 'p');
|
|
466
721
|
// element
|
|
467
722
|
const elw = (typeof options.elementWhitelist === 'string' ? options.elementWhitelist : '').toLowerCase();
|
|
468
|
-
o.
|
|
723
|
+
const mjxEls = o.get('externalLibs').mathjax ? DEFAULT_CLASS_MJX + '|' : '';
|
|
724
|
+
o.set('elementWhitelist', elw + (elw ? '|' : '') + mjxEls + o.get('_allowedExtraTag'));
|
|
469
725
|
const elb = _createBlacklist((typeof options.elementBlacklist === 'string' ? options.elementBlacklist : '').toLowerCase(), o.get('defaultLine'));
|
|
470
726
|
o.set('elementBlacklist', elb + (elb ? '|' : '') + o.get('_disallowedExtraTag'));
|
|
471
727
|
// attribute
|
|
@@ -519,6 +775,8 @@ export function InitOptions(options, editorTargets) {
|
|
|
519
775
|
)
|
|
520
776
|
);
|
|
521
777
|
|
|
778
|
+
o.set('allowedEmptyTags', DEFAULT_ALLOWED_EMPTY_NODE_LIST + (options.allowedEmptyTags ? ', ' + options.allowedEmptyTags : ''));
|
|
779
|
+
|
|
522
780
|
/** __defaults */
|
|
523
781
|
o.set('__defaultElementWhitelist', REQUIRED_ELEMENT_WHITELIST + '|' + (typeof options.__defaultElementWhitelist === 'string' ? options.__defaultElementWhitelist : DEFAULT_ELEMENT_WHITELIST).toLowerCase());
|
|
524
782
|
o.set('__defaultAttributeWhitelist', (typeof options.__defaultAttributeWhitelist === 'string' ? options.__defaultAttributeWhitelist : DEFAULT_ATTRIBUTE_WHITELIST).toLowerCase());
|
|
@@ -528,7 +786,7 @@ export function InitOptions(options, editorTargets) {
|
|
|
528
786
|
/** Toolbar */
|
|
529
787
|
o.set('toolbar_width', options.toolbar_width ? (numbers.is(options.toolbar_width) ? options.toolbar_width + 'px' : options.toolbar_width) : 'auto');
|
|
530
788
|
o.set('toolbar_container', options.toolbar_container && !/inline/i.test(o.get('mode')) ? (typeof options.toolbar_container === 'string' ? _d.querySelector(options.toolbar_container) : options.toolbar_container) : null);
|
|
531
|
-
o.set('toolbar_sticky', /balloon/i.test(o.get('mode')) ? -1 : options.toolbar_sticky === undefined ? 0 :
|
|
789
|
+
o.set('toolbar_sticky', /balloon/i.test(o.get('mode')) ? -1 : options.toolbar_sticky === undefined ? 0 : numbers.is(options.toolbar_sticky) ? numbers.get(options.toolbar_sticky, 0) : -1);
|
|
532
790
|
o.set('toolbar_hide', !!options.toolbar_hide);
|
|
533
791
|
|
|
534
792
|
/** subToolbar */
|
|
@@ -541,12 +799,14 @@ export function InitOptions(options, editorTargets) {
|
|
|
541
799
|
o.set('_subMode', subbar.mode || 'balloon');
|
|
542
800
|
o.set('toolbar.sub_width', subbar.width ? (numbers.is(subbar.width) ? subbar.width + 'px' : subbar.width) : 'auto');
|
|
543
801
|
subButtons = o.get('_rtl') ? subbar.buttonList.reverse() : subbar.buttonList;
|
|
802
|
+
o.set('buttons_sub', new Set(subButtons.toString().split(',')));
|
|
544
803
|
}
|
|
545
804
|
}
|
|
546
805
|
|
|
547
806
|
/** root options */
|
|
807
|
+
const frameMap = new Map();
|
|
548
808
|
for (let i = 0, len = editorTargets.length; i < len; i++) {
|
|
549
|
-
|
|
809
|
+
frameMap.set(editorTargets[i].key, InitFrameOptions(editorTargets[i].options || {}, options));
|
|
550
810
|
}
|
|
551
811
|
|
|
552
812
|
/** Key actions */
|
|
@@ -557,20 +817,25 @@ export function InitOptions(options, editorTargets) {
|
|
|
557
817
|
: [
|
|
558
818
|
{
|
|
559
819
|
// default command
|
|
560
|
-
selectAll: ['
|
|
561
|
-
bold: ['
|
|
562
|
-
strike: ['
|
|
563
|
-
underline: ['
|
|
564
|
-
italic: ['
|
|
565
|
-
redo: ['
|
|
566
|
-
undo: ['
|
|
567
|
-
indent: ['
|
|
568
|
-
outdent: ['
|
|
569
|
-
|
|
570
|
-
sub: ['s187', '='],
|
|
571
|
-
save: ['83', 'S'],
|
|
820
|
+
selectAll: ['c+KeyA', 'A'],
|
|
821
|
+
bold: ['c+KeyB', 'B'],
|
|
822
|
+
strike: ['c+s+KeyS', 'S'],
|
|
823
|
+
underline: ['c+KeyU', 'U'],
|
|
824
|
+
italic: ['c+KeyI', 'I'],
|
|
825
|
+
redo: ['c+KeyY', 'Y', 'c+s+KeyZ', 'Z'],
|
|
826
|
+
undo: ['c+KeyZ', 'Z'],
|
|
827
|
+
indent: ['c+BracketRight', ']'],
|
|
828
|
+
outdent: ['c+BracketLeft', '['],
|
|
829
|
+
save: ['c+KeyS', 'S'],
|
|
572
830
|
// plugins
|
|
573
|
-
link: ['
|
|
831
|
+
link: ['c+KeyK', 'K'],
|
|
832
|
+
hr: ['!+---+=+~shortcut', ''],
|
|
833
|
+
list_numbered: ['!+1.+_+~shortcut', ''],
|
|
834
|
+
list_bulleted: ['!+*.+_+~shortcut', ''],
|
|
835
|
+
// custom
|
|
836
|
+
_h1: ['c+s+Digit1+p~formatBlock.createHeader', ''],
|
|
837
|
+
_h2: ['c+s+Digit2+p~formatBlock.createHeader', ''],
|
|
838
|
+
_h3: ['c+s+Digit3+p~formatBlock.createHeader', '']
|
|
574
839
|
},
|
|
575
840
|
options.shortcuts || {}
|
|
576
841
|
].reduce((_default, _new) => {
|
|
@@ -582,12 +847,12 @@ export function InitOptions(options, editorTargets) {
|
|
|
582
847
|
o.set('shortcuts', shortcuts);
|
|
583
848
|
|
|
584
849
|
/** View */
|
|
585
|
-
o.set('fullScreenOffset', options.fullScreenOffset === undefined ? 0 :
|
|
850
|
+
o.set('fullScreenOffset', options.fullScreenOffset === undefined ? 0 : numbers.is(options.fullScreenOffset) ? numbers.get(options.fullScreenOffset, 0) : 0);
|
|
586
851
|
o.set('previewTemplate', typeof options.previewTemplate === 'string' ? options.previewTemplate : null);
|
|
587
852
|
o.set('printTemplate', typeof options.printTemplate === 'string' ? options.printTemplate : null);
|
|
588
853
|
|
|
589
854
|
/** --- Media select */
|
|
590
|
-
o.set('
|
|
855
|
+
o.set('componentAutoSelect', options.componentAutoSelect === undefined ? false : !!options.componentAutoSelect);
|
|
591
856
|
|
|
592
857
|
/** --- Url input protocol */
|
|
593
858
|
o.set('defaultUrlProtocol', typeof options.defaultUrlProtocol === 'string' ? options.defaultUrlProtocol : null);
|
|
@@ -651,42 +916,49 @@ export function InitOptions(options, editorTargets) {
|
|
|
651
916
|
return {
|
|
652
917
|
o: o,
|
|
653
918
|
i: icons,
|
|
654
|
-
l: options.lang || _defaultLang,
|
|
919
|
+
l: /** @type {Object<string, string>} */ (options.lang || _defaultLang),
|
|
655
920
|
v: (options.value = typeof options.value === 'string' ? options.value : null),
|
|
656
921
|
buttons: o.get('_rtl') ? buttonList.reverse() : buttonList,
|
|
657
922
|
subButtons: subButtons,
|
|
658
|
-
statusbarContainer: typeof options.statusbar_container === 'string' ? _d.querySelector(options.statusbar_container) : options.statusbar_container
|
|
923
|
+
statusbarContainer: typeof options.statusbar_container === 'string' ? _d.querySelector(options.statusbar_container) : options.statusbar_container,
|
|
924
|
+
frameMap: frameMap
|
|
659
925
|
};
|
|
660
926
|
}
|
|
661
927
|
|
|
928
|
+
/**
|
|
929
|
+
* @description Create a context object for the editor frame.
|
|
930
|
+
* @param {Map<string, *>} targetOptions - editor.frameOptions
|
|
931
|
+
* @param {HTMLElement} statusbar - statusbar element
|
|
932
|
+
* @returns {{statusbar: HTMLElement, navigation: HTMLElement, charWrapper: HTMLElement, charCounter: HTMLElement}}
|
|
933
|
+
*/
|
|
662
934
|
export function CreateStatusbar(targetOptions, statusbar) {
|
|
663
935
|
let navigation = null;
|
|
664
936
|
let charWrapper = null;
|
|
665
937
|
let charCounter = null;
|
|
666
938
|
|
|
667
939
|
if (targetOptions.get('statusbar')) {
|
|
668
|
-
statusbar = statusbar ||
|
|
940
|
+
statusbar = statusbar || dom.utils.createElement('DIV', { class: 'se-status-bar sun-editor-common' });
|
|
669
941
|
|
|
670
942
|
/** navigation */
|
|
671
|
-
navigation = statusbar.querySelector('.se-navigation') ||
|
|
943
|
+
navigation = statusbar.querySelector('.se-navigation') || dom.utils.createElement('DIV', { class: 'se-navigation sun-editor-common' });
|
|
672
944
|
statusbar.appendChild(navigation);
|
|
673
945
|
|
|
674
946
|
/** char counter */
|
|
675
947
|
if (targetOptions.get('charCounter')) {
|
|
676
|
-
charWrapper = statusbar.querySelector('.se-char-counter-wrapper') ||
|
|
948
|
+
charWrapper = statusbar.querySelector('.se-char-counter-wrapper') || dom.utils.createElement('DIV', { class: 'se-char-counter-wrapper' });
|
|
677
949
|
|
|
678
950
|
if (targetOptions.get('charCounter_label')) {
|
|
679
|
-
const charLabel = charWrapper.querySelector('.se-char-label') ||
|
|
951
|
+
const charLabel = charWrapper.querySelector('.se-char-label') || dom.utils.createElement('SPAN', { class: 'se-char-label' });
|
|
680
952
|
charLabel.textContent = targetOptions.get('charCounter_label');
|
|
681
953
|
charWrapper.appendChild(charLabel);
|
|
682
954
|
}
|
|
683
955
|
|
|
684
|
-
charCounter = charWrapper.querySelector('.se-char-counter') ||
|
|
956
|
+
charCounter = charWrapper.querySelector('.se-char-counter') || dom.utils.createElement('SPAN', { class: 'se-char-counter' });
|
|
685
957
|
charCounter.textContent = '0';
|
|
686
958
|
charWrapper.appendChild(charCounter);
|
|
687
959
|
|
|
688
960
|
if (targetOptions.get('charCounter_max') > 0) {
|
|
689
|
-
const char_max = charWrapper.querySelector('.se-char-max') ||
|
|
961
|
+
const char_max = charWrapper.querySelector('.se-char-max') || dom.utils.createElement('SPAN', { class: 'se-char-max' });
|
|
690
962
|
char_max.textContent = ' / ' + targetOptions.get('charCounter_max');
|
|
691
963
|
charWrapper.appendChild(char_max);
|
|
692
964
|
}
|
|
@@ -697,13 +969,21 @@ export function CreateStatusbar(targetOptions, statusbar) {
|
|
|
697
969
|
|
|
698
970
|
return {
|
|
699
971
|
statusbar: statusbar,
|
|
700
|
-
navigation: navigation,
|
|
701
|
-
charWrapper: charWrapper,
|
|
702
|
-
charCounter: charCounter
|
|
972
|
+
navigation: /** @type {HTMLElement} */ (navigation),
|
|
973
|
+
charWrapper: /** @type {HTMLElement} */ (charWrapper),
|
|
974
|
+
charCounter: /** @type {HTMLElement} */ (charCounter)
|
|
703
975
|
};
|
|
704
976
|
}
|
|
705
977
|
|
|
706
|
-
|
|
978
|
+
/**
|
|
979
|
+
* @description Initialize options.
|
|
980
|
+
* @param {EditorFrameOptions} o - Target options
|
|
981
|
+
* @param {EditorInitOptions} origin - Full options
|
|
982
|
+
* @returns {Map<string, *>}
|
|
983
|
+
*/
|
|
984
|
+
function InitFrameOptions(o, origin) {
|
|
985
|
+
const fo = new Map();
|
|
986
|
+
|
|
707
987
|
fo.set('_origin', o);
|
|
708
988
|
const barContainer = origin.statusbar_container;
|
|
709
989
|
|
|
@@ -757,14 +1037,18 @@ function InitFrameOptions(o, origin, fo) {
|
|
|
757
1037
|
fo.set('charCounter_max', numbers.is(charCounter_max) && charCounter_max > -1 ? charCounter_max * 1 : null);
|
|
758
1038
|
fo.set('charCounter_label', typeof charCounter_label === 'string' ? charCounter_label.trim() : null);
|
|
759
1039
|
fo.set('charCounter_type', typeof charCounter_type === 'string' ? charCounter_type : 'char');
|
|
1040
|
+
|
|
1041
|
+
return fo;
|
|
760
1042
|
}
|
|
761
1043
|
|
|
762
1044
|
/**
|
|
1045
|
+
* @private
|
|
763
1046
|
* @description Initialize property of suneditor elements
|
|
764
|
-
* @param {string} key
|
|
765
|
-
* @param {
|
|
766
|
-
* @param {
|
|
767
|
-
* @
|
|
1047
|
+
* @param {string} key - The key of the editor frame
|
|
1048
|
+
* @param {Map<string, *>} options - options
|
|
1049
|
+
* @param {HTMLElement} topDiv - top div
|
|
1050
|
+
* @param {Map<string, *>} targetOptions - editor.frameOptions
|
|
1051
|
+
* @returns {{bottomBar: ReturnType<CreateStatusbar>, wysiwygFrame: HTMLElement, codeView: HTMLElement, placeholder: HTMLElement}}
|
|
768
1052
|
*/
|
|
769
1053
|
function _initTargetElements(key, options, topDiv, targetOptions) {
|
|
770
1054
|
const editorStyles = targetOptions.get('_defaultStyles');
|
|
@@ -773,13 +1057,13 @@ function _initTargetElements(key, options, topDiv, targetOptions) {
|
|
|
773
1057
|
|
|
774
1058
|
/** editor */
|
|
775
1059
|
// wysiwyg div or iframe
|
|
776
|
-
const wysiwygDiv =
|
|
1060
|
+
const wysiwygDiv = dom.utils.createElement(!targetOptions.get('iframe') ? 'DIV' : 'IFRAME', {
|
|
777
1061
|
class: 'se-wrapper-inner se-wrapper-wysiwyg',
|
|
778
1062
|
'data-root-key': key
|
|
779
1063
|
});
|
|
780
1064
|
|
|
781
1065
|
if (!targetOptions.get('iframe')) {
|
|
782
|
-
wysiwygDiv.setAttribute('contenteditable', true);
|
|
1066
|
+
wysiwygDiv.setAttribute('contenteditable', 'true');
|
|
783
1067
|
wysiwygDiv.setAttribute('scrolling', 'auto');
|
|
784
1068
|
wysiwygDiv.className += ' ' + options.get('_editableClass');
|
|
785
1069
|
wysiwygDiv.style.cssText = editorStyles.frame + editorStyles.editor;
|
|
@@ -788,17 +1072,19 @@ function _initTargetElements(key, options, topDiv, targetOptions) {
|
|
|
788
1072
|
for (const frameKey in frameAttrs) {
|
|
789
1073
|
wysiwygDiv.setAttribute(frameKey, frameAttrs[frameKey]);
|
|
790
1074
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
1075
|
+
|
|
1076
|
+
const iframeWW = /** @type {HTMLIFrameElement} */ (wysiwygDiv);
|
|
1077
|
+
iframeWW.allowFullscreen = true;
|
|
1078
|
+
iframeWW.frameBorder = '0';
|
|
1079
|
+
iframeWW.style.cssText = editorStyles.frame;
|
|
794
1080
|
}
|
|
795
1081
|
|
|
796
1082
|
// textarea for code view
|
|
797
|
-
const textarea =
|
|
1083
|
+
const textarea = dom.utils.createElement('TEXTAREA', { class: 'se-wrapper-inner se-code-viewer', style: editorStyles.frame });
|
|
798
1084
|
let placeholder = null;
|
|
799
1085
|
if (targetOptions.get('placeholder')) {
|
|
800
|
-
placeholder =
|
|
801
|
-
placeholder.
|
|
1086
|
+
placeholder = dom.utils.createElement('SPAN', { class: 'se-placeholder' });
|
|
1087
|
+
placeholder.textContent = targetOptions.get('placeholder');
|
|
802
1088
|
}
|
|
803
1089
|
|
|
804
1090
|
return {
|
|
@@ -810,9 +1096,10 @@ function _initTargetElements(key, options, topDiv, targetOptions) {
|
|
|
810
1096
|
}
|
|
811
1097
|
|
|
812
1098
|
/**
|
|
1099
|
+
* @private
|
|
813
1100
|
* @description Check the CodeMirror option to apply the CodeMirror and return the CodeMirror element.
|
|
814
|
-
* @param {
|
|
815
|
-
* @param {
|
|
1101
|
+
* @param {Map<string, *>} options options
|
|
1102
|
+
* @param {HTMLElement} textarea textarea element
|
|
816
1103
|
*/
|
|
817
1104
|
function _checkCodeMirror(options, targetOptions, textarea) {
|
|
818
1105
|
let cmeditor = null;
|
|
@@ -863,7 +1150,7 @@ function _checkCodeMirror(options, targetOptions, textarea) {
|
|
|
863
1150
|
|
|
864
1151
|
options.set('hasCodeMirror', hasCodeMirror);
|
|
865
1152
|
if (cmeditor) {
|
|
866
|
-
|
|
1153
|
+
dom.utils.removeItem(textarea);
|
|
867
1154
|
cmeditor.className += ' se-code-viewer-mirror';
|
|
868
1155
|
return cmeditor;
|
|
869
1156
|
}
|
|
@@ -872,6 +1159,7 @@ function _checkCodeMirror(options, targetOptions, textarea) {
|
|
|
872
1159
|
}
|
|
873
1160
|
|
|
874
1161
|
/**
|
|
1162
|
+
* @private
|
|
875
1163
|
* @description create blacklist
|
|
876
1164
|
* @param {string} blacklist blacklist
|
|
877
1165
|
* @param {string} defaultLine options.get('defaultLine')
|
|
@@ -893,6 +1181,7 @@ function _createBlacklist(blacklist, defaultLine) {
|
|
|
893
1181
|
}
|
|
894
1182
|
|
|
895
1183
|
/**
|
|
1184
|
+
* @private
|
|
896
1185
|
* @description create formats regexp object.
|
|
897
1186
|
* @param {string} value value
|
|
898
1187
|
* @param {string} defaultValue default value
|
|
@@ -913,8 +1202,9 @@ function _createFormatInfo(value, defaultValue, blacklist) {
|
|
|
913
1202
|
}
|
|
914
1203
|
|
|
915
1204
|
/**
|
|
1205
|
+
* @private
|
|
916
1206
|
* @description create whitelist or blacklist.
|
|
917
|
-
* @param {
|
|
1207
|
+
* @param {Map<string, *>} o options
|
|
918
1208
|
* @returns {string} whitelist
|
|
919
1209
|
*/
|
|
920
1210
|
function _createWhitelist(o) {
|
|
@@ -928,8 +1218,9 @@ function _createWhitelist(o) {
|
|
|
928
1218
|
}
|
|
929
1219
|
|
|
930
1220
|
/**
|
|
1221
|
+
* @private
|
|
931
1222
|
* @description Suneditor's Default button list
|
|
932
|
-
* @param {
|
|
1223
|
+
* @param {Map<string, *>} options options
|
|
933
1224
|
*/
|
|
934
1225
|
function _defaultButtons(options, icons, lang) {
|
|
935
1226
|
const isRTL = options.get('_rtl');
|
|
@@ -941,6 +1232,7 @@ function _defaultButtons(options, icons, lang) {
|
|
|
941
1232
|
subscript: ['', lang.subscript, 'subscript', '', icons.subscript],
|
|
942
1233
|
superscript: ['', lang.superscript, 'superscript', '', icons.superscript],
|
|
943
1234
|
removeFormat: ['', lang.removeFormat, 'removeFormat', '', icons.remove_format],
|
|
1235
|
+
copyFormat: ['', lang.copyFormat, 'copyFormat', '', icons.format_paint],
|
|
944
1236
|
indent: ['se-icon-flip-rtl', lang.indent, 'indent', '', isRTL ? icons.outdent : icons.indent],
|
|
945
1237
|
outdent: ['se-icon-flip-rtl', lang.outdent, 'outdent', '', isRTL ? icons.indent : icons.outdent],
|
|
946
1238
|
fullScreen: ['se-code-view-enabled se-component-enabled', lang.fullScreen, 'fullScreen', '', icons.expansion],
|
|
@@ -955,17 +1247,23 @@ function _defaultButtons(options, icons, lang) {
|
|
|
955
1247
|
dir_rtl: ['', lang.dir_rtl, 'dir_rtl', '', icons.dir_rtl],
|
|
956
1248
|
save: ['se-component-enabled', lang.save, 'save', '', icons.save],
|
|
957
1249
|
newDocument: ['se-component-enabled', lang.newDocument, 'newDocument', '', icons.new_document],
|
|
958
|
-
selectAll: ['se-component-enabled', lang.selectAll, 'selectAll', '', icons.select_all]
|
|
1250
|
+
selectAll: ['se-component-enabled', lang.selectAll, 'selectAll', '', icons.select_all],
|
|
1251
|
+
pageBreak: ['se-component-enabled', lang.pageBreak, 'pageBreak', '', icons.page_break],
|
|
1252
|
+
// document type buttons
|
|
1253
|
+
pageUp: ['se-component-enabled', lang.pageUp, 'pageUp', '', icons.page_up],
|
|
1254
|
+
pageDown: ['se-component-enabled', lang.pageDown, 'pageDown', '', icons.page_down],
|
|
1255
|
+
pageNavigator: ['se-component-enabled', '', 'pageNavigator', 'input', '']
|
|
959
1256
|
};
|
|
960
1257
|
}
|
|
961
1258
|
|
|
962
1259
|
/**
|
|
1260
|
+
* @private
|
|
963
1261
|
* @description Create a group div containing each module
|
|
964
|
-
* @returns {
|
|
1262
|
+
* @returns {{div: Element, ul: Element}}
|
|
965
1263
|
*/
|
|
966
1264
|
function _createModuleGroup() {
|
|
967
|
-
const oUl =
|
|
968
|
-
const oDiv =
|
|
1265
|
+
const oUl = dom.utils.createElement('UL', { class: 'se-menu-list' });
|
|
1266
|
+
const oDiv = dom.utils.createElement('DIV', { class: 'se-btn-module se-btn-module-border' }, oUl);
|
|
969
1267
|
|
|
970
1268
|
return {
|
|
971
1269
|
div: oDiv,
|
|
@@ -974,27 +1272,38 @@ function _createModuleGroup() {
|
|
|
974
1272
|
}
|
|
975
1273
|
|
|
976
1274
|
/**
|
|
1275
|
+
* @private
|
|
977
1276
|
* @description Create a button element
|
|
978
1277
|
* @param {string} className className in button
|
|
979
1278
|
* @param {string} title Title in button
|
|
980
1279
|
* @param {string} dataCommand The data-command property of the button
|
|
981
|
-
* @param {
|
|
1280
|
+
* @param {"command"|"dropdown"|"field"|"browser"|"input"|"modal"|"popup"} dataType The data-type property of the button
|
|
982
1281
|
* @param {string} innerHTML Html in button
|
|
983
1282
|
* @param {string} _disabled Button disabled
|
|
984
|
-
* @param {Object} icons Icons
|
|
985
|
-
* @returns {
|
|
1283
|
+
* @param {Object<string, string>} icons Icons
|
|
1284
|
+
* @returns {{li: HTMLElement, button: HTMLElement}}
|
|
986
1285
|
*/
|
|
987
1286
|
function _createButton(className, title, dataCommand, dataType, innerHTML, _disabled, icons) {
|
|
988
|
-
|
|
1287
|
+
if (!innerHTML) innerHTML = '';
|
|
1288
|
+
|
|
1289
|
+
const oLi = dom.utils.createElement('LI');
|
|
989
1290
|
const label = title || '';
|
|
990
|
-
const
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1291
|
+
const isDiv = /^INPUT|FIELD$/i.test(dataType);
|
|
1292
|
+
const oButton = /** @type {HTMLButtonElement} */ (
|
|
1293
|
+
'se-toolbar-separator-vertical' === className
|
|
1294
|
+
? dom.utils.createElement('DIV', { class: className, tabindex: '-1' }, null)
|
|
1295
|
+
: dom.utils.createElement(isDiv ? 'DIV' : 'BUTTON', {
|
|
1296
|
+
class: 'se-toolbar-btn se-btn se-tooltip' + (className ? ' ' + className : ''),
|
|
1297
|
+
'data-command': dataCommand,
|
|
1298
|
+
'data-type': dataType,
|
|
1299
|
+
'aria-label': label.replace(/<span .+<\/span>/, ''),
|
|
1300
|
+
tabindex: '-1'
|
|
1301
|
+
})
|
|
1302
|
+
);
|
|
1303
|
+
|
|
1304
|
+
if (!isDiv) {
|
|
1305
|
+
oButton.setAttribute('type', 'button');
|
|
1306
|
+
}
|
|
998
1307
|
|
|
999
1308
|
if (/^default\./i.test(innerHTML)) {
|
|
1000
1309
|
innerHTML = icons[innerHTML.replace(/^default\./i, '')];
|
|
@@ -1004,9 +1313,9 @@ function _createButton(className, title, dataCommand, dataType, innerHTML, _disa
|
|
|
1004
1313
|
oButton.className += ' se-btn-more-text';
|
|
1005
1314
|
}
|
|
1006
1315
|
|
|
1007
|
-
if (_disabled) oButton.
|
|
1316
|
+
if (_disabled) oButton.disabled = true;
|
|
1008
1317
|
|
|
1009
|
-
if (/^FIELD$/i.test(dataType))
|
|
1318
|
+
if (/^FIELD$/i.test(dataType)) dom.utils.addClass(oLi, 'se-toolbar-hidden-btn');
|
|
1010
1319
|
|
|
1011
1320
|
if (label) innerHTML += CreateTooltipInner(label);
|
|
1012
1321
|
if (innerHTML) oButton.innerHTML = innerHTML;
|
|
@@ -1019,18 +1328,34 @@ function _createButton(className, title, dataCommand, dataType, innerHTML, _disa
|
|
|
1019
1328
|
};
|
|
1020
1329
|
}
|
|
1021
1330
|
|
|
1331
|
+
/**
|
|
1332
|
+
* @description Create tooltip HTML
|
|
1333
|
+
* @param {string} text Tooltip text
|
|
1334
|
+
* @returns {string} Tooltip HTML
|
|
1335
|
+
*/
|
|
1022
1336
|
export function CreateTooltipInner(text) {
|
|
1023
1337
|
return `<span class="se-tooltip-inner"><span class="se-tooltip-text">${text}</span></span>`;
|
|
1024
1338
|
}
|
|
1025
1339
|
|
|
1340
|
+
/**
|
|
1341
|
+
* @description Update a button state, attributes, and icons
|
|
1342
|
+
* @param {HTMLElement|null} element Button element
|
|
1343
|
+
* @param {Object<string, *>} plugin Plugin
|
|
1344
|
+
* @param {Object<string, string>} icons Icons
|
|
1345
|
+
* @param {Object<string, string>} lang lang
|
|
1346
|
+
*/
|
|
1026
1347
|
export function UpdateButton(element, plugin, icons, lang) {
|
|
1027
1348
|
if (!element) return;
|
|
1028
1349
|
|
|
1029
1350
|
const noneInner = plugin.inner === false;
|
|
1030
1351
|
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1352
|
+
if (plugin.inner?.nodeType === 1) {
|
|
1353
|
+
element.appendChild(plugin.inner);
|
|
1354
|
+
} else {
|
|
1355
|
+
element.innerHTML = noneInner
|
|
1356
|
+
? ''
|
|
1357
|
+
: (plugin.inner || icons[plugin.icon] || plugin.icon || '<span class="se-icon-text">!</span>') + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + (lang[plugin.title] || plugin.title) + '</span></span>';
|
|
1358
|
+
}
|
|
1034
1359
|
|
|
1035
1360
|
element.setAttribute('aria-label', plugin.title);
|
|
1036
1361
|
|
|
@@ -1043,24 +1368,24 @@ export function UpdateButton(element, plugin, icons, lang) {
|
|
|
1043
1368
|
}
|
|
1044
1369
|
|
|
1045
1370
|
// side, replace button
|
|
1046
|
-
if (plugin.
|
|
1047
|
-
|
|
1048
|
-
element.parentElement.appendChild(plugin.
|
|
1371
|
+
if (plugin.afterItem) {
|
|
1372
|
+
dom.utils.addClass(plugin.afterItem, 'se-toolbar-btn');
|
|
1373
|
+
element.parentElement.appendChild(plugin.afterItem);
|
|
1049
1374
|
|
|
1050
|
-
|
|
1051
|
-
|
|
1375
|
+
dom.utils.addClass(element, 'se-side-btn-a');
|
|
1376
|
+
dom.utils.addClass(plugin.afterItem, 'se-side-btn-after');
|
|
1052
1377
|
}
|
|
1053
|
-
if (plugin.
|
|
1054
|
-
|
|
1055
|
-
element.parentElement.insertBefore(plugin.
|
|
1378
|
+
if (plugin.beforeItem) {
|
|
1379
|
+
dom.utils.addClass(plugin.beforeItem, 'se-toolbar-btn');
|
|
1380
|
+
element.parentElement.insertBefore(plugin.beforeItem, element);
|
|
1056
1381
|
|
|
1057
|
-
if (plugin.
|
|
1058
|
-
|
|
1059
|
-
|
|
1382
|
+
if (plugin.afterItem) {
|
|
1383
|
+
dom.utils.addClass(element, 'se-side-btn');
|
|
1384
|
+
dom.utils.removeClass(element, 'se-side-btn-a');
|
|
1060
1385
|
} else {
|
|
1061
|
-
|
|
1386
|
+
dom.utils.addClass(element, 'se-side-btn-b');
|
|
1062
1387
|
}
|
|
1063
|
-
|
|
1388
|
+
dom.utils.addClass(plugin.beforeItem, 'se-side-btn-before');
|
|
1064
1389
|
}
|
|
1065
1390
|
if (plugin.replaceButton) {
|
|
1066
1391
|
element.parentElement.appendChild(plugin.replaceButton);
|
|
@@ -1070,10 +1395,10 @@ export function UpdateButton(element, plugin, icons, lang) {
|
|
|
1070
1395
|
if (!plugin.replaceButton && /^INPUT$/i.test(element.getAttribute('data-type'))) {
|
|
1071
1396
|
const inputTarget = element.querySelector('input');
|
|
1072
1397
|
if (inputTarget) {
|
|
1073
|
-
|
|
1398
|
+
dom.utils.addClass(inputTarget, 'se-toolbar-btn');
|
|
1074
1399
|
inputTarget.setAttribute('data-command', element.getAttribute('data-command'));
|
|
1075
1400
|
inputTarget.setAttribute('data-type', element.getAttribute('data-type'));
|
|
1076
|
-
if (element.hasAttribute('disabled')) inputTarget.
|
|
1401
|
+
if (element.hasAttribute('disabled')) inputTarget.disabled = true;
|
|
1077
1402
|
}
|
|
1078
1403
|
}
|
|
1079
1404
|
}
|
|
@@ -1081,17 +1406,18 @@ export function UpdateButton(element, plugin, icons, lang) {
|
|
|
1081
1406
|
/**
|
|
1082
1407
|
* @description Create editor HTML
|
|
1083
1408
|
* @param {Array} buttonList option.buttonList
|
|
1084
|
-
* @param {Object
|
|
1085
|
-
* @param {
|
|
1086
|
-
* @param {Object} icons icons
|
|
1087
|
-
* @param {Object} lang lang
|
|
1409
|
+
* @param {?Object<string, *>} plugins Plugins
|
|
1410
|
+
* @param {Map<string, *>} options options
|
|
1411
|
+
* @param {Object<string, string>} icons icons
|
|
1412
|
+
* @param {Object<string, string>} lang lang
|
|
1088
1413
|
* @param {boolean} isUpdate Is update
|
|
1089
|
-
* @returns {
|
|
1414
|
+
* @returns {{element: HTMLElement, pluginCallButtons: Object<string, Array<HTMLElement>>, responsiveButtons: Array<HTMLElement>, buttonTray: HTMLElement, updateButtons: Array<{button: HTMLElement, plugin: *, key: string}>}}}
|
|
1090
1415
|
*/
|
|
1091
1416
|
export function CreateToolBar(buttonList, plugins, options, icons, lang, isUpdate) {
|
|
1092
1417
|
/** create button list */
|
|
1093
1418
|
buttonList = JSON.parse(JSON.stringify(buttonList));
|
|
1094
1419
|
const defaultButtonList = _defaultButtons(options, icons, lang);
|
|
1420
|
+
/** @type {Object<string, Array<HTMLElement>>} */
|
|
1095
1421
|
const pluginCallButtons = {};
|
|
1096
1422
|
const responsiveButtons = [];
|
|
1097
1423
|
const updateButtons = [];
|
|
@@ -1101,10 +1427,10 @@ export function CreateToolBar(buttonList, plugins, options, icons, lang, isUpdat
|
|
|
1101
1427
|
let plugin = null;
|
|
1102
1428
|
let moduleElement = null;
|
|
1103
1429
|
let buttonElement = null;
|
|
1104
|
-
let vertical = false;
|
|
1105
|
-
const moreLayer =
|
|
1106
|
-
const buttonTray =
|
|
1107
|
-
const separator_vertical =
|
|
1430
|
+
// let vertical = false;
|
|
1431
|
+
const moreLayer = dom.utils.createElement('DIV', { class: 'se-toolbar-more-layer' });
|
|
1432
|
+
const buttonTray = dom.utils.createElement('DIV', { class: 'se-btn-tray' });
|
|
1433
|
+
const separator_vertical = dom.utils.createElement('DIV', { class: 'se-toolbar-separator-vertical' });
|
|
1108
1434
|
|
|
1109
1435
|
buttonGroupLoop: for (let i = 0, more, moreContainer, moreCommand, buttonGroup, align; i < buttonList.length; i++) {
|
|
1110
1436
|
more = false;
|
|
@@ -1134,14 +1460,14 @@ export function CreateToolBar(buttonList, plugins, options, icons, lang, isUpdat
|
|
|
1134
1460
|
} else {
|
|
1135
1461
|
// align
|
|
1136
1462
|
if (/^-/.test(button)) {
|
|
1137
|
-
align = button.
|
|
1463
|
+
align = button.substring(1);
|
|
1138
1464
|
moduleElement.div.className += ' module-float-' + align;
|
|
1139
1465
|
continue;
|
|
1140
1466
|
}
|
|
1141
1467
|
|
|
1142
1468
|
// rtl fix
|
|
1143
1469
|
if (/^#/.test(button)) {
|
|
1144
|
-
const option = button.
|
|
1470
|
+
const option = button.substring(1);
|
|
1145
1471
|
if (option === 'fix') moduleElement.ul.className += ' se-menu-dir-fix';
|
|
1146
1472
|
continue;
|
|
1147
1473
|
}
|
|
@@ -1154,6 +1480,9 @@ export function CreateToolBar(buttonList, plugins, options, icons, lang, isUpdat
|
|
|
1154
1480
|
const title = matched[1].trim();
|
|
1155
1481
|
const innerHTML = matched[2].trim();
|
|
1156
1482
|
modules = ['se-btn-more', /^lang\./i.test(title) ? lang[title.replace(/^lang\./i, '')] : title, moreCommand, 'MORE', innerHTML];
|
|
1483
|
+
} else if (button === '|') {
|
|
1484
|
+
// separator vertical
|
|
1485
|
+
modules = ['se-toolbar-separator-vertical', '', '', 'separator', ''];
|
|
1157
1486
|
} else {
|
|
1158
1487
|
// default command
|
|
1159
1488
|
modules = defaultButtonList[button];
|
|
@@ -1184,7 +1513,7 @@ export function CreateToolBar(buttonList, plugins, options, icons, lang, isUpdat
|
|
|
1184
1513
|
// more button
|
|
1185
1514
|
if (moreButton) {
|
|
1186
1515
|
more = true;
|
|
1187
|
-
moreContainer =
|
|
1516
|
+
moreContainer = dom.utils.createElement('DIV');
|
|
1188
1517
|
moreContainer.className = 'se-more-layer ' + moreCommand;
|
|
1189
1518
|
moreContainer.setAttribute('data-ref', moreCommand);
|
|
1190
1519
|
moreContainer.innerHTML = '<div class="se-more-form"><ul class="se-menu-list"' + (align ? ' style="float: ' + align + ';"' : '') + '></ul></div>';
|
|
@@ -1193,18 +1522,23 @@ export function CreateToolBar(buttonList, plugins, options, icons, lang, isUpdat
|
|
|
1193
1522
|
}
|
|
1194
1523
|
}
|
|
1195
1524
|
|
|
1196
|
-
if (vertical) {
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
}
|
|
1525
|
+
// if (vertical) {
|
|
1526
|
+
// const sv = separator_vertical.cloneNode(false);
|
|
1527
|
+
// buttonTray.appendChild(sv);
|
|
1528
|
+
// }
|
|
1200
1529
|
|
|
1201
1530
|
buttonTray.appendChild(moduleElement.div);
|
|
1202
|
-
vertical = true;
|
|
1531
|
+
// vertical = true;
|
|
1532
|
+
} else if (buttonGroup === '|') {
|
|
1533
|
+
// // separator vertical
|
|
1534
|
+
const sv = separator_vertical.cloneNode(false);
|
|
1535
|
+
buttonTray.appendChild(sv);
|
|
1536
|
+
continue;
|
|
1203
1537
|
} else if (/^\/$/.test(buttonGroup)) {
|
|
1204
1538
|
/** line break */
|
|
1205
|
-
const enterDiv =
|
|
1539
|
+
const enterDiv = dom.utils.createElement('DIV', { class: 'se-btn-module-enter' });
|
|
1206
1540
|
buttonTray.appendChild(enterDiv);
|
|
1207
|
-
vertical = false;
|
|
1541
|
+
// vertical = false;
|
|
1208
1542
|
}
|
|
1209
1543
|
}
|
|
1210
1544
|
|
|
@@ -1213,7 +1547,7 @@ export function CreateToolBar(buttonList, plugins, options, icons, lang, isUpdat
|
|
|
1213
1547
|
buttonTray.style.display = 'none';
|
|
1214
1548
|
break;
|
|
1215
1549
|
case 1:
|
|
1216
|
-
|
|
1550
|
+
dom.utils.removeClass(buttonTray.firstElementChild, 'se-btn-module-border');
|
|
1217
1551
|
break;
|
|
1218
1552
|
}
|
|
1219
1553
|
|
|
@@ -1221,7 +1555,7 @@ export function CreateToolBar(buttonList, plugins, options, icons, lang, isUpdat
|
|
|
1221
1555
|
if (responsiveButtons.length > 0) responsiveButtons.unshift(buttonList);
|
|
1222
1556
|
|
|
1223
1557
|
// rendering toolbar
|
|
1224
|
-
const tool_bar =
|
|
1558
|
+
const tool_bar = dom.utils.createElement('DIV', { class: 'se-toolbar sun-editor-common' + (!options.get('shortcutsHint') ? ' se-shortcut-hide' : '') }, buttonTray);
|
|
1225
1559
|
|
|
1226
1560
|
if (options.get('toolbar_hide')) tool_bar.style.display = 'none';
|
|
1227
1561
|
|