suneditor 3.0.0-beta.1 → 3.0.0-beta.2

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.
Files changed (47) hide show
  1. package/CONTRIBUTING.md +166 -29
  2. package/README.md +13 -1
  3. package/dist/suneditor.min.css +1 -1
  4. package/dist/suneditor.min.js +1 -1
  5. package/package.json +13 -5
  6. package/src/assets/{variables.css → design/color.css} +34 -58
  7. package/src/assets/design/index.css +3 -0
  8. package/src/assets/design/size.css +35 -0
  9. package/src/assets/design/typography.css +37 -0
  10. package/src/assets/suneditor-contents.css +1 -1
  11. package/src/assets/suneditor.css +24 -17
  12. package/src/core/base/eventHandlers/handler_ww_key_input.js +15 -15
  13. package/src/core/base/eventHandlers/handler_ww_mouse.js +1 -1
  14. package/src/core/base/eventManager.js +21 -9
  15. package/src/core/class/component.js +21 -11
  16. package/src/core/class/menu.js +19 -0
  17. package/src/core/editor.js +3 -3
  18. package/src/core/section/actives.js +42 -4
  19. package/src/core/section/constructor.js +116 -41
  20. package/src/core/section/documentType.js +2 -2
  21. package/src/events.js +13 -1
  22. package/src/helper/dom/domCheck.js +10 -0
  23. package/src/modules/Figure.js +6 -6
  24. package/src/modules/FileManager.js +1 -1
  25. package/src/plugins/command/fileUpload.js +3 -3
  26. package/src/plugins/dropdown/table.js +51 -18
  27. package/src/plugins/modal/audio.js +2 -2
  28. package/src/plugins/modal/embed.js +2 -2
  29. package/src/plugins/modal/image.js +3 -3
  30. package/src/plugins/modal/math.js +2 -2
  31. package/src/plugins/modal/video.js +1 -1
  32. package/src/plugins/popup/anchor.js +1 -1
  33. package/src/suneditor.js +1 -1
  34. package/src/themes/dark.css +78 -45
  35. package/types/core/base/eventManager.d.ts +7 -0
  36. package/types/core/class/component.d.ts +12 -3
  37. package/types/core/class/menu.d.ts +8 -0
  38. package/types/core/section/constructor.d.ts +160 -149
  39. package/types/events.d.ts +1 -0
  40. package/types/helper/dom/domCheck.d.ts +7 -0
  41. package/types/helper/index.d.ts +1 -0
  42. package/types/index.d.ts +1 -1
  43. package/types/plugins/dropdown/table.d.ts +1 -0
  44. package/.eslintignore +0 -7
  45. package/.eslintrc.json +0 -81
  46. /package/src/assets/icons/{_default.js → defaultIcons.js} +0 -0
  47. /package/types/assets/icons/{_default.d.ts → defaultIcons.d.ts} +0 -0
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import CoreInjector from '../../editorInjector/_core';
6
- import { dom, env, numbers, unicode, keyCodeMap } from '../../helper';
6
+ import { dom, env, numbers, unicode, keyCodeMap, converter } from '../../helper';
7
7
  import { Figure, _DragHandle } from '../../modules';
8
8
 
9
9
  const { _w, ON_OVER_COMPONENT, isMobile } = env;
@@ -220,12 +220,10 @@ Component.prototype = {
220
220
  * @description The component(media, file component, table, etc) is selected and the resizing module is called.
221
221
  * @param {Node} element Target element
222
222
  * @param {string} pluginName The plugin name for the selected target.
223
- * @param {boolean} [isInput=false] Whether the target is an input component.(table)
224
- * @param {boolean} [force=false] Forces the component selection action again even if it is already selected.
223
+ * @param {Object} [options] Options
224
+ * @param {boolean} [options.isInput=false] Whether the target is an input component.(table)
225
225
  */
226
- select(element, pluginName, isInput, force) {
227
- if (!force && element === this.currentTarget && this.editor.currentControllerName === this.currentPluginName) return;
228
-
226
+ select(element, pluginName, { isInput = false } = {}) {
229
227
  const info = this.get(element);
230
228
  if (!info || dom.check.isUneditable(dom.query.getParentElement(element, this.is.bind(this))) || dom.check.isUneditable(element)) return false;
231
229
 
@@ -267,7 +265,10 @@ Component.prototype = {
267
265
  if (__overInfo !== ON_OVER_COMPONENT) this.__addGlobalEvent();
268
266
  if (!info.isFile) this.__addNotFileGlobalEvent();
269
267
  }, 0);
270
- dom.utils.addClass(info.container, 'se-component-selected');
268
+
269
+ converter.debounce(() => {
270
+ dom.utils.addClass(info.container, 'se-component-selected');
271
+ }, 0)();
271
272
 
272
273
  if (!isBreakComponent && __overInfo !== ON_OVER_COMPONENT) {
273
274
  // set zero width space
@@ -299,7 +300,7 @@ Component.prototype = {
299
300
  dragHandle.style.opacity = 0;
300
301
  dragHandle.style.width = w + 'px';
301
302
  dragHandle.style.height = h + 'px';
302
- dragHandle.style.top = top - 1 + 'px';
303
+ dragHandle.style.top = top + 'px';
303
304
  dragHandle.style.left = left + 'px';
304
305
 
305
306
  _DragHandle.set('__dragHandler', dragHandle);
@@ -416,8 +417,15 @@ Component.prototype = {
416
417
  this.editor._preventBlur = false;
417
418
  _DragHandle.set('__overInfo', null);
418
419
  this._removeDragEvent();
419
- dom.utils.removeClass(this.currentInfo?.container, 'se-component-selected|');
420
- dom.utils.removeClass(this.currentInfo?.cover, 'se-figure-over-selected');
420
+
421
+ if (this.currentInfo) {
422
+ const infoContainer = this.currentInfo.container;
423
+ const infoCover = this.currentInfo.cover;
424
+ converter.debounce(() => {
425
+ dom.utils.removeClass(infoContainer, 'se-component-selected');
426
+ dom.utils.removeClass(infoCover, 'se-figure-over-selected');
427
+ }, 0)();
428
+ }
421
429
 
422
430
  const { frameContext } = this.editor;
423
431
  frameContext.get('lineBreaker_t').style.display = frameContext.get('lineBreaker_b').style.display = 'none';
@@ -483,6 +491,7 @@ Component.prototype = {
483
491
  else dom.utils.addClass(lb_t, 'se-on-selected');
484
492
 
485
493
  t_style.display = 'block';
494
+ t_style.visibility = '';
486
495
  } else {
487
496
  t_style.display = 'none';
488
497
  }
@@ -508,6 +517,7 @@ Component.prototype = {
508
517
  else dom.utils.addClass(lb_b, 'se-on-selected');
509
518
 
510
519
  b_style.display = 'block';
520
+ b_style.visibility = '';
511
521
  } else {
512
522
  b_style.display = 'none';
513
523
  }
@@ -637,7 +647,7 @@ function OnDragClick(e) {
637
647
 
638
648
  const dragInst = _DragHandle.get('__dragInst');
639
649
  this._removeDragEvent();
640
- this.select(dragInst.currentTarget, dragInst.currentPluginName, false);
650
+ this.select(dragInst.currentTarget, dragInst.currentPluginName);
641
651
  }
642
652
 
643
653
  /**
@@ -45,6 +45,10 @@ function Menu(editor) {
45
45
  this._bindClose_dropdown_key = null;
46
46
  this._bindClose_cons_mouse = null;
47
47
  this.currentDropdownPlugin = null;
48
+
49
+ // eventManager member (viewport)
50
+ this.__menuBtn = null;
51
+ this.__menuContainer = null;
48
52
  }
49
53
 
50
54
  Menu.prototype = {
@@ -115,6 +119,8 @@ Menu.prototype = {
115
119
  this.__removeGlobalEvent();
116
120
  this.index = -1;
117
121
  this.menus = [];
122
+ this.__menuBtn = null;
123
+ this.__menuContainer = null;
118
124
 
119
125
  if (this.currentDropdown) {
120
126
  this.currentDropdownName = '';
@@ -187,6 +193,19 @@ Menu.prototype = {
187
193
  this.offset.setRelPosition(menu, this.carrierWrapper, element.parentElement, dom.query.getParentElement(element, '.se-toolbar'), false);
188
194
 
189
195
  menu.style.visibility = '';
196
+
197
+ this.__menuBtn = element;
198
+ this.__menuContainer = menu;
199
+ },
200
+
201
+ /**
202
+ * @private
203
+ * @this {MenuThis}
204
+ * @description Restore the last menu position using previously stored button and menu elements.
205
+ */
206
+ _restoreMenuPosition() {
207
+ if (!this.__menuBtn || !this.__menuContainer) return;
208
+ this._setMenuPosition(this.__menuBtn, this.__menuContainer);
190
209
  },
191
210
 
192
211
  /**
@@ -1,5 +1,5 @@
1
1
  import { env, converter, dom, numbers } from '../helper';
2
- import Constructor, { InitOptions, UpdateButton, CreateShortcuts, CreateStatusbar, RO_UNAVAILABD } from './section/constructor';
2
+ import Constructor, { InitOptions, UpdateButton, CreateShortcuts, CreateStatusbar, OPTION_FIXED_FLAG } from './section/constructor';
3
3
  import { UpdateStatusbarContext } from './section/context';
4
4
  import { BASIC_COMMANDS, ACTIVE_EVENT_COMMANDS, SELECT_ALL, DIR_BTN_ACTIVE, SAVE, COPY_FORMAT, FONT_STYLE, PAGE_BREAK } from './section/actives';
5
5
  import History from './base/history';
@@ -971,7 +971,7 @@ Editor.prototype = {
971
971
 
972
972
  const fileComponentInfo = this.component.get(focusEl);
973
973
  if (fileComponentInfo) {
974
- this.component.select(fileComponentInfo.target, fileComponentInfo.pluginName, false);
974
+ this.component.select(fileComponentInfo.target, fileComponentInfo.pluginName);
975
975
  } else if (focusEl) {
976
976
  if (focusEl.nodeType !== 3) {
977
977
  focusEl = dom.query.getEdgeChild(
@@ -1697,7 +1697,7 @@ function GetResetDiffKey(key) {
1697
1697
  function CheckResetKeys(keys, plugins, root) {
1698
1698
  for (let i = 0, len = keys.length, k; i < len; i++) {
1699
1699
  k = keys[i];
1700
- if (RO_UNAVAILABD.includes(k) || (plugins && plugins[k])) {
1700
+ if (OPTION_FIXED_FLAG[k] === 'fixed' || (plugins && plugins[k])) {
1701
1701
  console.warn(`[SUNEDITOR.warn.resetOptions] "[${root + k}]" options not available in resetOptions have no effect.`);
1702
1702
  keys.splice(i--, 1);
1703
1703
  len--;
@@ -52,11 +52,49 @@ export const BASIC_COMMANDS = ACTIVE_EVENT_COMMANDS.concat(['undo', 'redo', 'sav
52
52
  export function SELECT_ALL(editor) {
53
53
  editor.ui._offCurrentController();
54
54
  editor.menu.containerOff();
55
- const figcaption = dom.query.getParentElement(editor.selection.getNode(), 'FIGCAPTION');
56
- const selectArea = figcaption || editor.frameContext.get('wysiwyg');
57
55
 
58
- let first = dom.query.getEdgeChild(selectArea.firstChild, (current) => current.childNodes.length === 0 || current.nodeType === 3 || dom.check.isTable(current), false) || selectArea.firstChild;
59
- let last = dom.query.getEdgeChild(selectArea.lastChild, (current) => current.childNodes.length === 0 || current.nodeType === 3 || dom.check.isTable(current), true) || selectArea.lastChild;
56
+ // check all tags
57
+ const ww = editor.frameContext.get('wysiwyg');
58
+ let prevScopeTag = null;
59
+ let prevScopeTagName = '';
60
+ const scopeSelectionTags = editor.options.get('scopeSelectionTags');
61
+ const range = editor.selection.getRange();
62
+ if (!range.collapsed) {
63
+ let commonNode = range.commonAncestorContainer;
64
+ let commonNodeName = commonNode.nodeName?.toLowerCase();
65
+
66
+ while (commonNode && ((!commonNode.nextSibling && !commonNode.previousSibling && !scopeSelectionTags.includes(commonNodeName)) || dom.check.isContentLess(commonNodeName)) && commonNode !== ww) {
67
+ commonNode = commonNode.parentElement;
68
+ commonNodeName = commonNode.nodeName?.toLowerCase();
69
+ }
70
+
71
+ if (scopeSelectionTags.includes(commonNodeName)) {
72
+ prevScopeTag = commonNode;
73
+ prevScopeTagName = commonNodeName;
74
+ }
75
+ }
76
+
77
+ // select all
78
+ const scopeTagList = scopeSelectionTags.filter((tagName) => tagName !== prevScopeTagName);
79
+ const scopeBaseTag = dom.query.getParentElement(prevScopeTag || editor.selection.getNode(), (current) => scopeTagList.includes(current.nodeName?.toLowerCase()));
80
+ const selectArea = scopeBaseTag || ww;
81
+
82
+ let first =
83
+ dom.query.getEdgeChild(
84
+ dom.query.getEdgeChild(selectArea, (current) => !dom.check.isContentLess(current), false),
85
+ (current) => {
86
+ return current.childNodes.length === 0 || current.nodeType === 3 || dom.check.isTable(current);
87
+ },
88
+ false
89
+ ) || selectArea.firstChild;
90
+ let last =
91
+ dom.query.getEdgeChild(
92
+ selectArea.lastChild,
93
+ (current) => {
94
+ return current.childNodes.length === 0 || current.nodeType === 3 || dom.check.isTable(current);
95
+ },
96
+ true
97
+ ) || selectArea.lastChild;
60
98
 
61
99
  if (!first || !last) return;
62
100
 
@@ -1,4 +1,4 @@
1
- import _icons from '../../assets/icons/_default';
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,119 @@ 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
- * @property {Object<string, *>} [PluginOptions] - Dynamic plugin options, where the key is the plugin name and the value is its configuration.
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
+ /**
228
+ * @description For all EditorInitOptions keys, only boolean | null values are allowed.
229
+ * - 'fixed' → Immutable / null → Resettable.
230
+ * @type {Partial<Record<keyof EditorInitOptions, "fixed" | true>>}
231
+ */
232
+ export const OPTION_FIXED_FLAG = {
233
+ value: 'fixed',
234
+ placeholder: 'fixed',
235
+ editableFrameAttributes: null,
236
+ width: null,
237
+ minWidth: null,
238
+ maxWidth: null,
239
+ height: null,
240
+ minHeight: null,
241
+ maxHeight: null,
242
+ editorStyle: null,
243
+ iframe: 'fixed',
244
+ iframe_fullPage: null,
245
+ iframe_attributes: null,
246
+ iframe_cssFileName: null,
247
+ statusbar: null,
248
+ statusbar_showPathLabel: null,
249
+ statusbar_resizeEnable: null,
250
+ charCounter: null,
251
+ charCounter_max: null,
252
+ charCounter_label: null,
253
+ charCounter_type: null,
254
+ plugins: null,
255
+ excludedPlugins: null,
256
+ buttonList: 'fixed',
257
+ v2Migration: null,
258
+ strictMode: null,
259
+ mode: 'fixed',
260
+ type: 'fixed',
261
+ theme: null,
262
+ lang: 'fixed',
263
+ fontSizeUnits: 'fixed',
264
+ allowedClassName: null,
265
+ closeModalOutsideClick: null,
266
+ copyFormatKeepOn: null,
267
+ syncTabIndent: null,
268
+ tabDisable: null,
269
+ autoLinkify: null,
270
+ autoStyleify: null,
271
+ scrollToOptions: null,
272
+ componentScrollToOptions: null,
273
+ retainStyleMode: null,
274
+ allowedExtraTags: null,
275
+ events: null,
276
+ __textStyleTags: 'fixed',
277
+ textStyleTags: 'fixed',
278
+ convertTextTags: 'fixed',
279
+ __tagStyles: null,
280
+ tagStyles: 'fixed',
281
+ spanStyles: 'fixed',
282
+ lineStyles: 'fixed',
283
+ textDirection: null,
284
+ reverseButtons: null,
285
+ historyStackDelayTime: null,
286
+ lineAttrReset: null,
287
+ printClass: null,
288
+ defaultLine: 'fixed',
289
+ defaultLineBreakFormat: null,
290
+ scopeSelectionTags: null,
291
+ __defaultElementWhitelist: 'fixed',
292
+ elementWhitelist: 'fixed',
293
+ elementBlacklist: 'fixed',
294
+ __defaultAttributeWhitelist: 'fixed',
295
+ attributeWhitelist: 'fixed',
296
+ attributeBlacklist: 'fixed',
297
+ __defaultFormatLine: null,
298
+ formatLine: 'fixed',
299
+ __defaultFormatBrLine: null,
300
+ formatBrLine: 'fixed',
301
+ __defaultFormatClosureBrLine: 'fixed',
302
+ formatClosureBrLine: 'fixed',
303
+ __defaultFormatBlock: null,
304
+ formatBlock: 'fixed',
305
+ __defaultFormatClosureBlock: null,
306
+ formatClosureBlock: 'fixed',
307
+ allowedEmptyTags: null,
308
+ toolbar_width: null,
309
+ toolbar_container: 'fixed',
310
+ toolbar_sticky: null,
311
+ toolbar_hide: null,
312
+ subToolbar: 'fixed',
313
+ statusbar_container: 'fixed',
314
+ shortcutsHint: null,
315
+ shortcutsDisable: 'fixed',
316
+ shortcuts: 'fixed',
317
+ fullScreenOffset: null,
318
+ previewTemplate: null,
319
+ printTemplate: null,
320
+ componentAutoSelect: null,
321
+ defaultUrlProtocol: null,
322
+ allUsedStyles: null,
323
+ toastMessageTime: null,
324
+ icons: 'fixed',
325
+ freeCodeViewMode: null,
326
+ __lineFormatFilter: null,
327
+ __pluginRetainFilter: null,
328
+ __listCommonStyle: 'fixed',
329
+ externalLibs: 'fixed'
330
+ };
331
+
258
332
  /**
259
333
  * @description Creates a new SunEditor instance with specified options.
260
334
  * @param {Array<{target: Element, key: *, options: EditorFrameOptions}>} editorTargets - Target element or multi-root object.
@@ -424,10 +498,10 @@ function Constructor(editorTargets, options) {
424
498
 
425
499
  // document type
426
500
  const documentTypeInner = { inner: null, page: null, pageMirror: null };
427
- if (o.get('type-options').includes('header')) {
501
+ if (o.get('_type_options').includes('header')) {
428
502
  documentTypeInner.inner = dom.utils.createElement('DIV', { class: 'se-document-lines', style: `height: ${to.get('height')};` }, '<div class="se-document-lines-inner"></div>');
429
503
  }
430
- if (o.get('type-options').includes('page')) {
504
+ if (o.get('_type_options').includes('page')) {
431
505
  documentTypeInner.page = dom.utils.createElement('DIV', { class: 'se-document-page' }, null);
432
506
  documentTypeInner.pageMirror = dom.utils.createElement(
433
507
  'DIV',
@@ -619,7 +693,7 @@ export function InitOptions(options, editorTargets, plugins) {
619
693
  o.set('type', options.type?.split(':')[0] || ''); // document:header,page
620
694
  o.set('theme', options.theme || '');
621
695
  o.set('_themeClass', options.theme ? ` se-theme-${options.theme}` : '');
622
- o.set('type-options', options.type?.split(':')[1] || '');
696
+ o.set('_type_options', options.type?.split(':')[1] || '');
623
697
  o.set('externalLibs', options.externalLibs || {});
624
698
  o.set('fontSizeUnits', Array.isArray(options.fontSizeUnits) && options.fontSizeUnits.length > 0 ? options.fontSizeUnits.map((v) => v.toLowerCase()) : DEFAULT_SIZE_UNITS);
625
699
  o.set('allowedClassName', new RegExp(`${options.allowedClassName && typeof options.allowedClassName === 'string' ? options.allowedClassName + '|' : ''}${DEFAULT_CLASS_NAME}`));
@@ -736,6 +810,7 @@ export function InitOptions(options, editorTargets, plugins) {
736
810
  // default line
737
811
  o.set('defaultLine', typeof options.defaultLine === 'string' && options.defaultLine.length > 0 ? options.defaultLine : 'p');
738
812
  o.set('_defaultBrLineBreak', options.defaultLineBreakFormat === 'br');
813
+ o.set('scopeSelectionTags', options.scopeSelectionTags || DEFAULT_SCOPE_SELECTION_TAGS.split('|'));
739
814
  // element
740
815
  const elw = (typeof options.elementWhitelist === 'string' ? options.elementWhitelist : '').toLowerCase();
741
816
  const mjxEls = o.get('externalLibs').mathjax ? DEFAULT_CLASS_MJX + '|' : '';
@@ -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('type-options').includes('header');
47
- this.usePage = editor.options.get('type-options').includes('page');
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
@@ -606,5 +606,17 @@ export default {
606
606
  * @param {EmbedInfo} params.info - info object
607
607
  * @param {(newInfo?: EmbedInfo|null) => void} params.handler - handler function
608
608
  */
609
- onEmbedInputBefore: null
609
+ onEmbedInputBefore: null,
610
+
611
+ /**
612
+ * @description Called before the embed is deleted
613
+ * @param {Object} params
614
+ * @param {__se__EditorCore} params.editor - The root editor instance
615
+ * @param {HTMLElement} params.element - target element
616
+ * @param {HTMLElement} params.container - target's container element (div)
617
+ * @param {string} params.align - align value
618
+ * @param {string} params.url - embed url
619
+ * @returns {Promise<boolean>}
620
+ */
621
+ onEmbedDeleteBefore: null
610
622
  };
@@ -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
@@ -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,
@@ -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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
371
+ this.component.select(a, FileUpload.key);
372
372
  }
373
373
  }
374
374