suneditor 2.43.6 → 2.43.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "suneditor",
3
- "version": "2.43.6",
3
+ "version": "2.43.7",
4
4
  "description": "Pure JavaScript based WYSIWYG web editor",
5
5
  "author": "JiHong.Lee",
6
6
  "license": "MIT",
@@ -396,6 +396,16 @@ export default {
396
396
  * @private
397
397
  */
398
398
  _initOptions: function (element, options) {
399
+ const plugins = {};
400
+ if (options.plugins) {
401
+ const _plugins = options.plugins;
402
+ const pluginsValues = _plugins.length ? _plugins : Object.keys(_plugins).map(function(name) { return _plugins[name]; });
403
+ for (let i = 0, len = pluginsValues.length, p; i < len; i++) {
404
+ p = pluginsValues[i].default || pluginsValues[i];
405
+ plugins[p.name] = p;
406
+ }
407
+ }
408
+ options.plugins = plugins;
399
409
  /** Values */
400
410
  options.lang = options.lang || _defaultLang;
401
411
  options.value = typeof options.value === 'string' ? options.value : null;
@@ -493,7 +503,7 @@ export default {
493
503
  options.className = (typeof options.className === 'string' && options.className.length > 0) ? ' ' + options.className : '';
494
504
  options.defaultStyle = typeof options.defaultStyle === 'string' ? options.defaultStyle : '';
495
505
  /** Defining menu items */
496
- options.font = !options.font ? null : options.font;
506
+ options.font = !options.font ? ['Arial', 'Comic Sans MS', 'Courier New', 'Impact', 'Georgia', 'tahoma', 'Trebuchet MS', 'Verdana'] : options.font;
497
507
  options.fontSize = !options.fontSize ? null : options.fontSize;
498
508
  options.formats = !options.formats ? null : options.formats;
499
509
  options.colorList = !options.colorList ? null : options.colorList;
@@ -756,12 +766,12 @@ export default {
756
766
  * @description Create editor HTML
757
767
  * @param {Array} doc document object
758
768
  * @param {Array} buttonList option.buttonList
759
- * @param {Array|Object|null} _plugins Plugins
769
+ * @param {Object|null} plugins Plugins
760
770
  * @param {Array} options options
761
771
  * @returns {Object} { element: (Element) Toolbar element, plugins: (Array|null) Plugins Array, pluginCallButtons: (Object), responsiveButtons: (Array) }
762
772
  * @private
763
773
  */
764
- _createToolBar: function (doc, buttonList, _plugins, options) {
774
+ _createToolBar: function (doc, buttonList, plugins, options) {
765
775
  const separator_vertical = doc.createElement('DIV');
766
776
  separator_vertical.className = 'se-toolbar-separator-vertical';
767
777
 
@@ -778,14 +788,6 @@ export default {
778
788
  const defaultButtonList = this._defaultButtons(options);
779
789
  const pluginCallButtons = {};
780
790
  const responsiveButtons = [];
781
- const plugins = {};
782
- if (_plugins) {
783
- const pluginsValues = _plugins.length ? _plugins : Object.keys(_plugins).map(function(name) { return _plugins[name]; });
784
- for (let i = 0, len = pluginsValues.length, p; i < len; i++) {
785
- p = pluginsValues[i].default || pluginsValues[i];
786
- plugins[p.name] = p;
787
- }
788
- }
789
791
 
790
792
  let module = null;
791
793
  let button = null;
package/src/lib/core.js CHANGED
@@ -41,6 +41,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
41
41
  _parser: new _w.DOMParser(),
42
42
  _prevRtl: options.rtl,
43
43
  _editorHeight: 0,
44
+ _editorHeightPadding: 0,
44
45
  _listCamel: options.__listCommonStyle,
45
46
  _listKebab: util.camelToKebabCase(options.__listCommonStyle),
46
47
 
@@ -1500,7 +1501,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
1500
1501
 
1501
1502
  const currentFormatEl = util.getFormatElement(this.getSelectionNode(), null);
1502
1503
  let oFormat = null;
1503
- if (util.isFreeFormatElement(currentFormatEl || element.parentNode)) {
1504
+ if (!util.isFormatElement(element) && util.isFreeFormatElement(currentFormatEl || element.parentNode)) {
1504
1505
  oFormat = util.createElement('BR');
1505
1506
  } else {
1506
1507
  const oFormatName = formatNode ? (typeof formatNode === 'string' ? formatNode : formatNode.nodeName) : (util.isFormatElement(currentFormatEl) && !util.isRangeFormatElement(currentFormatEl) && !util.isFreeFormatElement(currentFormatEl)) ? currentFormatEl.nodeName : options.defaultTag;
@@ -1691,7 +1692,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
1691
1692
  const isEdge = this.isEdgePoint(range.endContainer, range.endOffset, 'end');
1692
1693
  const r = this.removeNode();
1693
1694
  const container = r.container;
1694
- const prevContainer = r.prevContainer;
1695
+ const prevContainer = (container === r.prevContainer && range.collapsed) ? null : r.prevContainer;
1695
1696
 
1696
1697
  if (insertListCell && prevContainer) {
1697
1698
  tempParentNode = prevContainer.nodeType === 3 ? prevContainer.parentNode : prevContainer;
@@ -1731,7 +1732,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
1731
1732
  newCell.appendChild(line.lastElementChild);
1732
1733
  }
1733
1734
  if (newCell) {
1734
- tempParentNode.insertBefore(newCell, line.nextElementSibling);
1735
+ line.parentNode.insertBefore(newCell, line.nextElementSibling);
1735
1736
  tempAfterNode = afterNode = newCell;
1736
1737
  }
1737
1738
  }
@@ -5031,10 +5032,16 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5031
5032
  // element
5032
5033
  if (node.nodeType === 1) {
5033
5034
  if (util._disallowedTags(node)) return '';
5035
+
5036
+ const ch = util.getListChildNodes(node, function(current) { return util.isSpanWithoutAttr(current); }) || [];
5037
+ for (let i = ch.length - 1; i >= 0; i--) {
5038
+ ch[i].outerHTML = ch[i].innerHTML;
5039
+ }
5040
+
5034
5041
  if (!requireFormat || (util.isFormatElement(node) || util.isRangeFormatElement(node) || util.isComponent(node) || util.isMedia(node) || (util.isAnchor(node) && util.isMedia(node.firstElementChild)))) {
5035
- return node.outerHTML;
5042
+ return util.isSpanWithoutAttr(node) ? node.innerHTML : node.outerHTML;
5036
5043
  } else {
5037
- return '<' + defaultTag + '>' + node.outerHTML + '</' + defaultTag + '>';
5044
+ return '<' + defaultTag + '>' + (util.isSpanWithoutAttr(node) ? node.innerHTML : node.outerHTML) + '</' + defaultTag + '>';
5038
5045
  }
5039
5046
  }
5040
5047
  // text
@@ -5124,7 +5131,37 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5124
5131
  const sv = m.match(/style\s*=\s*(?:"|')[^"']*(?:"|')/);
5125
5132
  if (sv) {
5126
5133
  if (!v) v = [];
5127
- v.push(sv[0]);
5134
+ const style = sv[0].replace(/&quot;/g, '').match(/\s*(font-family|font-size|color|background-color)\s*:[^;]+(?!;)*/ig);
5135
+ if (style) {
5136
+ const allowedStyle = [];
5137
+ for (let i = 0, len = style.length, r; i < len; i++) {
5138
+ r = style[i].match(/(.+)(:)([^:]+$)/);
5139
+ if (r && !/inherit|initial/i.test(r[3])) {
5140
+ const k = util.kebabToCamelCase(r[1].trim());
5141
+ const v = this.wwComputedStyle[k].replace(/"/g, '');
5142
+ const c = r[3].trim();
5143
+ switch (k) {
5144
+ case 'fontFamily':
5145
+ if (options.plugins.font ? options.font.indexOf(c) === -1 : true) continue;
5146
+ break;
5147
+ case 'fontSize':
5148
+ if (!options.plugins.fontSize) continue;
5149
+ break;
5150
+ case 'color':
5151
+ if (!options.plugins.fontColor) continue;
5152
+ break;
5153
+ case 'backgroundColor':
5154
+ if (!options.plugins.hiliteColor) continue;
5155
+ break;
5156
+ }
5157
+
5158
+ if (v !== c) {
5159
+ allowedStyle.push(r[0]);
5160
+ }
5161
+ }
5162
+ }
5163
+ if (allowedStyle.length > 0) v.push('style="' + allowedStyle.join(';') + '"');
5164
+ }
5128
5165
  }
5129
5166
  }
5130
5167
 
@@ -5153,14 +5190,82 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5153
5190
 
5154
5191
  if (v) {
5155
5192
  for (let i = 0, len = v.length; i < len; i++) {
5156
- if (lowLevelCheck && /^class="(?!(__se__|se-|katex))/.test(v[i])) continue;
5157
- t += ' ' + (/^(?:href|src)\s*=\s*('|"|\s)*javascript\s*\:/i.test(v[i]) ? '' : v[i]);
5193
+ if (lowLevelCheck && /^class="(?!(__se__|se-|katex))/.test(v[i].trim())) continue;
5194
+ t += ' ' + (/^(?:href|src)\s*=\s*('|"|\s)*javascript\s*\:/i.test(v[i].trim()) ? '' : v[i]);
5158
5195
  }
5159
5196
  }
5160
5197
 
5161
5198
  return t;
5162
5199
  },
5163
5200
 
5201
+ /**
5202
+ * @description Determines if formatting is required and returns a domTree
5203
+ * @param {Element} dom documentFragment
5204
+ * @returns {Element}
5205
+ * @private
5206
+ */
5207
+ _editFormat: function (dom) {
5208
+ let value = '', f;
5209
+ const tempTree = dom.childNodes;
5210
+ for (let i = 0, len = tempTree.length, n; i < len; i++) {
5211
+ n = tempTree[i];
5212
+ if (!util.isFormatElement(n) && !util.isRangeFormatElement(n) && !util.isComponent(n) && !/meta/i.test(n.nodeName)) {
5213
+ if (!f) f = util.createElement(options.defaultTag);
5214
+ f.appendChild(n);
5215
+ i--; len--;
5216
+ } else {
5217
+ if (f) {
5218
+ value += f.outerHTML;
5219
+ f = null;
5220
+ }
5221
+ value += n.outerHTML;
5222
+ }
5223
+ }
5224
+
5225
+ if (f) value += f.outerHTML;
5226
+
5227
+ return _d.createRange().createContextualFragment(value);
5228
+ },
5229
+
5230
+ _convertListCell: function (domTree) {
5231
+ let html = '';
5232
+
5233
+ for (let i = 0, len = domTree.length, node; i < len; i++) {
5234
+ node = domTree[i];
5235
+ if (node.nodeType === 1) {
5236
+ if (util.isList(node)) {
5237
+ html += node.innerHTML;
5238
+ } else if (util.isListCell(node)) {
5239
+ html += node.outerHTML;
5240
+ } else if (util.isFormatElement(node)) {
5241
+ html += '<li>' +(node.innerHTML.trim() || '<br>') + '</li>';
5242
+ } else if (util.isRangeFormatElement(node) && !util.isTable(node)) {
5243
+ html += event._convertListCell(node);
5244
+ } else {
5245
+ html += '<li>' + node.outerHTML + '</li>';
5246
+ }
5247
+ } else {
5248
+ html += '<li>' + (node.textContent || '<br>') + '</li>';
5249
+ }
5250
+ }
5251
+
5252
+ return html;
5253
+ },
5254
+
5255
+ _isFormatData: function (domTree) {
5256
+ let requireFormat = false;
5257
+
5258
+ for (let i = 0, len = domTree.length, t; i < len; i++) {
5259
+ t = domTree[i];
5260
+ if (t.nodeType === 1 && !util.isTextStyleElement(t) && !util.isBreak(t) && !util._disallowedTags(t)) {
5261
+ requireFormat = true;
5262
+ break;
5263
+ }
5264
+ }
5265
+
5266
+ return requireFormat;
5267
+ },
5268
+
5164
5269
  /**
5165
5270
  * @description Gets the clean HTML code for editor
5166
5271
  * @param {String} html HTML string
@@ -5194,16 +5299,12 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5194
5299
  }
5195
5300
  }
5196
5301
 
5197
- const domTree = dom.childNodes;
5302
+ let domTree = dom.childNodes;
5198
5303
  let cleanHTML = '';
5199
- let requireFormat = false;
5304
+ const requireFormat = this._isFormatData(domTree);
5200
5305
 
5201
- for (let i = 0, len = domTree.length, t; i < len; i++) {
5202
- t = domTree[i];
5203
- if (t.nodeType === 1 && !util.isTextStyleElement(t) && !util.isBreak(t) && !util._disallowedTags(t)) {
5204
- requireFormat = true;
5205
- break;
5206
- }
5306
+ if(requireFormat) {
5307
+ domTree = this._editFormat(dom).childNodes;
5207
5308
  }
5208
5309
 
5209
5310
  for (let i = 0, len = domTree.length; i < len; i++) {
@@ -5566,6 +5667,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5566
5667
  this._charTypeHTML = options.charCounterType === 'byte-html';
5567
5668
  this.wwComputedStyle = _w.getComputedStyle(context.element.wysiwyg);
5568
5669
  this._editorHeight = context.element.wysiwygFrame.offsetHeight;
5670
+ this._editorHeightPadding = util.getNumber(this.wwComputedStyle.getPropertyValue('padding-top')) + util.getNumber(this.wwComputedStyle.getPropertyValue('padding-bottom'));
5569
5671
 
5570
5672
  if (!options.iframe && typeof _w.ShadowRoot === 'function') {
5571
5673
  let child = context.element.wysiwygFrame;
@@ -5799,7 +5901,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5799
5901
  },
5800
5902
 
5801
5903
  __callResizeFunction: function (h, resizeObserverEntry) {
5802
- h = h === -1 ? resizeObserverEntry.borderBoxSize[0].blockSize : h;
5904
+ h = h === -1 ? (resizeObserverEntry.borderBoxSize ? resizeObserverEntry.borderBoxSize[0].blockSize : (resizeObserverEntry.contentRect.height + this._editorHeightPadding)) : h;
5803
5905
  if (this._editorHeight !== h) {
5804
5906
  if (typeof functions.onResizeEditor === 'function') functions.onResizeEditor(h, this._editorHeight, core, resizeObserverEntry);
5805
5907
  this._editorHeight = h;
@@ -7691,39 +7793,11 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
7691
7793
  }
7692
7794
 
7693
7795
  if (cleanData) {
7694
- if (util.isListCell(util.getFormatElement(core.getSelectionNode(), null))) {
7695
- const dom = (_d.createRange().createContextualFragment(cleanData));
7696
- const domTree = dom.childNodes;
7697
- if (domTree.length > 1 && domTree[0].nodeType === 1) cleanData = event._convertListCell(domTree);
7698
- }
7699
7796
  functions.insertHTML(cleanData, true, false);
7700
7797
  return false;
7701
7798
  }
7702
7799
  },
7703
7800
 
7704
- _convertListCell: function (domTree) {
7705
- let html = '';
7706
-
7707
- for (let i = 0, len = domTree.length, node; i < len; i++) {
7708
- node = domTree[i];
7709
- if (node.nodeType === 1) {
7710
- if (util.isListCell(node) || util.isList(node)) {
7711
- html += node.outerHTML;
7712
- } else if (util.isFormatElement(node)) {
7713
- html += '<li>' +(node.innerHTML.trim() || '<br>') + '</li>';
7714
- } else if (util.isRangeFormatElement(node) && !util.isTable(node)) {
7715
- html += event._convertListCell(node);
7716
- } else {
7717
- html += '<li>' + node.outerHTML + '</li>';
7718
- }
7719
- } else {
7720
- html += '<li>' + (node.textContent || '<br>') + '</li>';
7721
- }
7722
- }
7723
-
7724
- return html;
7725
- },
7726
-
7727
7801
  onMouseMove_wysiwyg: function (e) {
7728
7802
  if (core.isDisabled || core.isReadOnly) return false;
7729
7803
  const component = util.getParentElement(e.target, util.isComponent);
@@ -8439,10 +8513,16 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
8439
8513
  */
8440
8514
  insertHTML: function (html, notCleaningData, checkCharCount, rangeSelection) {
8441
8515
  if (!context.element.wysiwygFrame.contains(core.getSelection().focusNode)) core.focus();
8442
-
8516
+
8443
8517
  if (typeof html === 'string') {
8444
8518
  if (!notCleaningData) html = core.cleanHTML(html, null, null);
8445
8519
  try {
8520
+ if (util.isListCell(util.getFormatElement(core.getSelectionNode(), null))) {
8521
+ const dom = _d.createRange().createContextualFragment(html);
8522
+ const domTree = dom.childNodes;
8523
+ if (core._isFormatData(domTree)) html = core._convertListCell(domTree);
8524
+ }
8525
+
8446
8526
  const dom = _d.createRange().createContextualFragment(html);
8447
8527
  const domTree = dom.childNodes;
8448
8528
 
package/src/lib/util.d.ts CHANGED
@@ -42,6 +42,12 @@ declare interface util {
42
42
  */
43
43
  camelToKebabCase(param: string | string[]): string | string[],
44
44
 
45
+ /**
46
+ * @description Convert the KebabCase To the CamelCase.
47
+ * @param {String|Array} param [KebabCase string]
48
+ */
49
+ kebabToCamelCase(param: string | string[]): string | string[],
50
+
45
51
  /**
46
52
  * @description Create Element node
47
53
  * @param elementName Element name
@@ -351,6 +357,13 @@ declare interface util {
351
357
  */
352
358
  isEmptyLine(element: Element): boolean;
353
359
 
360
+ /**
361
+ * @description Check the span's attributes are empty.
362
+ * @param {Element} element Element node
363
+ * @returns {Boolean}
364
+ */
365
+ isSpanWithoutAttr(element: Element|null): boolean;
366
+
354
367
  /**
355
368
  * @description Check the node is a list (ol, ul)
356
369
  * @param node The element or element name to check
package/src/lib/util.js CHANGED
@@ -119,6 +119,19 @@ const util = {
119
119
  }
120
120
  },
121
121
 
122
+ /**
123
+ * @description Convert the KebabCase To the CamelCase.
124
+ * @param {String|Array} param [KebabCase string]
125
+ * @returns {String|Array}
126
+ */
127
+ kebabToCamelCase: function (param) {
128
+ if (typeof param === 'string') {
129
+ return param.replace(/-[a-zA-Z]/g, function (letter) { return letter.replace('-', '').toUpperCase(); });
130
+ } else {
131
+ return param.map(function(str) { return util.camelToKebabCase(str); });
132
+ }
133
+ },
134
+
122
135
  /**
123
136
  * @description Create Element node
124
137
  * @param {String} elementName Element name
@@ -763,6 +776,15 @@ const util = {
763
776
  return !element || !element.parentNode || (!element.querySelector('IMG, IFRAME, AUDIO, VIDEO, CANVAS, TABLE') && this.onlyZeroWidthSpace(element.textContent));
764
777
  },
765
778
 
779
+ /**
780
+ * @description Check the span's attributes are empty.
781
+ * @param {Element|null} element Element node
782
+ * @returns {Boolean}
783
+ */
784
+ isSpanWithoutAttr: function (element) {
785
+ return !!element && element.nodeType === 1 && /^SPAN$/i.test(element.nodeName) && !element.className && !element.style.cssText;
786
+ },
787
+
766
788
  /**
767
789
  * @description Check the node is a list (ol, ul)
768
790
  * @param {Node|String} node The element or element name to check
@@ -1375,12 +1397,33 @@ const util = {
1375
1397
  * @description Split all tags based on "baseNode"
1376
1398
  * Returns the last element of the splited tag.
1377
1399
  * @param {Node} baseNode Element or text node on which to base
1378
- * @param {Number|null} offset Text offset of "baseNode" (Only valid when "baseNode" is a text node)
1400
+ * @param {Number|Node|null} offset Text offset of "baseNode" (Only valid when "baseNode" is a text node)
1379
1401
  * @param {Number} depth The nesting depth of the element being split. (default: 0)
1380
1402
  * @returns {Element}
1381
1403
  */
1382
1404
  splitElement: function (baseNode, offset, depth) {
1383
1405
  if (this.isWysiwygDiv(baseNode)) return baseNode;
1406
+
1407
+ if (!!offset && !this.isNumber(offset)) {
1408
+ const children = baseNode.childNodes;
1409
+ let index = this.getPositionIndex(offset);
1410
+ const prev = baseNode.cloneNode(false);
1411
+ const next = baseNode.cloneNode(false);
1412
+ for (let i = 0, len = children.length; i < len; i++) {
1413
+ if (i < index) prev.appendChild(children[i]);
1414
+ else if (i > index) next.appendChild(children[i]);
1415
+ else continue;
1416
+ i--;
1417
+ len--;
1418
+ index--;
1419
+ }
1420
+
1421
+ if (prev.childNodes.length > 0) baseNode.parentNode.insertBefore(prev, baseNode);
1422
+ if (next.childNodes.length > 0) baseNode.parentNode.insertBefore(next, baseNode.nextElementSibling);
1423
+
1424
+ return baseNode;
1425
+ }
1426
+
1384
1427
  const bp = baseNode.parentNode;
1385
1428
  let index = 0, newEl, children, temp;
1386
1429
  let next = true;
@@ -454,7 +454,7 @@ export default {
454
454
  this.plugins.audio._setTagAttrs.call(this, element);
455
455
 
456
456
  // find component element
457
- const existElement = (this.util.isRangeFormatElement(element.parentNode) || this.util.isWysiwygDiv(element.parentNode)) ?
457
+ let existElement = (this.util.isRangeFormatElement(element.parentNode) || this.util.isWysiwygDiv(element.parentNode)) ?
458
458
  element : this.util.getFormatElement(element) || element;
459
459
 
460
460
  // clone element
@@ -464,12 +464,16 @@ export default {
464
464
  const container = this.plugins.component.set_container.call(this, cover, 'se-audio-container');
465
465
 
466
466
  try {
467
- if (this.util.isListCell(existElement) || this.util.isFormatElement(existElement)) {
468
- prevElement.parentNode.replaceChild(container, prevElement);
469
- } else if (this.util.isFormatElement(existElement) && existElement.childNodes.length > 0) {
467
+ if (this.util.isListCell(existElement)) {
468
+ const refer = this.util.getParentElement(prevElement, function (current) { return current.parentNode === existElement; });
469
+ existElement.insertBefore(container, refer);
470
+ this.util.removeItem(prevElement);
471
+ this.util.removeEmptyNode(refer, null);
472
+ } else if (this.util.isFormatElement(existElement)) {
473
+ const refer = this.util.getParentElement(prevElement, function (current) { return current.parentNode === existElement; });
474
+ existElement = this.util.splitElement(existElement, refer);
470
475
  existElement.parentNode.insertBefore(container, existElement);
471
476
  this.util.removeItem(prevElement);
472
- // clean format tag
473
477
  this.util.removeEmptyNode(existElement, null);
474
478
  if (existElement.children.length === 0) existElement.innerHTML = this.util.htmlRemoveWhiteSpace(existElement.innerHTML);
475
479
  } else {
@@ -768,16 +768,20 @@ export default {
768
768
  }
769
769
 
770
770
  if (isNewContainer) {
771
- const existElement = (this.util.isRangeFormatElement(contextImage._element.parentNode) || this.util.isWysiwygDiv(contextImage._element.parentNode)) ?
771
+ let existElement = (this.util.isRangeFormatElement(contextImage._element.parentNode) || this.util.isWysiwygDiv(contextImage._element.parentNode)) ?
772
772
  contextImage._element :
773
773
  /^A$/i.test(contextImage._element.parentNode.nodeName) ? contextImage._element.parentNode : this.util.getFormatElement(contextImage._element) || contextImage._element;
774
774
 
775
- if (this.util.isListCell(existElement) || this.util.isFormatElement(existElement)) {
776
- contextImage._element.parentNode.replaceChild(container, contextImage._element);
777
- } else if (this.util.isFormatElement(existElement) && existElement.childNodes.length > 0) {
775
+ if (this.util.isListCell(existElement)) {
776
+ const refer = this.util.getParentElement(contextImage._element, function (current) { return current.parentNode === existElement; });
777
+ existElement.insertBefore(container, refer);
778
+ this.util.removeItem(contextImage._element);
779
+ this.util.removeEmptyNode(refer, null);
780
+ } else if (this.util.isFormatElement(existElement)) {
781
+ const refer = this.util.getParentElement(contextImage._element, function (current) { return current.parentNode === existElement; });
782
+ existElement = this.util.splitElement(existElement, refer);
778
783
  existElement.parentNode.insertBefore(container, existElement);
779
784
  this.util.removeItem(contextImage._element);
780
- // clean format tag
781
785
  this.util.removeEmptyNode(existElement, null);
782
786
  if (existElement.children.length === 0) existElement.innerHTML = this.util.htmlRemoveWhiteSpace(existElement.innerHTML);
783
787
  } else {
@@ -645,7 +645,7 @@ export default {
645
645
  if (/^video$/i.test(oFrame.nodeName)) this.plugins.video._setTagAttrs.call(this, oFrame);
646
646
  else this.plugins.video._setIframeAttrs.call(this, oFrame);
647
647
 
648
- const existElement = (this.util.isRangeFormatElement(oFrame.parentNode) || this.util.isWysiwygDiv(oFrame.parentNode)) ?
648
+ let existElement = (this.util.isRangeFormatElement(oFrame.parentNode) || this.util.isWysiwygDiv(oFrame.parentNode)) ?
649
649
  oFrame : this.util.getFormatElement(oFrame) || oFrame;
650
650
 
651
651
  const prevFrame = oFrame;
@@ -671,12 +671,16 @@ export default {
671
671
  if (format) contextVideo._align = format.style.textAlign || format.style.float;
672
672
  this.plugins.video.setAlign.call(this, null, oFrame, cover, container);
673
673
 
674
- if (this.util.isListCell(existElement) || this.util.isFormatElement(existElement)) {
675
- prevFrame.parentNode.replaceChild(container, prevFrame);
676
- } else if (this.util.isFormatElement(existElement) && existElement.childNodes.length > 0) {
674
+ if (this.util.isListCell(existElement)) {
675
+ const refer = this.util.getParentElement(prevFrame, function (current) { return current.parentNode === existElement; });
676
+ existElement.insertBefore(container, refer);
677
+ this.util.removeItem(prevFrame);
678
+ this.util.removeEmptyNode(refer, null);
679
+ } else if (this.util.isFormatElement(existElement)) {
680
+ const refer = this.util.getParentElement(prevFrame, function (current) { return current.parentNode === existElement; });
681
+ existElement = this.util.splitElement(existElement, refer);
677
682
  existElement.parentNode.insertBefore(container, existElement);
678
683
  this.util.removeItem(prevFrame);
679
- // clean format tag
680
684
  this.util.removeEmptyNode(existElement, null);
681
685
  if (existElement.children.length === 0) existElement.innerHTML = this.util.htmlRemoveWhiteSpace(existElement.innerHTML);
682
686
  } else {
@@ -35,24 +35,13 @@ export default {
35
35
  },
36
36
 
37
37
  setSubmenu: function (core) {
38
- const option = core.options;
39
38
  const lang = core.lang;
40
39
  const listDiv = core.util.createElement('DIV');
41
40
 
42
41
  listDiv.className = 'se-submenu se-list-layer se-list-font-family';
43
42
 
44
43
  let font, text, i, len;
45
- let fontList = !option.font ?
46
- [
47
- 'Arial',
48
- 'Comic Sans MS',
49
- 'Courier New',
50
- 'Impact',
51
- 'Georgia',
52
- 'tahoma',
53
- 'Trebuchet MS',
54
- 'Verdana'
55
- ] : option.font;
44
+ let fontList = core.options.font;
56
45
 
57
46
  let list = '<div class="se-list-inner">' +
58
47
  '<ul class="se-list-basic">' +