suneditor 3.0.0-beta.1 → 3.0.0-beta.3
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/CONTRIBUTING.md +166 -29
- package/README.md +13 -1
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +13 -5
- package/src/assets/{variables.css → design/color.css} +45 -59
- package/src/assets/design/index.css +3 -0
- package/src/assets/design/size.css +35 -0
- package/src/assets/design/typography.css +37 -0
- package/src/assets/suneditor-contents.css +1 -1
- package/src/assets/suneditor.css +40 -28
- package/src/core/base/eventHandlers/handler_ww_dragDrop.js +4 -2
- package/src/core/base/eventHandlers/handler_ww_key_input.js +16 -16
- package/src/core/base/eventHandlers/handler_ww_mouse.js +1 -1
- package/src/core/base/eventManager.js +75 -32
- package/src/core/class/char.js +3 -2
- package/src/core/class/component.js +38 -14
- package/src/core/class/format.js +13 -2
- package/src/core/class/html.js +58 -26
- package/src/core/class/menu.js +19 -0
- package/src/core/class/selection.js +1 -8
- package/src/core/class/toolbar.js +2 -1
- package/src/core/class/ui.js +3 -1
- package/src/core/editor.js +125 -59
- package/src/core/section/actives.js +73 -10
- package/src/core/section/constructor.js +144 -55
- package/src/core/section/documentType.js +2 -2
- package/src/events.js +25 -1
- package/src/helper/converter.js +23 -1
- package/src/helper/dom/domCheck.js +12 -2
- package/src/modules/Controller.js +25 -5
- package/src/modules/Figure.js +6 -6
- package/src/modules/FileManager.js +1 -1
- package/src/plugins/command/fileUpload.js +3 -3
- package/src/plugins/dropdown/formatBlock.js +4 -13
- package/src/plugins/dropdown/table.js +51 -18
- package/src/plugins/modal/audio.js +2 -2
- package/src/plugins/modal/embed.js +2 -2
- package/src/plugins/modal/image.js +3 -3
- package/src/plugins/modal/math.js +2 -2
- package/src/plugins/modal/video.js +1 -1
- package/src/plugins/popup/anchor.js +1 -1
- package/src/suneditor.js +1 -1
- package/src/themes/dark.css +88 -45
- package/types/core/base/eventManager.d.ts +23 -0
- package/types/core/class/char.d.ts +2 -1
- package/types/core/class/component.d.ts +13 -3
- package/types/core/class/format.d.ts +8 -1
- package/types/core/class/html.d.ts +8 -0
- package/types/core/class/menu.d.ts +8 -0
- package/types/core/class/ui.d.ts +1 -1
- package/types/core/editor.d.ts +7 -2
- package/types/core/section/constructor.d.ts +167 -149
- package/types/events.d.ts +3 -0
- package/types/helper/converter.d.ts +9 -0
- package/types/helper/dom/domCheck.d.ts +7 -0
- package/types/helper/index.d.ts +2 -0
- package/types/index.d.ts +1 -1
- package/types/plugins/dropdown/formatBlock.d.ts +2 -2
- package/types/plugins/dropdown/table.d.ts +1 -0
- package/.eslintignore +0 -7
- package/.eslintrc.json +0 -81
- /package/src/assets/icons/{_default.js → defaultIcons.js} +0 -0
- /package/types/assets/icons/{_default.d.ts → defaultIcons.d.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import _icons from '../../assets/icons/
|
|
1
|
+
import _icons from '../../assets/icons/defaultIcons';
|
|
2
2
|
import _defaultLang from '../../langs/en';
|
|
3
3
|
import { CreateContext, CreateFrameContext } from './context';
|
|
4
4
|
import { dom, numbers, converter, env } from '../../helper';
|
|
@@ -24,6 +24,9 @@ const DEFAULT_ELEMENT_WHITELIST =
|
|
|
24
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';
|
|
25
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';
|
|
26
26
|
|
|
27
|
+
/* scopeSelectionTags */
|
|
28
|
+
const DEFAULT_SCOPE_SELECTION_TAGS = 'td|table|li|ol|ul|pre|figcaption|blockquote|dl|dt|dd';
|
|
29
|
+
|
|
27
30
|
const _video_audio_attr = '|controls|autoplay|loop|muted|poster|preload|playsinline|volume|crossorigin|disableRemotePlayback|controlsList';
|
|
28
31
|
const _iframe_attr = '|allowfullscreen|sandbox|loading|allow|referrerpolicy|frameborder|scrolling';
|
|
29
32
|
const DEFAULT_ATTRIBUTE_WHITELIST = 'contenteditable|target|href|title|download|rel|src|alt|class|type|colspan|rowspan' + _video_audio_attr + _iframe_attr;
|
|
@@ -69,42 +72,6 @@ const DEFAULT_CONTENT_STYLES =
|
|
|
69
72
|
|
|
70
73
|
const RETAIN_STYLE_MODE = ['repeat', 'always', 'none'];
|
|
71
74
|
|
|
72
|
-
export const RO_UNAVAILABD = [
|
|
73
|
-
'mode',
|
|
74
|
-
'type',
|
|
75
|
-
'externalLibs',
|
|
76
|
-
'iframe',
|
|
77
|
-
'convertTextTags',
|
|
78
|
-
'textStyleTags',
|
|
79
|
-
'fontSizeUnits',
|
|
80
|
-
'spanStyles',
|
|
81
|
-
'lineStyles',
|
|
82
|
-
'tagStyles',
|
|
83
|
-
'reverseCommands',
|
|
84
|
-
'shortcutsDisable',
|
|
85
|
-
'shortcuts',
|
|
86
|
-
'buttonList',
|
|
87
|
-
'subToolbar',
|
|
88
|
-
'toolbar_container',
|
|
89
|
-
'statusbar_container',
|
|
90
|
-
'elementWhitelist',
|
|
91
|
-
'elementBlacklist',
|
|
92
|
-
'attributeWhitelist',
|
|
93
|
-
'attributeBlacklist',
|
|
94
|
-
'defaultLine',
|
|
95
|
-
'formatClosureBrLine',
|
|
96
|
-
'formatBrLine',
|
|
97
|
-
'formatLine',
|
|
98
|
-
'formatClosureBlock',
|
|
99
|
-
'formatBlock',
|
|
100
|
-
'__defaultElementWhitelist',
|
|
101
|
-
'__defaultAttributeWhitelist',
|
|
102
|
-
'__listCommonStyle',
|
|
103
|
-
'icons',
|
|
104
|
-
'lang',
|
|
105
|
-
'codeMirror'
|
|
106
|
-
];
|
|
107
|
-
|
|
108
75
|
/**
|
|
109
76
|
* @typedef {Object} EditorFrameOptions
|
|
110
77
|
* @property {string} [value=""] - Initial value for the editor.
|
|
@@ -185,6 +152,7 @@ export const RO_UNAVAILABD = [
|
|
|
185
152
|
* - Formats that include "line", such as "Quote", still operate on a "line" basis.
|
|
186
153
|
* - ● suneditor processes work in "line" units.
|
|
187
154
|
* - ● When set to "br", performance may decrease when editing a lot of data.
|
|
155
|
+
* @property {Array<string>} [scopeSelectionTags=["td", "table", "li", "ol", "ul", "pre", "figcaption", "blockquote", "dl", "dt", "dd"]] - Tags treated as whole units when selecting all content.
|
|
188
156
|
* @property {string} [__defaultElementWhitelist="br|div"] - Default allowed HTML elements. The default values are maintained.
|
|
189
157
|
* @property {string} [elementWhitelist=""] - Allowed HTML elements. Delimiter: "|" (e.g. "p|div", "*").
|
|
190
158
|
* @property {string} [elementBlacklist=""] - Disallowed HTML elements. Delimiter: "|" (e.g. "script|style").
|
|
@@ -248,13 +216,127 @@ export const RO_UNAVAILABD = [
|
|
|
248
216
|
* - For example, when changing the font size or color of a list item (`<li>`),
|
|
249
217
|
* - these styles will be applied to the `<li>` tag instead of wrapping the content inside additional tags.
|
|
250
218
|
* @property {Object<string, *>} [externalLibs] - External libraries like CodeMirror or MathJax.
|
|
251
|
-
*
|
|
219
|
+
*
|
|
220
|
+
* @property {Object<string, *>} [Dynamic_pluginOptions] - Dynamic plugin options, where the key is the plugin name and the value is its configuration.
|
|
252
221
|
*/
|
|
253
222
|
|
|
254
223
|
/**
|
|
255
224
|
* @typedef {EditorBaseOptions & EditorFrameOptions} EditorInitOptions
|
|
256
225
|
*/
|
|
257
226
|
|
|
227
|
+
/** ------------- [OPTIONS FRAG] ------------- */
|
|
228
|
+
/**
|
|
229
|
+
* @description For all EditorInitOptions keys, only boolean | null values are allowed.
|
|
230
|
+
* - 'fixed' → Immutable / null → Resettable.
|
|
231
|
+
* @type {Partial<Record<keyof EditorInitOptions, "fixed" | true>>}
|
|
232
|
+
*/
|
|
233
|
+
export const OPTION_FRAME_FIXED_FLAG = {
|
|
234
|
+
value: 'fixed',
|
|
235
|
+
placeholder: true,
|
|
236
|
+
editableFrameAttributes: true,
|
|
237
|
+
width: true,
|
|
238
|
+
minWidth: true,
|
|
239
|
+
maxWidth: true,
|
|
240
|
+
height: true,
|
|
241
|
+
minHeight: true,
|
|
242
|
+
maxHeight: true,
|
|
243
|
+
editorStyle: true,
|
|
244
|
+
iframe: 'fixed',
|
|
245
|
+
iframe_fullPage: 'fixed',
|
|
246
|
+
iframe_attributes: true,
|
|
247
|
+
iframe_cssFileName: true,
|
|
248
|
+
statusbar: true,
|
|
249
|
+
statusbar_showPathLabel: true,
|
|
250
|
+
statusbar_resizeEnable: 'fixed',
|
|
251
|
+
charCounter: true,
|
|
252
|
+
charCounter_max: true,
|
|
253
|
+
charCounter_label: true,
|
|
254
|
+
charCounter_type: true
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* @description For all EditorInitOptions keys, only boolean | null values are allowed.
|
|
258
|
+
* - 'fixed' → Immutable / null → Resettable.
|
|
259
|
+
* @type {Partial<Record<keyof EditorInitOptions, "fixed" | true>>}
|
|
260
|
+
*/
|
|
261
|
+
export const OPTION_FIXED_FLAG = {
|
|
262
|
+
plugins: 'fixed',
|
|
263
|
+
excludedPlugins: 'fixed',
|
|
264
|
+
buttonList: 'fixed',
|
|
265
|
+
v2Migration: 'fixed',
|
|
266
|
+
strictMode: 'fixed',
|
|
267
|
+
mode: 'fixed',
|
|
268
|
+
type: 'fixed',
|
|
269
|
+
theme: true,
|
|
270
|
+
lang: 'fixed',
|
|
271
|
+
fontSizeUnits: 'fixed',
|
|
272
|
+
allowedClassName: 'fixed',
|
|
273
|
+
closeModalOutsideClick: 'fixed',
|
|
274
|
+
copyFormatKeepOn: true,
|
|
275
|
+
syncTabIndent: true,
|
|
276
|
+
tabDisable: true,
|
|
277
|
+
autoLinkify: true,
|
|
278
|
+
autoStyleify: true,
|
|
279
|
+
scrollToOptions: true,
|
|
280
|
+
componentScrollToOptions: true,
|
|
281
|
+
retainStyleMode: true,
|
|
282
|
+
allowedExtraTags: 'fixed',
|
|
283
|
+
events: true,
|
|
284
|
+
__textStyleTags: 'fixed',
|
|
285
|
+
textStyleTags: 'fixed',
|
|
286
|
+
convertTextTags: 'fixed',
|
|
287
|
+
__tagStyles: 'fixed',
|
|
288
|
+
tagStyles: 'fixed',
|
|
289
|
+
spanStyles: 'fixed',
|
|
290
|
+
lineStyles: 'fixed',
|
|
291
|
+
textDirection: true,
|
|
292
|
+
reverseButtons: 'fixed',
|
|
293
|
+
historyStackDelayTime: true,
|
|
294
|
+
lineAttrReset: true,
|
|
295
|
+
printClass: true,
|
|
296
|
+
defaultLine: 'fixed',
|
|
297
|
+
defaultLineBreakFormat: true,
|
|
298
|
+
scopeSelectionTags: true,
|
|
299
|
+
__defaultElementWhitelist: 'fixed',
|
|
300
|
+
elementWhitelist: 'fixed',
|
|
301
|
+
elementBlacklist: 'fixed',
|
|
302
|
+
__defaultAttributeWhitelist: 'fixed',
|
|
303
|
+
attributeWhitelist: 'fixed',
|
|
304
|
+
attributeBlacklist: 'fixed',
|
|
305
|
+
__defaultFormatLine: 'fixed',
|
|
306
|
+
formatLine: 'fixed',
|
|
307
|
+
__defaultFormatBrLine: 'fixed',
|
|
308
|
+
formatBrLine: 'fixed',
|
|
309
|
+
__defaultFormatClosureBrLine: 'fixed',
|
|
310
|
+
formatClosureBrLine: 'fixed',
|
|
311
|
+
__defaultFormatBlock: 'fixed',
|
|
312
|
+
formatBlock: 'fixed',
|
|
313
|
+
__defaultFormatClosureBlock: 'fixed',
|
|
314
|
+
formatClosureBlock: 'fixed',
|
|
315
|
+
allowedEmptyTags: true,
|
|
316
|
+
toolbar_width: true,
|
|
317
|
+
toolbar_container: 'fixed',
|
|
318
|
+
toolbar_sticky: true,
|
|
319
|
+
toolbar_hide: true,
|
|
320
|
+
subToolbar: 'fixed',
|
|
321
|
+
statusbar_container: 'fixed',
|
|
322
|
+
shortcutsHint: true,
|
|
323
|
+
shortcutsDisable: 'fixed',
|
|
324
|
+
shortcuts: 'fixed',
|
|
325
|
+
fullScreenOffset: true,
|
|
326
|
+
previewTemplate: true,
|
|
327
|
+
printTemplate: true,
|
|
328
|
+
componentAutoSelect: true,
|
|
329
|
+
defaultUrlProtocol: true,
|
|
330
|
+
allUsedStyles: 'fixed',
|
|
331
|
+
toastMessageTime: true,
|
|
332
|
+
icons: 'fixed',
|
|
333
|
+
freeCodeViewMode: true,
|
|
334
|
+
__lineFormatFilter: true,
|
|
335
|
+
__pluginRetainFilter: true,
|
|
336
|
+
__listCommonStyle: 'fixed',
|
|
337
|
+
externalLibs: 'fixed'
|
|
338
|
+
};
|
|
339
|
+
|
|
258
340
|
/**
|
|
259
341
|
* @description Creates a new SunEditor instance with specified options.
|
|
260
342
|
* @param {Array<{target: Element, key: *, options: EditorFrameOptions}>} editorTargets - Target element or multi-root object.
|
|
@@ -364,7 +446,7 @@ function Constructor(editorTargets, options) {
|
|
|
364
446
|
const to = optionMap.frameMap.get(editTarget.key);
|
|
365
447
|
const top_div = dom.utils.createElement('DIV', { class: 'sun-editor' + o.get('_themeClass') + (o.get('_rtl') ? ' se-rtl' : '') });
|
|
366
448
|
const container = dom.utils.createElement('DIV', { class: 'se-container' });
|
|
367
|
-
const editor_div = dom.utils.createElement('DIV', { class: 'se-wrapper' + (o.get('type') === 'document' ? ' se-type-document' : '') });
|
|
449
|
+
const editor_div = dom.utils.createElement('DIV', { class: 'se-wrapper' + (o.get('type') === 'document' ? ' se-type-document' : '') + (o.get('_type_options').includes('header') ? ' se-type-document-header' : '') });
|
|
368
450
|
|
|
369
451
|
container.appendChild(dom.utils.createElement('DIV', { class: 'se-toolbar-shadow' }));
|
|
370
452
|
|
|
@@ -424,10 +506,10 @@ function Constructor(editorTargets, options) {
|
|
|
424
506
|
|
|
425
507
|
// document type
|
|
426
508
|
const documentTypeInner = { inner: null, page: null, pageMirror: null };
|
|
427
|
-
if (o.get('
|
|
509
|
+
if (o.get('_type_options').includes('header')) {
|
|
428
510
|
documentTypeInner.inner = dom.utils.createElement('DIV', { class: 'se-document-lines', style: `height: ${to.get('height')};` }, '<div class="se-document-lines-inner"></div>');
|
|
429
511
|
}
|
|
430
|
-
if (o.get('
|
|
512
|
+
if (o.get('_type_options').includes('page')) {
|
|
431
513
|
documentTypeInner.page = dom.utils.createElement('DIV', { class: 'se-document-page' }, null);
|
|
432
514
|
documentTypeInner.pageMirror = dom.utils.createElement(
|
|
433
515
|
'DIV',
|
|
@@ -500,13 +582,16 @@ export function CreateShortcuts(command, button, values, keyMap, rc, reverseKeys
|
|
|
500
582
|
plugin = null;
|
|
501
583
|
method = a[a.length - 1].trim?.();
|
|
502
584
|
if (method.startsWith('~')) {
|
|
585
|
+
// plugin key, method
|
|
503
586
|
plugin = command;
|
|
504
587
|
method = a.pop().trim().substring(1);
|
|
505
|
-
} else if (method.startsWith('
|
|
588
|
+
} else if (method.startsWith('$~')) {
|
|
589
|
+
// custom key, plugin method
|
|
506
590
|
const a_ = a.pop().trim().substring(2).split('.');
|
|
507
591
|
plugin = a_[0];
|
|
508
592
|
method = a_[1];
|
|
509
593
|
} else if (method.startsWith('$')) {
|
|
594
|
+
// directly method
|
|
510
595
|
_i = 1;
|
|
511
596
|
method = values[i + 2];
|
|
512
597
|
} else {
|
|
@@ -539,13 +624,16 @@ export function CreateShortcuts(command, button, values, keyMap, rc, reverseKeys
|
|
|
539
624
|
}
|
|
540
625
|
}
|
|
541
626
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
627
|
+
v = v.split('|');
|
|
628
|
+
for (let j = 0, len = v.length; j < len; j++) {
|
|
629
|
+
k = c ? v[j] + (s ? '1000' : '') : v[j];
|
|
630
|
+
if (!keyMap.has(k)) {
|
|
631
|
+
r = rc.indexOf(command);
|
|
632
|
+
r = r === -1 ? '' : numbers.isOdd(r) ? rc[r + 1] : rc[r - 1];
|
|
633
|
+
if (r) reverseKeys.push(k);
|
|
547
634
|
|
|
548
|
-
|
|
635
|
+
keyMap.set(k, { c, s, edge, space, enter, textTrigger, plugin, command, method, r, type: button?.getAttribute('data-type'), button, key: k });
|
|
636
|
+
}
|
|
549
637
|
}
|
|
550
638
|
|
|
551
639
|
if (!(t = values[i + 1])) continue;
|
|
@@ -619,7 +707,7 @@ export function InitOptions(options, editorTargets, plugins) {
|
|
|
619
707
|
o.set('type', options.type?.split(':')[0] || ''); // document:header,page
|
|
620
708
|
o.set('theme', options.theme || '');
|
|
621
709
|
o.set('_themeClass', options.theme ? ` se-theme-${options.theme}` : '');
|
|
622
|
-
o.set('
|
|
710
|
+
o.set('_type_options', options.type?.split(':')[1] || '');
|
|
623
711
|
o.set('externalLibs', options.externalLibs || {});
|
|
624
712
|
o.set('fontSizeUnits', Array.isArray(options.fontSizeUnits) && options.fontSizeUnits.length > 0 ? options.fontSizeUnits.map((v) => v.toLowerCase()) : DEFAULT_SIZE_UNITS);
|
|
625
713
|
o.set('allowedClassName', new RegExp(`${options.allowedClassName && typeof options.allowedClassName === 'string' ? options.allowedClassName + '|' : ''}${DEFAULT_CLASS_NAME}`));
|
|
@@ -735,7 +823,8 @@ export function InitOptions(options, editorTargets, plugins) {
|
|
|
735
823
|
/** whitelist, blacklist */
|
|
736
824
|
// default line
|
|
737
825
|
o.set('defaultLine', typeof options.defaultLine === 'string' && options.defaultLine.length > 0 ? options.defaultLine : 'p');
|
|
738
|
-
o.set('
|
|
826
|
+
o.set('defaultLineBreakFormat', options.defaultLineBreakFormat || 'line');
|
|
827
|
+
o.set('scopeSelectionTags', options.scopeSelectionTags || DEFAULT_SCOPE_SELECTION_TAGS.split('|'));
|
|
739
828
|
// element
|
|
740
829
|
const elw = (typeof options.elementWhitelist === 'string' ? options.elementWhitelist : '').toLowerCase();
|
|
741
830
|
const mjxEls = o.get('externalLibs').mathjax ? DEFAULT_CLASS_MJX + '|' : '';
|
|
@@ -851,9 +940,9 @@ export function InitOptions(options, editorTargets, plugins) {
|
|
|
851
940
|
list_numbered: ['!+1.+_+~shortcut', ''],
|
|
852
941
|
list_bulleted: ['!+*.+_+~shortcut', ''],
|
|
853
942
|
// custom
|
|
854
|
-
_h1: ['c+s+Digit1
|
|
855
|
-
_h2: ['c+s+Digit2
|
|
856
|
-
_h3: ['c+s+Digit3
|
|
943
|
+
_h1: ['c+s+Digit1|Numpad1+$~formatBlock.applyHeaderByShortcut', ''],
|
|
944
|
+
_h2: ['c+s+Digit2|Numpad2+$~formatBlock.applyHeaderByShortcut', ''],
|
|
945
|
+
_h3: ['c+s+Digit3|Numpad3+$~formatBlock.applyHeaderByShortcut', '']
|
|
857
946
|
},
|
|
858
947
|
options.shortcuts || {}
|
|
859
948
|
].reduce((_default, _new) => {
|
|
@@ -1040,6 +1129,7 @@ function InitFrameOptions(o, origin) {
|
|
|
1040
1129
|
fo.set('height', height ? (numbers.is(height) ? height + 'px' : height) : 'auto');
|
|
1041
1130
|
fo.set('minHeight', (numbers.is(minHeight) ? minHeight + 'px' : minHeight) || '');
|
|
1042
1131
|
fo.set('maxHeight', (numbers.is(maxHeight) ? maxHeight + 'px' : maxHeight) || '');
|
|
1132
|
+
fo.set('editorStyle', editorStyle);
|
|
1043
1133
|
fo.set('_defaultStyles', converter._setDefaultOptionStyle(fo, typeof editorStyle === 'string' ? editorStyle : ''));
|
|
1044
1134
|
// iframe
|
|
1045
1135
|
fo.set('iframe', !!(iframe_fullPage || iframe));
|
|
@@ -1100,9 +1190,8 @@ function _initTargetElements(key, options, topDiv, targetOptions) {
|
|
|
1100
1190
|
|
|
1101
1191
|
// textarea for code view
|
|
1102
1192
|
const textarea = dom.utils.createElement('TEXTAREA', { class: 'se-wrapper-inner se-code-viewer', style: editorStyles.frame });
|
|
1103
|
-
|
|
1193
|
+
const placeholder = dom.utils.createElement('SPAN', { class: 'se-placeholder' });
|
|
1104
1194
|
if (targetOptions.get('placeholder')) {
|
|
1105
|
-
placeholder = dom.utils.createElement('SPAN', { class: 'se-placeholder' });
|
|
1106
1195
|
placeholder.textContent = targetOptions.get('placeholder');
|
|
1107
1196
|
}
|
|
1108
1197
|
|
|
@@ -43,8 +43,8 @@ function DocumentType(editor, fc) {
|
|
|
43
43
|
this.pages = [];
|
|
44
44
|
this.pages_line = [];
|
|
45
45
|
this.prevScrollTop = 0;
|
|
46
|
-
this.useHeader = editor.options.get('
|
|
47
|
-
this.usePage = editor.options.get('
|
|
46
|
+
this.useHeader = editor.options.get('_type_options').includes('header');
|
|
47
|
+
this.usePage = editor.options.get('_type_options').includes('page');
|
|
48
48
|
this.navigatorButtons = [];
|
|
49
49
|
this.pageNavigator = null;
|
|
50
50
|
this._mirror = fc.get('documentTypePageMirror');
|
package/src/events.js
CHANGED
|
@@ -161,12 +161,24 @@ export default {
|
|
|
161
161
|
*/
|
|
162
162
|
onFocus: null,
|
|
163
163
|
|
|
164
|
+
/**
|
|
165
|
+
* @description Event call back function
|
|
166
|
+
* @param {BaseEvent} params
|
|
167
|
+
*/
|
|
168
|
+
onNativeFocus: null,
|
|
169
|
+
|
|
164
170
|
/**
|
|
165
171
|
* @description Event call back function
|
|
166
172
|
* @param {BaseEvent} params
|
|
167
173
|
*/
|
|
168
174
|
onBlur: null,
|
|
169
175
|
|
|
176
|
+
/**
|
|
177
|
+
* @description Event call back function
|
|
178
|
+
* @param {BaseEvent} params
|
|
179
|
+
*/
|
|
180
|
+
onNativeBlur: null,
|
|
181
|
+
|
|
170
182
|
/**
|
|
171
183
|
* @description Event function on copy
|
|
172
184
|
* @param {Object} params
|
|
@@ -606,5 +618,17 @@ export default {
|
|
|
606
618
|
* @param {EmbedInfo} params.info - info object
|
|
607
619
|
* @param {(newInfo?: EmbedInfo|null) => void} params.handler - handler function
|
|
608
620
|
*/
|
|
609
|
-
onEmbedInputBefore: null
|
|
621
|
+
onEmbedInputBefore: null,
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* @description Called before the embed is deleted
|
|
625
|
+
* @param {Object} params
|
|
626
|
+
* @param {__se__EditorCore} params.editor - The root editor instance
|
|
627
|
+
* @param {HTMLElement} params.element - target element
|
|
628
|
+
* @param {HTMLElement} params.container - target's container element (div)
|
|
629
|
+
* @param {string} params.align - align value
|
|
630
|
+
* @param {string} params.url - embed url
|
|
631
|
+
* @returns {Promise<boolean>}
|
|
632
|
+
*/
|
|
633
|
+
onEmbedDeleteBefore: null
|
|
610
634
|
};
|
package/src/helper/converter.js
CHANGED
|
@@ -170,6 +170,26 @@ export function syncMaps(targetMap, referenceMap) {
|
|
|
170
170
|
});
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
/**
|
|
174
|
+
* @description Merges multiple Map objects into a new Map using spread syntax.
|
|
175
|
+
* - Entries from later maps in the arguments list will overwrite entries from earlier maps if keys conflict.
|
|
176
|
+
* - The original maps are not modified.
|
|
177
|
+
* @param {...Map<*, *>} mapsToMerge - An arbitrary number of Map objects to merge.
|
|
178
|
+
* @returns {Map<*, *>} A new Map containing all entries from the input maps.
|
|
179
|
+
*/
|
|
180
|
+
export function mergeMaps(...mapsToMerge) {
|
|
181
|
+
const validMaps = mapsToMerge.filter((m) => {
|
|
182
|
+
if (!(m instanceof Map)) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
return true;
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const allEntries = validMaps.flatMap((map) => [...map]);
|
|
189
|
+
|
|
190
|
+
return new Map(allEntries);
|
|
191
|
+
}
|
|
192
|
+
|
|
173
193
|
/**
|
|
174
194
|
* @description Object.values
|
|
175
195
|
* @param {Object<*, *>} obj Object parameter.
|
|
@@ -269,8 +289,9 @@ export function nodeListToArray(nodeList) {
|
|
|
269
289
|
export function swapKeyValue(obj) {
|
|
270
290
|
const swappedObj = {};
|
|
271
291
|
|
|
292
|
+
const hasOwn = Object.prototype.hasOwnProperty;
|
|
272
293
|
for (const key in obj) {
|
|
273
|
-
if (
|
|
294
|
+
if (hasOwn.call(obj, key)) {
|
|
274
295
|
swappedObj[obj[key]] = key;
|
|
275
296
|
}
|
|
276
297
|
}
|
|
@@ -542,6 +563,7 @@ const converter = {
|
|
|
542
563
|
entityToHTML,
|
|
543
564
|
debounce,
|
|
544
565
|
syncMaps,
|
|
566
|
+
mergeMaps,
|
|
545
567
|
getValues,
|
|
546
568
|
camelToKebabCase,
|
|
547
569
|
kebabToCamelCase,
|
|
@@ -162,6 +162,15 @@ export function isFigure(node) {
|
|
|
162
162
|
return /^FIGURE$/i.test(typeof node === 'string' ? node : node?.nodeName);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
/**
|
|
166
|
+
* @description Checks whether the given node is a content-less (void) HTML tag
|
|
167
|
+
* @param {?Node|string} node The element or element name to check
|
|
168
|
+
* @returns {boolean}
|
|
169
|
+
*/
|
|
170
|
+
export function isContentLess(node) {
|
|
171
|
+
return /^(BR|COLGROUP|COL|THEAD|TBODY|TFOOT|TR|AREA|BASE|EMBED|HR|IMG|INPUT|KEYGEN|LINK|META|PARAM|SOURCE|TRACK|WBR)$/i.test(typeof node === 'string' ? node : node?.nodeName);
|
|
172
|
+
}
|
|
173
|
+
|
|
165
174
|
/**
|
|
166
175
|
* @description Check the line element is empty.
|
|
167
176
|
* @param {Node} node "line" element node
|
|
@@ -170,7 +179,7 @@ export function isFigure(node) {
|
|
|
170
179
|
export function isEmptyLine(node) {
|
|
171
180
|
if (!node?.parentNode) return true;
|
|
172
181
|
const el = /** @type {HTMLElement} */ (node);
|
|
173
|
-
return !el.querySelector('IMG, IFRAME, AUDIO, VIDEO, CANVAS, TABLE') && el.children.length
|
|
182
|
+
return !el.querySelector('IMG, IFRAME, AUDIO, VIDEO, CANVAS, TABLE') && (el.children.length <= 1 || isBreak(el.firstElementChild)) && isZeroWidth(el.textContent);
|
|
174
183
|
}
|
|
175
184
|
|
|
176
185
|
/**
|
|
@@ -179,7 +188,7 @@ export function isEmptyLine(node) {
|
|
|
179
188
|
* @returns {node is HTMLElement}
|
|
180
189
|
*/
|
|
181
190
|
export function isWysiwygFrame(node) {
|
|
182
|
-
return node?.nodeType === 1 && (domUtils.hasClass(node, 'se-wrapper-wysiwyg|sun-editor-carrier-wrapper') || /^BODY$/i.test(node.nodeName));
|
|
191
|
+
return node?.nodeType === 1 && (domUtils.hasClass(node, 'se-wrapper-wysiwyg|sun-editor-carrier-wrapper|se-wrapper') || /^BODY$/i.test(node.nodeName));
|
|
183
192
|
}
|
|
184
193
|
|
|
185
194
|
/**
|
|
@@ -281,6 +290,7 @@ const check = {
|
|
|
281
290
|
isMedia,
|
|
282
291
|
isIFrame,
|
|
283
292
|
isFigure,
|
|
293
|
+
isContentLess,
|
|
284
294
|
isEmptyLine,
|
|
285
295
|
isWysiwygFrame,
|
|
286
296
|
isNonEditable,
|
|
@@ -108,10 +108,12 @@ class Controller extends EditorInjector {
|
|
|
108
108
|
if (this.editor.isBalloon) this.toolbar.hide();
|
|
109
109
|
else if (this.editor.isSubBalloon) this.subToolbar.hide();
|
|
110
110
|
|
|
111
|
-
if (
|
|
112
|
-
this.
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
if (!this.status.hasFocus) {
|
|
112
|
+
if (disabled ?? this.disabled) {
|
|
113
|
+
this.ui.setControllerOnDisabledButtons(true);
|
|
114
|
+
} else {
|
|
115
|
+
this.ui.setControllerOnDisabledButtons(false);
|
|
116
|
+
}
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
this.currentPositionTarget = positionTarget || target;
|
|
@@ -429,6 +431,7 @@ class Controller extends EditorInjector {
|
|
|
429
431
|
if (this.form.contains(eventTarget) || this._checkForm(eventTarget)) return;
|
|
430
432
|
if (this.editor._fileManager.pluginRegExp.test(this.kind) && !keyCodeMap.isEsc(keyCode)) return;
|
|
431
433
|
|
|
434
|
+
this.#PostCloseEvent(eventTarget);
|
|
432
435
|
this.close();
|
|
433
436
|
}
|
|
434
437
|
|
|
@@ -443,12 +446,29 @@ class Controller extends EditorInjector {
|
|
|
443
446
|
}
|
|
444
447
|
|
|
445
448
|
this.isOpen = true;
|
|
446
|
-
if (
|
|
449
|
+
if (
|
|
450
|
+
eventTarget === this.inst._element ||
|
|
451
|
+
eventTarget === this.currentTarget ||
|
|
452
|
+
this._checkFixed() ||
|
|
453
|
+
this.form.contains(eventTarget) ||
|
|
454
|
+
this._checkForm(eventTarget) ||
|
|
455
|
+
dom.query.getParentElement(eventTarget, '.se-line-breaker-component')
|
|
456
|
+
) {
|
|
447
457
|
return;
|
|
448
458
|
}
|
|
449
459
|
|
|
460
|
+
this.#PostCloseEvent(eventTarget);
|
|
450
461
|
this.close(true);
|
|
451
462
|
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* @param {HTMLElement} eventTarget - The target element that triggered the event.
|
|
466
|
+
*/
|
|
467
|
+
#PostCloseEvent(eventTarget) {
|
|
468
|
+
if (!this.editor.frameContext.get('wysiwyg').contains(eventTarget)) {
|
|
469
|
+
this.component.__prevent = false;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
452
472
|
}
|
|
453
473
|
|
|
454
474
|
export default Controller;
|
package/src/modules/Figure.js
CHANGED
|
@@ -652,7 +652,7 @@ class Figure extends EditorInjector {
|
|
|
652
652
|
*/
|
|
653
653
|
_asFormatChange(figureinfo, w, h) {
|
|
654
654
|
const kind = this.kind;
|
|
655
|
-
figureinfo.target.onload = () => this.component.select(figureinfo.target, kind
|
|
655
|
+
figureinfo.target.onload = () => this.component.select(figureinfo.target, kind);
|
|
656
656
|
|
|
657
657
|
this._setFigureInfo(figureinfo);
|
|
658
658
|
|
|
@@ -745,7 +745,7 @@ class Figure extends EditorInjector {
|
|
|
745
745
|
|
|
746
746
|
this.history.push(false);
|
|
747
747
|
if (!/^remove|caption$/.test(command)) {
|
|
748
|
-
this.component.select(element, this.kind
|
|
748
|
+
this.component.select(element, this.kind);
|
|
749
749
|
}
|
|
750
750
|
}
|
|
751
751
|
|
|
@@ -1318,7 +1318,7 @@ class Figure extends EditorInjector {
|
|
|
1318
1318
|
}
|
|
1319
1319
|
|
|
1320
1320
|
this.history.push(false);
|
|
1321
|
-
this.component.select(this._element, this.kind
|
|
1321
|
+
this.component.select(this._element, this.kind);
|
|
1322
1322
|
}
|
|
1323
1323
|
|
|
1324
1324
|
/**
|
|
@@ -1328,7 +1328,7 @@ class Figure extends EditorInjector {
|
|
|
1328
1328
|
#ContainerResizingESC(e) {
|
|
1329
1329
|
if (!keyCodeMap.isEsc(e.code)) return;
|
|
1330
1330
|
this._offResizeEvent();
|
|
1331
|
-
this.component.select(this._element, this.kind
|
|
1331
|
+
this.component.select(this._element, this.kind);
|
|
1332
1332
|
}
|
|
1333
1333
|
|
|
1334
1334
|
/**
|
|
@@ -1337,7 +1337,7 @@ class Figure extends EditorInjector {
|
|
|
1337
1337
|
#SetMenuAlign(value) {
|
|
1338
1338
|
this.setAlign(this._element, value);
|
|
1339
1339
|
this.selectMenu_align.close();
|
|
1340
|
-
this.component.select(this._element, this.kind
|
|
1340
|
+
this.component.select(this._element, this.kind);
|
|
1341
1341
|
}
|
|
1342
1342
|
|
|
1343
1343
|
/**
|
|
@@ -1367,7 +1367,7 @@ class Figure extends EditorInjector {
|
|
|
1367
1367
|
}
|
|
1368
1368
|
|
|
1369
1369
|
this.selectMenu_resize.close();
|
|
1370
|
-
this.component.select(this._element, this.kind
|
|
1370
|
+
this.component.select(this._element, this.kind);
|
|
1371
1371
|
}
|
|
1372
1372
|
|
|
1373
1373
|
#OffFigureContainer() {
|
|
@@ -202,7 +202,7 @@ class FileManager extends CoreInjector {
|
|
|
202
202
|
el.scrollIntoView(this.options.get('componentScrollToOptions'));
|
|
203
203
|
const comp = this.component.get(el);
|
|
204
204
|
if (comp) {
|
|
205
|
-
this.component.select(comp.target, comp.pluginName
|
|
205
|
+
this.component.select(comp.target, comp.pluginName);
|
|
206
206
|
} else if (typeof this.inst.select === 'function') {
|
|
207
207
|
this.inst.select(el);
|
|
208
208
|
}
|
|
@@ -184,7 +184,7 @@ class FileUpload extends EditorInjector {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
this.controller.close();
|
|
187
|
-
this.component.select(this._element, FileUpload.key
|
|
187
|
+
this.component.select(this._element, FileUpload.key);
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
/**
|
|
@@ -321,7 +321,7 @@ class FileUpload extends EditorInjector {
|
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
this.history.push(false);
|
|
324
|
-
this.component.select(target, FileUpload.key
|
|
324
|
+
this.component.select(target, FileUpload.key);
|
|
325
325
|
}
|
|
326
326
|
|
|
327
327
|
/**
|
|
@@ -368,7 +368,7 @@ class FileUpload extends EditorInjector {
|
|
|
368
368
|
const line = this.format.addLine(figure.container, null);
|
|
369
369
|
if (line) this.selection.setRange(line, 0, line, 0);
|
|
370
370
|
} else {
|
|
371
|
-
this.component.select(a, FileUpload.key
|
|
371
|
+
this.component.select(a, FileUpload.key);
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
374
|
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import EditorInjector from '../../editorInjector';
|
|
2
2
|
import { dom } from '../../helper';
|
|
3
3
|
|
|
4
|
-
const HEADER_KEYCODE = new Map([
|
|
5
|
-
['Digit1', 'h1'],
|
|
6
|
-
['Digit2', 'h2'],
|
|
7
|
-
['Digit3', 'h3'],
|
|
8
|
-
['Digit4', 'h4'],
|
|
9
|
-
['Digit5', 'h5'],
|
|
10
|
-
['Digit6', 'h6']
|
|
11
|
-
]);
|
|
12
|
-
|
|
13
4
|
/**
|
|
14
5
|
* @class
|
|
15
6
|
* @description FormatBlock Plugin (P, BLOCKQUOTE, PRE, H1, H2...)
|
|
@@ -125,12 +116,12 @@ class FormatBlock extends EditorInjector {
|
|
|
125
116
|
|
|
126
117
|
/**
|
|
127
118
|
* @description Create a header tag, call by "shortcut" class
|
|
128
|
-
* - (e.g. shortcuts._h1: ['c+s+49
|
|
119
|
+
* - (e.g. shortcuts._h1: ['c+s+49+$~formatBlock.applyHeaderByShortcut', ''])
|
|
129
120
|
* @param {__se__PluginShortcutInfo} params - Information of the "shortcut" plugin
|
|
130
121
|
*/
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
const tag = dom.utils.createElement(
|
|
122
|
+
applyHeaderByShortcut({ keyCode }) {
|
|
123
|
+
const headerNum = keyCode.match(/\d+$/)?.[0];
|
|
124
|
+
const tag = dom.utils.createElement(`H${headerNum}`);
|
|
134
125
|
this.format.setLine(tag);
|
|
135
126
|
}
|
|
136
127
|
}
|