suneditor 2.43.14 → 2.44.1

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.14",
3
+ "version": "2.44.1",
4
4
  "description": "Pure JavaScript based WYSIWYG web editor",
5
5
  "author": "JiHong.Lee",
6
6
  "license": "MIT",
@@ -32,6 +32,10 @@
32
32
  direction: rtl;
33
33
  }
34
34
 
35
+ .sun-editor-editable .se-component > figure {
36
+ direction: initial;
37
+ }
38
+
35
39
  /** controllers on tag */
36
40
  .sun-editor-editable td, .sun-editor-editable th,
37
41
  .sun-editor-editable figure, .sun-editor-editable figcaption, .sun-editor-editable img,
@@ -39,20 +43,6 @@
39
43
  position: relative;
40
44
  }
41
45
 
42
- /* float */
43
- .sun-editor-editable .__se__float-left {
44
- float: left;
45
- }
46
- .sun-editor-editable .__se__float-right {
47
- float: right;
48
- }
49
- .sun-editor-editable .__se__float-center {
50
- float: center;
51
- }
52
- .sun-editor-editable .__se__float-none {
53
- float: none;
54
- }
55
-
56
46
  /** span */
57
47
  .sun-editor-editable span {
58
48
  display: inline;
@@ -364,6 +354,22 @@
364
354
  -webkit-box-shadow:0 0 0 0.2rem #80bdff; box-shadow:0 0 0 0.2rem #3f9dff; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;
365
355
  }
366
356
 
357
+ /* float */
358
+ .sun-editor-editable .__se__float-left {
359
+ float: left;
360
+ margin-right: 4px;
361
+ }
362
+ .sun-editor-editable .__se__float-right {
363
+ float: right;
364
+ margin-left: 4px;
365
+ }
366
+ .sun-editor-editable .__se__float-center {
367
+ float: center;
368
+ }
369
+ .sun-editor-editable .__se__float-none {
370
+ float: none;
371
+ }
372
+
367
373
  /** image, video .. */
368
374
  .sun-editor-editable img, .sun-editor-editable iframe, .sun-editor-editable video, .sun-editor-editable audio {
369
375
  display: block;
@@ -2,7 +2,7 @@
2
2
  /* font color #333, background color: #fff */
3
3
  /* grey color #e1e1e1 , #d1d1d1 , #c1c1c1 , #b1b1b1 */
4
4
  /* blue color #c7deff , #80bdff , #3f9dff , #4592ff, #407dd1, #3288ff */
5
- /* red color #b94a48 , #f2dede , #eed3d7 */
5
+ /* red color #b94a48 , #f2dede , #eed3d7, #d9534f */
6
6
 
7
7
  /** --- suneditor main */
8
8
  .sun-editor {width:auto; height:auto; box-sizing:border-box; font-family:Helvetica Neue; border:1px solid #dadada; background-color:#FFF; color:#000; user-select:none; -o-user-select:none; -moz-user-select:none; -khtml-user-select:none; -webkit-user-select:none; -ms-user-select:none;}
@@ -459,8 +459,8 @@
459
459
 
460
460
  /** --- tooltip */
461
461
  .sun-editor .se-tooltip {position:relative; overflow:visible;}
462
- .sun-editor .se-tooltip .se-tooltip-inner {visibility:hidden; position:absolute; display:block; width:auto; top:120%; left:50%; background:transparent; opacity:0; z-index:1; line-height:1.5; transition:opacity 0.5s; margin:0; padding:0; bottom:auto; float:none; pointer-events:none; backface-visibility:hidden; -webkit-backface-visibility:hidden; -moz-backface-visibility:hidden;}
463
- .sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text {position:relative; display:inline-block; width:auto; left:-50%; font-size:0.9em; margin:0; padding:4px 6px; border-radius:2px; background-color:#333; color:#fff; text-align:center; line-height:unset; white-space:nowrap; cursor:auto;}
462
+ .sun-editor .se-tooltip .se-tooltip-inner {visibility:hidden; position:absolute; display:block; width:auto; height:auto; top:120%; left:50%; background:transparent; opacity:0; z-index:1; line-height:1.5; transition:opacity 0.5s; margin:0; padding:0; bottom:auto; float:none; pointer-events:none; backface-visibility:hidden; -webkit-backface-visibility:hidden; -moz-backface-visibility:hidden;}
463
+ .sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text {position:relative; display:inline-block; width:auto; height:auto; left:-50%; font-size:0.9em; margin:0; padding:4px 6px; border-radius:2px; background-color:#333; color:#fff; text-align:center; line-height:unset; white-space:nowrap; cursor:auto;}
464
464
  .sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text::after {content:""; position:absolute; bottom:100%; left:50%; margin-left:-5px; border-width:5px; border-style:solid; border-color:transparent transparent #333 transparent;}
465
465
  .sun-editor .se-tooltip:hover .se-tooltip-inner {visibility:visible; opacity:1;}
466
466
  .sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text .se-shortcut {display:block !important;}
@@ -501,6 +501,7 @@
501
501
 
502
502
  /* dialog--- */
503
503
  .sun-editor.se-rtl .se-dialog * {direction:rtl;}
504
+ .sun-editor.se-rtl .se-dialog .se-dialog-inner .se-dialog-form .se-video-ratio {margin-left:0; margin-right:4px;}
504
505
  /* dialog - header */
505
506
  .sun-editor.se-rtl .se-dialog .se-dialog-inner .se-dialog-header .se-dialog-close {float:left;}
506
507
  .sun-editor.se-rtl .se-dialog .se-dialog-inner .se-dialog-header .se-modal-title {float:right;}
@@ -535,6 +536,17 @@
535
536
  .sun-editor .se-btn-module-border.module-float-right {float:right;}
536
537
 
537
538
 
539
+ /** --- error ---------------------------------------------------------- */
540
+ .sun-editor .se-error {color:#d9534f;}
541
+ .sun-editor input.se-error:focus, select.se-error:focus, textarea.se-error:focus {
542
+ border: 1px solid #f2dede;
543
+ outline: 0;
544
+ -webkit-box-shadow: 0 0 0 0.2rem #eed3d7;
545
+ box-shadow: 0 0 0 0.2rem #eed3d7;
546
+ transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
547
+ }
548
+
549
+
538
550
  /** ---------------------------------------------------------- menu items style ---------------------------------------------------------- */
539
551
  /** hr menu items */
540
552
  .sun-editor hr.__se__solid {
@@ -410,6 +410,7 @@ export default {
410
410
  options.lang = options.lang || _defaultLang;
411
411
  options.value = typeof options.value === 'string' ? options.value : null;
412
412
  options.historyStackDelayTime = typeof options.historyStackDelayTime === 'number' ? options.historyStackDelayTime : 400;
413
+ options.frameAttrbutes = options.frameAttrbutes || {};
413
414
  // tag style
414
415
  options.defaultTag = typeof options.defaultTag === 'string' && options.defaultTag.length > 0 ? options.defaultTag : 'p';
415
416
  const textTags = options.textTags = [{bold: 'STRONG', underline: 'U', italic: 'EM', strike: 'DEL', sub: 'SUB', sup: 'SUP'}, (options.textTags || {})].reduce(function (_default, _new) {
@@ -511,7 +512,7 @@ export default {
511
512
  options.lineHeights = !options.lineHeights ? null : options.lineHeights;
512
513
  options.paragraphStyles = !options.paragraphStyles ? null : options.paragraphStyles;
513
514
  options.textStyles = !options.textStyles ? null : options.textStyles;
514
- options.fontSizeUnit = typeof options.fontSizeUnit === 'string' ? (options.fontSizeUnit.trim() || 'px') : 'px';
515
+ options.fontSizeUnit = typeof options.fontSizeUnit === 'string' ? (options.fontSizeUnit.trim().toLowerCase() || 'px') : 'px';
515
516
  options.alignItems = typeof options.alignItems === 'object' ? options.alignItems : (options.rtl ? ['right', 'center', 'left', 'justify'] : ['left', 'center', 'right', 'justify']);
516
517
  /** Image */
517
518
  options.imageResizing = options.imageResizing === undefined ? true : options.imageResizing;
package/src/lib/core.js CHANGED
@@ -474,8 +474,9 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
474
474
  * @private
475
475
  */
476
476
  _cleanStyleRegExp: {
477
- span: new _w.RegExp('\s*(font-family|font-size|color|background-color)\s*:[^;]+(?!;)*', 'ig'),
478
- format: new _w.RegExp('\s*(text-align|margin-left|margin-right)\s*:[^;]+(?!;)*', 'ig')
477
+ span: new _w.RegExp('\\s*[^-a-zA-Z](font-family|font-size|color|background-color)\\s*:[^;]+(?!;)*', 'ig'),
478
+ format: new _w.RegExp('\\s*[^-a-zA-Z](text-align|margin-left|margin-right)\\s*:[^;]+(?!;)*', 'ig'),
479
+ fontSizeUnit: new _w.RegExp('\\d+' + options.fontSizeUnit + '$', 'i'),
479
480
  },
480
481
 
481
482
  /**
@@ -1670,6 +1671,51 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
1670
1671
  }
1671
1672
  },
1672
1673
 
1674
+ _checkDuplicateNode: function (oNode, parentNode) {
1675
+ (function recursionFunc(current) {
1676
+ core._dupleCheck(current, parentNode);
1677
+ const childNodes = current.childNodes;
1678
+ for (let i = 0, len = childNodes.length; i < len; i++) {
1679
+ recursionFunc(childNodes[i]);
1680
+ }
1681
+ })(oNode);
1682
+ },
1683
+
1684
+ _dupleCheck: function (oNode, parentNode) {
1685
+ if (!util.isTextStyleElement(oNode)) return;
1686
+
1687
+ const oStyles = (oNode.style.cssText.match(/[^;]+;/g) || []).map(function(v){ return v.trim(); });
1688
+ const nodeName = oNode.nodeName;
1689
+ if (/^span$/i.test(nodeName) && oStyles.length === 0) return oNode;
1690
+
1691
+ let duple = false;
1692
+ (function recursionFunc(ancestor) {
1693
+ if (util.isWysiwygDiv(ancestor) || !util.isTextStyleElement(ancestor)) return;
1694
+
1695
+ if (ancestor.nodeName === nodeName) {
1696
+ duple = true;
1697
+ (ancestor.style.cssText.match(/[^;]+;/g) || []).forEach(function(v){
1698
+ let i;
1699
+ if ((i = oStyles.indexOf(v.trim())) > -1) {
1700
+ oStyles.splice(i, 1);
1701
+ }
1702
+ });
1703
+ ancestor.classList.forEach(function(v){
1704
+ oNode.classList.remove(v);
1705
+ });
1706
+ }
1707
+
1708
+ recursionFunc(ancestor.parentElement);
1709
+ })(parentNode);
1710
+
1711
+ if (duple) {
1712
+ if (!(oNode.style.cssText = oStyles.join(' '))) oNode.removeAttribute('style');
1713
+ if (!oNode.attributes.length) oNode.setAttribute('data-se-duple', 'true');
1714
+ }
1715
+
1716
+ return oNode;
1717
+ },
1718
+
1673
1719
  /**
1674
1720
  * @description Delete selected node and insert argument value node and return.
1675
1721
  * If the "afterNode" exists, it is inserted after the "afterNode"
@@ -1777,7 +1823,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
1777
1823
  let c = parentNode.childNodes[startOff];
1778
1824
  const focusNode = (c && c.nodeType === 3 && util.onlyZeroWidthSpace(c) && util.isBreak(c.nextSibling)) ? c.nextSibling : c;
1779
1825
  if (focusNode) {
1780
- if (!focusNode.nextSibling) {
1826
+ if (!focusNode.nextSibling && util.isBreak(focusNode)) {
1781
1827
  parentNode.removeChild(focusNode);
1782
1828
  afterNode = null;
1783
1829
  } else {
@@ -1793,7 +1839,6 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
1793
1839
  }
1794
1840
  } else { /** Select range nodes */
1795
1841
  const isSameContainer = startCon === endCon;
1796
-
1797
1842
  if (isSameContainer) {
1798
1843
  if (this.isEdgePoint(endCon, endOff)) afterNode = endCon.nextSibling;
1799
1844
  else afterNode = endCon.splitText(endOff);
@@ -1916,6 +1961,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
1916
1961
  insertListCell = true;
1917
1962
  }
1918
1963
 
1964
+ this._checkDuplicateNode(oNode, parentNode);
1919
1965
  parentNode.insertBefore(oNode, afterNode);
1920
1966
 
1921
1967
  if (insertListCell) {
@@ -1939,9 +1985,27 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
1939
1985
  }
1940
1986
  }
1941
1987
  }
1942
- } catch (e) {
1988
+ } catch (error) {
1943
1989
  parentNode.appendChild(oNode);
1990
+ console.warn('[SUNEDITOR.insertNode.warn] ' + error);
1944
1991
  } finally {
1992
+ const dupleNodes = parentNode.querySelectorAll('[data-se-duple]');
1993
+ if (dupleNodes.length > 0) {
1994
+ for (let i = 0, len = dupleNodes.length, d, c, ch, parent; i < len; i++) {
1995
+ d = dupleNodes[i];
1996
+ ch = d.childNodes;
1997
+ parent = d.parentNode;
1998
+
1999
+ while (ch[0]) {
2000
+ c = ch[0];
2001
+ parent.insertBefore(c, d);
2002
+ }
2003
+
2004
+ if (d === oNode) oNode = c;
2005
+ util.removeItem(d);
2006
+ }
2007
+ }
2008
+
1945
2009
  if ((util.isFormatElement(oNode) || util.isComponent(oNode)) && startCon === endCon) {
1946
2010
  const cItem = util.getFormatElement(commonCon, null);
1947
2011
  if (cItem && cItem.nodeType === 1 && util.isEmptyLine(cItem)) {
@@ -2057,6 +2121,16 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
2057
2121
  startOff = endOff = 0;
2058
2122
  }
2059
2123
 
2124
+ if (startCon === endCon && range.collapsed) {
2125
+ if (startCon.textContent && util.onlyZeroWidthSpace(startCon.textContent.substr(startOff))) {
2126
+ return {
2127
+ container: startCon,
2128
+ offset: offset,
2129
+ prevContainer: startCon && startCon.parentNode ? startCon : null
2130
+ };
2131
+ }
2132
+ }
2133
+
2060
2134
  let beforeNode = null;
2061
2135
  let afterNode = null;
2062
2136
 
@@ -4721,7 +4795,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
4721
4795
  _var._codeOriginCssText = code.style.cssText;
4722
4796
 
4723
4797
  editorArea.style.cssText = toolbar.style.cssText = '';
4724
- wysiwygFrame.style.cssText = (wysiwygFrame.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/) || [''])[0];
4798
+ wysiwygFrame.style.cssText = (wysiwygFrame.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/) || [''])[0] + options.defaultStyle;
4725
4799
  code.style.cssText = (code.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/) || [''])[0];
4726
4800
  toolbar.style.width = wysiwygFrame.style.height = code.style.height = '100%';
4727
4801
  toolbar.style.position = 'relative';
@@ -4889,7 +4963,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
4889
4963
  '<!DOCTYPE html><html>' +
4890
4964
  '<head>' +
4891
4965
  '<meta charset="utf-8" />' +
4892
- '<meta name="viewport" content="width=device-width, initial-scale=1">' +
4966
+ '<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">' +
4893
4967
  '<title>' + lang.toolbar.preview + '</title>' +
4894
4968
  linkHTML +
4895
4969
  '</head>' +
@@ -5102,6 +5176,32 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5102
5176
  .replace(this.editorTagsBlacklistRegExp, '');
5103
5177
  },
5104
5178
 
5179
+ _convertFontSize: function (to, size) {
5180
+ const value = size.match(/(\d+(?:\.\d+)?)(.+)/);
5181
+ const sizeNum = value[1] * 1;
5182
+ const from = value[2];
5183
+ let pxSize = sizeNum;
5184
+
5185
+ if (/em/.test(from)) {
5186
+ pxSize = this.round(sizeNum / 0.0625);
5187
+ } else if (from === 'pt') {
5188
+ pxSize = this.round(sizeNum * 1.333);
5189
+ } else if (from === '%') {
5190
+ pxSize = sizeNum / 100;
5191
+ }
5192
+
5193
+ switch (to) {
5194
+ case 'em':
5195
+ case 'rem':
5196
+ case '%':
5197
+ return (pxSize * 0.0625).toFixed(2) + to;
5198
+ case 'pt':
5199
+ return this._w.Math.floor(pxSize / 1.333) + to;
5200
+ default: // px
5201
+ return pxSize + to;
5202
+ }
5203
+ },
5204
+
5105
5205
  _cleanStyle: function (m, v, name) {
5106
5206
  const sv = m.match(/style\s*=\s*(?:"|')[^"']*(?:"|')/);
5107
5207
  if (sv) {
@@ -5121,6 +5221,9 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5121
5221
  break;
5122
5222
  case 'fontSize':
5123
5223
  if (!options.plugins.fontSize) continue;
5224
+ if (!this._cleanStyleRegExp.fontSizeUnit.test(r[0])) {
5225
+ r[0] = r[0].replace(this._w.RegExp('\\d+' + r[0].match(/\d+(.+$)/)[1]), this._convertFontSize.bind(this._w.Math, options.fontSizeUnit));
5226
+ }
5124
5227
  break;
5125
5228
  case 'color':
5126
5229
  if (!options.plugins.fontColor || /rgba\(([0-9]+\s*,\s*){3}0\)|windowtext/i.test(c)) continue;
@@ -5299,7 +5402,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5299
5402
  * @returns {String}
5300
5403
  */
5301
5404
  cleanHTML: function (html, whitelist, blacklist) {
5302
- html = this._deleteDisallowedTags(this._parser.parseFromString(html, 'text/html').body.innerHTML).replace(/(<[a-zA-Z0-9\-]+)[^>]*(?=>)/g, this._cleanTags.bind(this, true)).replace(/^.+\x3C!--StartFragment--\>|\x3C!--EndFragment-->.+$/g, '');
5405
+ html = this._deleteDisallowedTags(this._parser.parseFromString(html, 'text/html').body.innerHTML).replace(/(<[a-zA-Z0-9\-]+)[^>]*(?=>)/g, this._cleanTags.bind(this, true));
5303
5406
 
5304
5407
  const dom = _d.createRange().createContextualFragment(html);
5305
5408
  try {
@@ -5925,7 +6028,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5925
6028
  },
5926
6029
 
5927
6030
  __callResizeFunction: function (h, resizeObserverEntry) {
5928
- h = h === -1 ? (resizeObserverEntry.borderBoxSize ? resizeObserverEntry.borderBoxSize[0].blockSize : (resizeObserverEntry.contentRect.height + this._editorHeightPadding)) : h;
6031
+ h = h === -1 ? (resizeObserverEntry.borderBoxSize && resizeObserverEntry.borderBoxSize[0] ? resizeObserverEntry.borderBoxSize[0].blockSize : (resizeObserverEntry.contentRect.height + this._editorHeightPadding)) : h;
5929
6032
  if (this._editorHeight !== h) {
5930
6033
  if (typeof functions.onResizeEditor === 'function') functions.onResizeEditor(h, this._editorHeight, core, resizeObserverEntry);
5931
6034
  this._editorHeight = h;
@@ -6063,18 +6166,24 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
6063
6166
 
6064
6167
  // toolbar visibility
6065
6168
  context.element.toolbar.style.visibility = '';
6169
+ // wisywig attributes
6170
+ const attr = options.frameAttrbutes;
6171
+ for (let k in attr) {
6172
+ context.element.wysiwyg.setAttribute(k, attr[k]);
6173
+ }
6066
6174
 
6067
6175
  this._checkComponents();
6068
6176
  this._componentsInfoInit = false;
6069
6177
  this._componentsInfoReset = false;
6070
6178
 
6071
6179
  this.history.reset(true);
6072
- this._resourcesStateChange();
6073
-
6180
+
6074
6181
  _w.setTimeout(function () {
6075
6182
  // observer
6076
6183
  if (event._resizeObserver) event._resizeObserver.observe(context.element.wysiwygFrame);
6077
6184
  if (event._toolbarObserver) event._toolbarObserver.observe(context.element._toolbarShadow);
6185
+ // resource state
6186
+ core._resourcesStateChange();
6078
6187
  // user event
6079
6188
  if (typeof functions.onload === 'function') functions.onload(core, reload);
6080
6189
  });
@@ -6617,9 +6726,6 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
6617
6726
 
6618
6727
  core._editorRange();
6619
6728
 
6620
- // user event
6621
- if (typeof functions.onInput === 'function' && functions.onInput(e, core) === false) return;
6622
-
6623
6729
  const data = (e.data === null ? '' : e.data === undefined ? ' ' : e.data) || '';
6624
6730
  if (!core._charCount(data)) {
6625
6731
  e.preventDefault();
@@ -6627,6 +6733,9 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
6627
6733
  return false;
6628
6734
  }
6629
6735
 
6736
+ // user event
6737
+ if (typeof functions.onInput === 'function' && functions.onInput(e, core) === false) return;
6738
+
6630
6739
  // history stack
6631
6740
  core.history.push(true);
6632
6741
  },
@@ -7774,6 +7883,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
7774
7883
  const onlyText = !cleanData;
7775
7884
 
7776
7885
  if (!onlyText) {
7886
+ cleanData = cleanData.replace(/^<html>\r?\n?<body>\r?\n?\x3C!--StartFragment--\>|\x3C!--EndFragment-->\r?\n?<\/body\>\r?\n?<\/html>$/g, '');
7777
7887
  if (MSData) {
7778
7888
  cleanData = cleanData.replace(/\n/g, ' ');
7779
7889
  plainText = plainText.replace(/\n/g, ' ');
@@ -8061,12 +8171,12 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
8061
8171
  */
8062
8172
  onChange: null,
8063
8173
 
8064
- /**
8174
+ /**
8065
8175
  * @description Event functions
8066
8176
  * @param {String} contents Current contents
8067
8177
  * @param {Object} core Core object
8068
8178
  */
8069
- onSave: null,
8179
+ onSave: null,
8070
8180
 
8071
8181
  /**
8072
8182
  * @description Event functions (drop, paste)
@@ -8435,6 +8545,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
8435
8545
 
8436
8546
  /**
8437
8547
  * @description Copying the contents of the editor to the original textarea and execute onSave callback
8548
+ * * not working during enabled codeView mode
8438
8549
  */
8439
8550
  save: function () {
8440
8551
  const contents = core.getContents(false);
@@ -8452,6 +8563,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
8452
8563
 
8453
8564
  /**
8454
8565
  * @description Gets the contents of the suneditor
8566
+ * * not working during enabled codeView mode
8455
8567
  * @param {Boolean} onlyContents - Return only the contents of the body without headers when the "fullPage" option is true
8456
8568
  * @returns {String}
8457
8569
  */
@@ -8461,6 +8573,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
8461
8573
 
8462
8574
  /**
8463
8575
  * @description Gets only the text of the suneditor contents
8576
+ * * not working during enabled codeView mode
8464
8577
  * @returns {String}
8465
8578
  */
8466
8579
  getText: function () {
package/src/lib/util.js CHANGED
@@ -1805,7 +1805,7 @@ const util = {
1805
1805
  // wrong position
1806
1806
  const wrongTags = this.getListChildNodes(documentFragment, function (current) {
1807
1807
  if (current.nodeType !== 1) {
1808
- if (this.isList(current.parentNode)) removeTags.push(current);
1808
+ if (this.isList(current.parentElement)) removeTags.push(current);
1809
1809
  return false;
1810
1810
  }
1811
1811
 
@@ -1947,7 +1947,7 @@ const util = {
1947
1947
  frame.setAttribute('scrolling', 'auto');
1948
1948
  frame.contentDocument.head.innerHTML = '' +
1949
1949
  '<meta charset="utf-8" />' +
1950
- '<meta name="viewport" content="width=device-width, initial-scale=1">' +
1950
+ '<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">' +
1951
1951
  this._setIframeCssTags(options);
1952
1952
  frame.contentDocument.body.className = options._editableClass;
1953
1953
  frame.contentDocument.body.setAttribute('contenteditable', true);
@@ -649,7 +649,7 @@ export default {
649
649
  oImg.src = src;
650
650
  oImg.alt = alt;
651
651
  oImg.setAttribute('data-rotate', '0');
652
- anchor = imagePlugin.onRender_link.call(this, oImg, anchor);
652
+ anchor = imagePlugin.onRender_link.call(this, oImg, anchor ? anchor.cloneNode(false) : null);
653
653
 
654
654
  if (contextImage._resizing) {
655
655
  oImg.setAttribute('data-proportion', contextImage._proportionChecked);
@@ -933,8 +933,8 @@ export default {
933
933
  */
934
934
  setSize: function (w, h, notResetPercentage, direction) {
935
935
  const contextImage = this.context.image;
936
- const onlyW = /^(rw|lw)$/.test(direction);
937
- const onlyH = /^(th|bh)$/.test(direction);
936
+ const onlyW = /^(rw|lw)$/.test(direction) && /\d+/.test(contextImage._element.style.height);
937
+ const onlyH = /^(th|bh)$/.test(direction) && /\d+/.test(contextImage._element.style.width);
938
938
 
939
939
  if (!onlyH) {
940
940
  contextImage._element.style.width = this.util.isNumber(w) ? w + contextImage.sizeUnit : w;
@@ -957,6 +957,7 @@ export default {
957
957
  setAutoSize: function () {
958
958
  const contextImage = this.context.image;
959
959
 
960
+ if (contextImage._caption) contextImage._caption.style.marginTop = '';
960
961
  this.plugins.resizing.resetTransform.call(this, contextImage._element);
961
962
  this.plugins.image.cancelPercentAttr.call(this);
962
963
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  import dialog from '../modules/dialog';
4
4
 
5
+ const KATEX_WEBSITE = "https://katex.org/docs/supported.html";
6
+
5
7
  export default {
6
8
  name: 'math',
7
9
  display: 'dialog',
@@ -63,7 +65,7 @@ export default {
63
65
  '</div>' +
64
66
  '<div class="se-dialog-body">' +
65
67
  '<div class="se-dialog-form">' +
66
- '<label>' + lang.dialogBox.mathBox.inputLabel + ' (<a href="https://katex.org/docs/supported.html" target="_blank">KaTeX</a>)</label>' +
68
+ '<label>' + lang.dialogBox.mathBox.inputLabel + ' (<a href="' + KATEX_WEBSITE + '" target="_blank">KaTeX</a>)</label>' +
67
69
  '<textarea class="se-input-form se-math-exp" type="text"></textarea>' +
68
70
  '</div>' +
69
71
  '<div class="se-dialog-form">' +
@@ -140,9 +142,11 @@ export default {
140
142
  _renderer: function (exp) {
141
143
  let result = '';
142
144
  try {
145
+ this.util.removeClass(this.context.math.focusElement, 'se-error');
143
146
  result = this.options.katex.src.renderToString(exp, {throwOnError: true, displayMode: true});
144
147
  } catch(error) {
145
- result = '<span class="se-math-katex-error">' + error + '</span>';
148
+ this.util.addClass(this.context.math.focusElement, 'se-error');
149
+ result = '<span class="se-math-katex-error">Katex syntax error. (Refer <a href="' + KATEX_WEBSITE + '" target="_blank">KaTeX</a>)</span>';
146
150
  console.warn('[SUNEDITOR.math.Katex.error] ', error);
147
151
  }
148
152
  return result;
@@ -540,7 +540,7 @@ export default {
540
540
  url = 'https://player.vimeo.com/video/' + url.slice(url.lastIndexOf('/') + 1);
541
541
  }
542
542
 
543
- this.plugins.video.create_video.call(this, this.plugins.video[(!/youtu\.?be/.test(url) && !/vimeo\.com/.test(url) ? "createVideoTag" : "createIframeTag")].call(this), url, contextVideo.inputX.value, contextVideo.inputY.value, contextVideo._align, null, this.context.dialog.updateModal);
543
+ this.plugins.video.create_video.call(this, this.plugins.video[(!/embed|iframe|player|\/e\/|\.php|\.html?/.test(url) && !/vimeo\.com/.test(url) ? "createVideoTag" : "createIframeTag")].call(this), url, contextVideo.inputX.value, contextVideo.inputY.value, contextVideo._align, null, this.context.dialog.updateModal);
544
544
  } catch (error) {
545
545
  throw Error('[SUNEDITOR.video.upload.fail] cause : "' + error.message + '"');
546
546
  } finally {