@syncfusion/ej2-richtexteditor 21.1.37 → 21.1.41

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 (28) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/ej2-richtexteditor.min.js +2 -2
  3. package/dist/ej2-richtexteditor.umd.min.js +2 -2
  4. package/dist/ej2-richtexteditor.umd.min.js.map +1 -1
  5. package/dist/es6/ej2-richtexteditor.es2015.js +222 -114
  6. package/dist/es6/ej2-richtexteditor.es2015.js.map +1 -1
  7. package/dist/es6/ej2-richtexteditor.es5.js +209 -102
  8. package/dist/es6/ej2-richtexteditor.es5.js.map +1 -1
  9. package/dist/global/ej2-richtexteditor.min.js +2 -2
  10. package/dist/global/ej2-richtexteditor.min.js.map +1 -1
  11. package/dist/global/index.d.ts +1 -1
  12. package/package.json +11 -11
  13. package/src/editor-manager/plugin/clearformat-exec.js +1 -1
  14. package/src/editor-manager/plugin/clearformat.d.ts +1 -1
  15. package/src/editor-manager/plugin/clearformat.js +2 -2
  16. package/src/editor-manager/plugin/ms-word-clean-up.js +4 -3
  17. package/src/editor-manager/plugin/selection-commands.d.ts +1 -0
  18. package/src/editor-manager/plugin/selection-commands.js +102 -63
  19. package/src/editor-manager/plugin/table.js +13 -2
  20. package/src/editor-manager/plugin/video.js +2 -1
  21. package/src/rich-text-editor/actions/paste-clean-up.d.ts +2 -0
  22. package/src/rich-text-editor/actions/paste-clean-up.js +60 -23
  23. package/src/rich-text-editor/actions/xhtml-validation.js +2 -1
  24. package/src/rich-text-editor/base/rich-text-editor.js +17 -0
  25. package/src/rich-text-editor/base/util.js +2 -1
  26. package/src/rich-text-editor/renderer/iframe-content-renderer.js +1 -1
  27. package/src/rich-text-editor/renderer/image-module.js +2 -2
  28. package/src/rich-text-editor/renderer/video-module.js +2 -2
@@ -3008,8 +3008,9 @@ function decode(value) {
3008
3008
  function sanitizeHelper(value, parent) {
3009
3009
  if (parent.enableHtmlSanitizer) {
3010
3010
  const item = SanitizeHtmlHelper.beforeSanitize();
3011
- if (item.selectors.tags[2] && item.selectors.tags[2].indexOf('iframe') > -1)
3011
+ if (item.selectors.tags[2] && item.selectors.tags[2].indexOf('iframe') > -1) {
3012
3012
  item.selectors.tags[2] = 'iframe:not(.e-rte-embed-url)';
3013
+ }
3013
3014
  const beforeEvent = {
3014
3015
  cancel: false,
3015
3016
  helper: null
@@ -5075,7 +5076,7 @@ class Toolbar$2 {
5075
5076
  toolbarClickHandler(e) {
5076
5077
  const trg = closest(e.originalEvent.target, '.e-hor-nav');
5077
5078
  if (trg && this.parent.toolbarSettings.type === ToolbarType.Expand && !isNullOrUndefined(trg)) {
5078
- let extendedTbar = this.tbElement.querySelector('.e-toolbar-extended');
5079
+ const extendedTbar = this.tbElement.querySelector('.e-toolbar-extended');
5079
5080
  if (!isNullOrUndefined(extendedTbar)) {
5080
5081
  setStyleAttribute(extendedTbar, { maxHeight: '', display: 'block' });
5081
5082
  setStyleAttribute(extendedTbar, { maxHeight: extendedTbar.offsetHeight + 'px', display: '' });
@@ -5956,8 +5957,8 @@ class BaseQuickToolbar {
5956
5957
  }
5957
5958
  if (!isNullOrUndefined(document.querySelector('.e-tooltip-wrap'))) {
5958
5959
  if (!isNullOrUndefined(document.querySelector('#' + this.element.id + ' [data-tooltip-id]'))) {
5959
- let tooltipTargetEle = document.querySelector('#' + this.element.id + ' [data-tooltip-id]');
5960
- let dataContent = tooltipTargetEle.getAttribute('data-content');
5960
+ const tooltipTargetEle = document.querySelector('#' + this.element.id + ' [data-tooltip-id]');
5961
+ const dataContent = tooltipTargetEle.getAttribute('data-content');
5961
5962
  tooltipTargetEle.removeAttribute('data-content');
5962
5963
  tooltipTargetEle.setAttribute('title', dataContent);
5963
5964
  tooltipTargetEle.removeAttribute('data-tooltip-id');
@@ -14440,8 +14441,9 @@ class VideoCommand {
14440
14441
  : (Browser.isIE ? selectedNode : !e.item.isEmbedUrl ? selectedNode.lastElementChild : selectedNode.querySelector('iframe'));
14441
14442
  videoElm.addEventListener(videoElm.tagName !== 'IFRAME' ? 'loadeddata' : 'load', () => {
14442
14443
  if (e.value !== 'VideoReplace' || !isReplaced) {
14443
- if (e.item.isEmbedUrl && videoElm)
14444
+ if (e.item.isEmbedUrl && videoElm) {
14444
14445
  videoElm.classList.add('e-rte-embed-url');
14446
+ }
14445
14447
  e.callBack({
14446
14448
  requestType: 'Videos',
14447
14449
  editorMode: 'HTML',
@@ -14856,7 +14858,7 @@ class TableCommand {
14856
14858
  const colIndex = Array.prototype.indexOf.call(selectedCell.parentNode.childNodes, selectedCell);
14857
14859
  this.curTable = closest(selectedCell, 'table');
14858
14860
  let currentRow;
14859
- const allCells = this.getCorrespondingColumns();
14861
+ let allCells = this.getCorrespondingColumns();
14860
14862
  const minMaxIndex = this.getSelectedCellMinMaxIndex(allCells);
14861
14863
  let maxI;
14862
14864
  let j;
@@ -14871,8 +14873,19 @@ class TableCommand {
14871
14873
  if (j === 0 || allCells[maxI][j] !== allCells[maxI][j - 1]) {
14872
14874
  if (1 < parseInt(allCells[maxI][j].getAttribute('rowspan'), 10)) {
14873
14875
  const rowSpanVal = parseInt(allCells[maxI][j].getAttribute('rowspan'), 10) - 1;
14874
- //eslint-disable-next-line
14875
- 1 === rowSpanVal ? allCells[maxI][j].removeAttribute('rowspan') : allCells[maxI][j].setAttribute('rowspan', rowSpanVal.toString());
14876
+ /* eslint-disable */
14877
+ if (1 === rowSpanVal) {
14878
+ allCells[maxI][j].removeAttribute('rowspan');
14879
+ const cell = allCells[maxI][j].cloneNode(true);
14880
+ allCells = this.getCorrespondingColumns();
14881
+ if (allCells[rowSpanVal][j] && allCells[rowSpanVal][j].parentElement) {
14882
+ allCells[rowSpanVal][j].parentElement.insertBefore(cell, allCells[rowSpanVal][j]);
14883
+ }
14884
+ }
14885
+ else {
14886
+ allCells[maxI][j].setAttribute('rowspan', rowSpanVal.toString());
14887
+ }
14888
+ /* eslint-enable */
14876
14889
  }
14877
14890
  }
14878
14891
  // eslint-disable-next-line max-len
@@ -15780,18 +15793,13 @@ class SelectionCommands {
15780
15793
  isSubSup = formatNode === null ? false : true;
15781
15794
  }
15782
15795
  }
15783
- else if ((format === 'fontsize' || format === 'fontname' || format === 'fontcolor' || format === 'backgroundcolor') && range.startContainer.parentElement === endNode) {
15784
- formatNode = null;
15785
- }
15786
15796
  if (index === 0 && formatNode === null) {
15787
15797
  isFormat = true;
15788
15798
  }
15789
15799
  if (formatNode !== null && (!isFormat || isFontStyle)) {
15790
15800
  nodes[index] = this.removeFormat(nodes, index, formatNode, isCursor, isFormat, isFontStyle, range, nodeCutter, format, value, domSelection, endNode, domNode);
15791
15801
  }
15792
- else if (range.startContainer.parentElement !== endNode ||
15793
- (range.commonAncestorContainer !== endNode && range.startContainer.parentElement === endNode)
15794
- || (range.commonAncestorContainer === endNode || nodes.length === 1)) {
15802
+ else {
15795
15803
  nodes[index] = this.insertFormat(docElement, nodes, index, formatNode, isCursor, isFormat, isFontStyle, range, nodeCutter, format, value, painterValues, domNode, endNode);
15796
15804
  }
15797
15805
  domSelection = this.applySelection(nodes, domSelection, nodeCutter, index, isCollapsed);
@@ -15943,6 +15951,27 @@ class SelectionCommands {
15943
15951
  nodes[index] = lastNode.firstChild;
15944
15952
  }
15945
15953
  }
15954
+ else if (isFontStyle && !nodes[index].contains(formatNode) && nodes[index].nodeType === 3 &&
15955
+ nodes[index].textContent !== formatNode.textContent) {
15956
+ // If the selection is within the format node .
15957
+ const isFullNodeSelected = nodes[index].textContent === nodes[index].wholeText;
15958
+ let nodeTraverse = nodes[index];
15959
+ const styleElement = this.GetFormatNode(format, value);
15960
+ // while loop and traverse back until text content does not match with parent text content
15961
+ while (nodeTraverse && nodeTraverse.textContent === nodeTraverse.parentElement.textContent) {
15962
+ nodeTraverse = nodeTraverse.parentElement;
15963
+ }
15964
+ if (isFullNodeSelected && formatNode.textContent !== nodeTraverse.textContent) {
15965
+ const nodeArray = [];
15966
+ const priorityNode = this.getPriorityFormatNode(nodeTraverse, endNode);
15967
+ if (priorityNode && priorityNode.textContent === nodeTraverse.textContent) {
15968
+ nodeTraverse = priorityNode;
15969
+ }
15970
+ nodeArray.push(nodeTraverse);
15971
+ this.applyStyles(nodeArray, 0, styleElement);
15972
+ return nodes[index];
15973
+ }
15974
+ }
15946
15975
  let fontStyle;
15947
15976
  if (format === 'backgroundcolor') {
15948
15977
  fontStyle = formatNode.style.fontSize;
@@ -16089,23 +16118,9 @@ class SelectionCommands {
16089
16118
  return nodes[index];
16090
16119
  }
16091
16120
  static insertFormat(docElement, nodes, index, formatNode, isCursor, isFormat, isFontStyle, range, nodeCutter, format, value, painterValues, domNode, endNode) {
16092
- let rootElementNode;
16093
16121
  if (!isCursor) {
16094
16122
  if ((formatNode === null && isFormat) || isFontStyle) {
16095
16123
  if (nodes[index].nodeName !== 'BR') {
16096
- if (format === 'fontsize' || format === 'fontname' || format === 'fontcolor' || format === 'backgroundcolor') {
16097
- let rangeNode = nodes[index];
16098
- while (rangeNode && !domNode.isBlockNode(rangeNode) && rangeNode !== endNode) {
16099
- if (domNode.isBlockNode(rangeNode.parentElement)) {
16100
- rootElementNode = rangeNode;
16101
- }
16102
- rangeNode = rangeNode.parentElement;
16103
- }
16104
- if (rootElementNode && rootElementNode.nodeType !== 3) {
16105
- nodeCutter.SplitNode(range, rootElementNode, true).cloneNode(true);
16106
- nodeCutter.SplitNode(range, rootElementNode, false).cloneNode(false);
16107
- }
16108
- }
16109
16124
  nodes[index] = nodeCutter.GetSpliceNode(range, nodes[index]);
16110
16125
  nodes[index].textContent = nodeCutter.TrimLineBreak(nodes[index].textContent);
16111
16126
  }
@@ -16115,57 +16130,63 @@ class SelectionCommands {
16115
16130
  }
16116
16131
  else if (!(isFontStyle === true && value === '')) {
16117
16132
  const element = this.GetFormatNode(format, value);
16118
- if (value === 'formatPainter' || format === 'fontsize' || format === 'fontcolor' || format === 'fontname' || format === 'backgroundcolor') {
16119
- if (format !== 'fontname' && format !== 'backgroundcolor') {
16120
- let liElement = nodes[index].parentElement;
16121
- let parentElement = nodes[index].parentElement;
16122
- while (!isNullOrUndefined(parentElement) && parentElement.tagName.toLowerCase() !== 'li') {
16123
- parentElement = parentElement.parentElement;
16124
- liElement = parentElement;
16133
+ if (value === 'formatPainter' || isFontStyle) {
16134
+ let liElement = nodes[index].parentElement;
16135
+ let parentElement = nodes[index].parentElement;
16136
+ while (!isNullOrUndefined(parentElement) && parentElement.tagName.toLowerCase() !== 'li') {
16137
+ parentElement = parentElement.parentElement;
16138
+ liElement = parentElement;
16139
+ }
16140
+ if (!isNullOrUndefined(liElement) && liElement.tagName.toLowerCase() === 'li' &&
16141
+ liElement.textContent.trim() === nodes[index].textContent.trim()) {
16142
+ if (format === 'fontsize') {
16143
+ liElement.style.fontSize = value;
16125
16144
  }
16126
- if (!isNullOrUndefined(liElement) && liElement.tagName.toLowerCase() === 'li' &&
16127
- liElement.textContent.trim() === nodes[index].textContent.trim()) {
16128
- if (format === 'fontsize') {
16129
- liElement.style.fontSize = value;
16130
- }
16131
- else {
16132
- liElement.style.color = value;
16133
- liElement.style.textDecoration = 'inherit';
16134
- }
16145
+ else if (format === 'fontcolor') {
16146
+ liElement.style.color = value;
16147
+ liElement.style.textDecoration = 'inherit';
16135
16148
  }
16136
16149
  }
16137
- if (rootElementNode && rootElementNode.nodeType !== 3 && rootElementNode.nodeName !== 'A') {
16138
- const save = new NodeSelection();
16139
- save.save(range, docElement);
16140
- domNode.setMarker(save);
16141
- const cloneNode = rootElementNode.cloneNode(true);
16142
- element.appendChild(cloneNode);
16143
- domNode.replaceWith(rootElementNode, element.outerHTML);
16144
- const currentStartNode = endNode.querySelector('.e-editor-select-start');
16145
- const currrentEndNode = endNode.querySelector('.e-editor-select-end');
16146
- if (index === 0) {
16147
- nodes[index] = currentStartNode ? currentStartNode.lastChild : nodes[index];
16148
- }
16149
- if (range.startContainer.parentElement === endNode) {
16150
- if (nodes.length > 1) {
16151
- nodes[nodes.length - 1] = currrentEndNode ? currrentEndNode.lastChild : nodes[index];
16150
+ if (value === 'formatPainter') {
16151
+ return this.insertFormatPainterElem(nodes, index, range, nodeCutter, painterValues, domNode);
16152
+ }
16153
+ const currentNode = nodes[index];
16154
+ const priorityNode = this.getPriorityFormatNode(currentNode, endNode);
16155
+ // 1. Checking is there any priority node present in the selection range. (Use case for nested styles);
16156
+ // 2 Or font style is applied. (Use case not a nested style)
16157
+ if (!isNullOrUndefined(priorityNode) || isFontStyle) {
16158
+ let currentFormatNode = isNullOrUndefined(priorityNode) ? currentNode : priorityNode;
16159
+ currentFormatNode = !isNullOrUndefined(priorityNode) && priorityNode.style.fontSize !== '' ?
16160
+ currentFormatNode.firstChild : currentFormatNode;
16161
+ if (isNullOrUndefined(priorityNode) || format === 'fontsize') {
16162
+ while (currentFormatNode) {
16163
+ const isSameTextContent = currentFormatNode.parentElement.textContent.trim()
16164
+ === nodes[index].textContent.trim();
16165
+ if (!domNode.isBlockNode(currentFormatNode.parentElement) && isSameTextContent) {
16166
+ currentFormatNode = currentFormatNode.parentElement;
16167
+ }
16168
+ else {
16169
+ break;
16170
+ }
16152
16171
  }
16153
16172
  }
16154
- domNode.saveMarker(save, null);
16155
- }
16156
- else {
16157
- if (value === 'formatPainter') {
16158
- return this.insertFormatPainterElem(nodes, index, range, nodeCutter, painterValues, domNode);
16173
+ const nodeList = [];
16174
+ // Since color is different for different themnes, we need to wrap the fontColor over the text node.
16175
+ if (format === 'fontcolor') {
16176
+ const closestAnchor = closest(nodes[index].parentElement, 'A');
16177
+ if (!isNullOrUndefined(closestAnchor) && closestAnchor.firstChild.textContent.trim()
16178
+ === nodes[index].textContent.trim()) {
16179
+ currentFormatNode = nodes[index];
16180
+ }
16159
16181
  }
16160
- else {
16161
- nodes[index] = this.applyStyles(nodes, index, element);
16182
+ if (nodes[index].textContent.trim() !== currentFormatNode.textContent.trim()) {
16183
+ currentFormatNode = nodes[index];
16162
16184
  }
16185
+ nodeList[0] = currentFormatNode;
16186
+ this.applyStyles(nodeList, 0, element);
16163
16187
  }
16164
- if (format === 'fontsize') {
16165
- const bg = closest(nodes[index].parentElement, 'span[style*=' + 'background-color' + ']');
16166
- if (!isNullOrUndefined(bg)) {
16167
- nodes[index].parentElement.style.backgroundColor = bg.style.backgroundColor;
16168
- }
16188
+ else {
16189
+ nodes[index] = this.applyStyles(nodes, index, element);
16169
16190
  }
16170
16191
  }
16171
16192
  else {
@@ -16198,6 +16219,37 @@ class SelectionCommands {
16198
16219
  }
16199
16220
  return nodes[index];
16200
16221
  }
16222
+ static getPriorityFormatNode(node, endNode) {
16223
+ const isFormatted = new IsFormatted();
16224
+ const fontSizeNode = isFormatted.getFormattedNode(node, 'fontsize', endNode);
16225
+ let fontColorNode;
16226
+ let backgroundColorNode;
16227
+ let fontNameNode;
16228
+ if (isNullOrUndefined(fontSizeNode)) {
16229
+ backgroundColorNode = isFormatted.getFormattedNode(node, 'backgroundcolor', endNode);
16230
+ if (isNullOrUndefined(backgroundColorNode)) {
16231
+ fontNameNode = isFormatted.getFormattedNode(node, 'fontname', endNode);
16232
+ if (isNullOrUndefined(fontNameNode)) {
16233
+ fontColorNode = isFormatted.getFormattedNode(node, 'fontcolor', endNode);
16234
+ if (isNullOrUndefined(fontColorNode)) {
16235
+ return null;
16236
+ }
16237
+ else {
16238
+ return fontColorNode;
16239
+ }
16240
+ }
16241
+ else {
16242
+ return fontNameNode;
16243
+ }
16244
+ }
16245
+ else {
16246
+ return backgroundColorNode;
16247
+ }
16248
+ }
16249
+ else {
16250
+ return fontSizeNode;
16251
+ }
16252
+ }
16201
16253
  static getInsertNode(docElement, range, format, value) {
16202
16254
  const element = this.GetFormatNode(format, value);
16203
16255
  element.innerHTML = '&#8203;';
@@ -16458,7 +16510,7 @@ class ClearFormat$1 {
16458
16510
  * @hidden
16459
16511
  * @deprecated
16460
16512
  */
16461
- static clear(docElement, endNode, enterAction, selector) {
16513
+ static clear(docElement, endNode, enterAction, selector, command) {
16462
16514
  this.domNode = new DOMNode(endNode, docElement);
16463
16515
  this.defaultTag = enterAction === 'P' ? this.defaultTag : 'div';
16464
16516
  const nodeSelection = new NodeSelection();
@@ -16468,7 +16520,7 @@ class ClearFormat$1 {
16468
16520
  nodeSelection.getSelectionNodeCollectionBr(range);
16469
16521
  const save = nodeSelection.save(range, docElement);
16470
16522
  let cursorRange = false;
16471
- if (range.collapsed) {
16523
+ if (range.collapsed && command !== 'ClearFormat') {
16472
16524
  cursorRange = true;
16473
16525
  range = nodeCutter.GetCursorRange(docElement, range, nodes[0]);
16474
16526
  }
@@ -16722,7 +16774,7 @@ class ClearFormatExec {
16722
16774
  }
16723
16775
  applyClear(e) {
16724
16776
  if (e.subCommand === 'ClearFormat') {
16725
- ClearFormat$1.clear(this.parent.currentDocument, this.parent.editableElement, e.enterAction, e.selector);
16777
+ ClearFormat$1.clear(this.parent.currentDocument, this.parent.editableElement, e.enterAction, e.selector, e.subCommand);
16726
16778
  if (e.callBack) {
16727
16779
  e.callBack({
16728
16780
  requestType: e.subCommand,
@@ -17065,6 +17117,7 @@ class MsWordPaste {
17065
17117
  if (!isNullOrUndefined(imgElem[i].getAttribute('v:shapes')) &&
17066
17118
  imgElem[i].getAttribute('v:shapes').indexOf('Picture') < 0 &&
17067
17119
  imgElem[i].getAttribute('v:shapes').indexOf('圖片') < 0 &&
17120
+ imgElem[i].getAttribute('v:shapes').indexOf('Grafik') < 0 &&
17068
17121
  imgElem[i].getAttribute('v:shapes').indexOf('Image') < 0) {
17069
17122
  detach(imgElem[i]);
17070
17123
  }
@@ -17159,7 +17212,7 @@ class MsWordPaste {
17159
17212
  hexConversion(rtfData) {
17160
17213
  // eslint-disable-next-line
17161
17214
  const picHead = /\{\\pict[\s\S]+?\\bliptag\-?\d+(\\blipupi\-?\d+)?(\{\\\*\\blipuid\s?[\da-fA-F]+)?[\s\}]*?/;
17162
- // eslint-disable-next-line security/detect-non-literal-regexp
17215
+ // eslint-disable-next-line
17163
17216
  const pic = new RegExp('(?:(' + picHead.source + '))([\\da-fA-F\\s]+)\\}', 'g');
17164
17217
  const fullImg = rtfData.match(pic);
17165
17218
  let imgType;
@@ -17223,9 +17276,9 @@ class MsWordPaste {
17223
17276
  removeUnwantedElements(elm) {
17224
17277
  let innerElement = elm.innerHTML;
17225
17278
  for (let i = 0; i < this.removableElements.length; i++) {
17226
- // eslint-disable-next-line security/detect-non-literal-regexp
17279
+ // eslint-disable-next-line
17227
17280
  const regExpStartElem = new RegExp('<' + this.removableElements[i] + '>', 'g');
17228
- // eslint-disable-next-line security/detect-non-literal-regexp
17281
+ // eslint-disable-next-line
17229
17282
  const regExpEndElem = new RegExp('</' + this.removableElements[i] + '>', 'g');
17230
17283
  innerElement = innerElement.replace(regExpStartElem, '');
17231
17284
  innerElement = innerElement.replace(regExpEndElem, '');
@@ -17316,10 +17369,10 @@ class MsWordPaste {
17316
17369
  }
17317
17370
  fromClass = false;
17318
17371
  }
17319
- let listClass = ['MsoListParagraphCxSpFirst', 'MsoListParagraphCxSpMiddle', 'MsoListParagraphCxSpLast'];
17372
+ const listClass = ['MsoListParagraphCxSpFirst', 'MsoListParagraphCxSpMiddle', 'MsoListParagraphCxSpLast'];
17320
17373
  for (let i = 0; i < listClass.length; i++) {
17321
17374
  if (keys.indexOf('li.' + listClass[i]) > -1) {
17322
- let olULElems = elm.querySelectorAll('ol.' + listClass[i] + ', ul.' + listClass[i]);
17375
+ const olULElems = elm.querySelectorAll('ol.' + listClass[i] + ', ul.' + listClass[i]);
17323
17376
  for (let j = 0; j < olULElems.length; j++) {
17324
17377
  const styleProperty = olULElems[j].getAttribute('style');
17325
17378
  if (!isNullOrUndefined(styleProperty) && styleProperty.trim() !== '' && olULElems[j].style.marginLeft !== '') {
@@ -17329,8 +17382,8 @@ class MsWordPaste {
17329
17382
  if (!isNullOrUndefined(valueSplit[k].split(':')[1]) &&
17330
17383
  valueSplit[k].split(':')[1].indexOf('in') >= 0 &&
17331
17384
  olULElems[j].style.marginLeft.indexOf('in') >= 0) {
17332
- let classStyle = parseFloat(valueSplit[k].split(':')[1].split('in')[0]);
17333
- let inlineStyle = parseFloat(olULElems[j].style.marginLeft.split('in')[0]);
17385
+ const classStyle = parseFloat(valueSplit[k].split(':')[1].split('in')[0]);
17386
+ const inlineStyle = parseFloat(olULElems[j].style.marginLeft.split('in')[0]);
17334
17387
  olULElems[j].style.marginLeft = (inlineStyle - classStyle) + 'in';
17335
17388
  }
17336
17389
  }
@@ -17526,14 +17579,14 @@ class MsWordPaste {
17526
17579
  }
17527
17580
  getlistStyleType(listContent, type) {
17528
17581
  let currentListClass;
17529
- let upperRomanNumber = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX',
17582
+ const upperRomanNumber = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX',
17530
17583
  'X', 'XI', 'XII', 'XIII', 'XIV', 'XV', 'XVI', 'XVII', 'XVIII', 'XIX', 'XX'];
17531
- let lowerRomanNumber = ['i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix',
17584
+ const lowerRomanNumber = ['i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix',
17532
17585
  'x', 'xi', 'xii', 'xiii', 'xiv', 'xv', 'xvi', 'xvii', 'xviii', 'xix', 'xx'];
17533
- let lowerGreekNumber = ['α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ',
17586
+ const lowerGreekNumber = ['α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ',
17534
17587
  'μ', 'ν', 'ξ', 'ο', 'π', 'ρ', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω'];
17535
17588
  if (type === 'ol') {
17536
- let charCode = listContent.split('.')[0].charCodeAt(0);
17589
+ const charCode = listContent.split('.')[0].charCodeAt(0);
17537
17590
  switch (true) {
17538
17591
  case upperRomanNumber.indexOf(listContent.split('.')[0]) > -1:
17539
17592
  currentListClass = 'upper-roman';
@@ -19025,6 +19078,8 @@ const IFRAMEHEADER = `
19025
19078
  span.e-table-box.e-rbox-select { background-color: #BDBDBD; border: 1px solid #BDBDBD; }
19026
19079
  .e-table-rhelper { background-color: #4a90e2;}
19027
19080
  .e-rtl { direction: rtl; }
19081
+ .e-rte-placeholder::before { content: attr(placeholder); opacity: 0.54; overflow: hidden;
19082
+ padding-top: 16px; position: absolute; text-align: start; top: 0; z-index: 1; }
19028
19083
  </style>
19029
19084
  </head>`;
19030
19085
  /**
@@ -19242,7 +19297,8 @@ class XhtmlValidation {
19242
19297
  const childEle = ele.childNodes[j];
19243
19298
  if (childEle.nodeType !== 3 && childEle.nodeName !== 'TABLE' && childEle.nodeName !== 'TBODY' &&
19244
19299
  childEle.nodeName !== 'THEAD' && childEle.nodeName !== 'TH' && childEle.nodeName !== 'TR' &&
19245
- childEle.nodeName !== 'TD' && childEle.hasAttribute(attrName)) {
19300
+ childEle.nodeName !== 'TD' && childEle.hasAttribute(attrName) &&
19301
+ !childEle.classList.contains('e-mention-chip')) {
19246
19302
  childEle.removeAttribute(attrName);
19247
19303
  }
19248
19304
  if (childEle.hasChildNodes()) {
@@ -20175,14 +20231,22 @@ class PasteCleanup {
20175
20231
  this.parent.trigger(afterPasteCleanup, { value: value }, (updatedArgs) => {
20176
20232
  value = updatedArgs.value;
20177
20233
  });
20234
+ const tempDivElem = this.parent.createElement('div');
20235
+ tempDivElem.innerHTML = value;
20236
+ const isValueNotEmpty = tempDivElem.textContent !== '' || !isNullOrUndefined(tempDivElem.querySelector('img')) ||
20237
+ !isNullOrUndefined(tempDivElem.querySelector('table'));
20178
20238
  if (this.parent.pasteCleanupSettings.prompt) {
20179
- e.args.preventDefault();
20180
- const tempDivElem = this.parent.createElement('div');
20181
- tempDivElem.innerHTML = value;
20182
- if (tempDivElem.textContent !== '' || !isNullOrUndefined(tempDivElem.querySelector('img')) ||
20183
- !isNullOrUndefined(tempDivElem.querySelector('table'))) {
20239
+ if (isValueNotEmpty) {
20240
+ e.args.preventDefault();
20184
20241
  this.pasteDialog(value, args);
20185
20242
  }
20243
+ else if (Browser.userAgent.indexOf('Firefox') !== -1) {
20244
+ this.fireFoxImageUpload();
20245
+ }
20246
+ }
20247
+ else if (!isValueNotEmpty && !this.parent.pasteCleanupSettings.plainText &&
20248
+ Browser.userAgent.indexOf('Firefox') !== -1) {
20249
+ this.fireFoxImageUpload();
20186
20250
  }
20187
20251
  else if (this.parent.pasteCleanupSettings.plainText) {
20188
20252
  e.args.preventDefault();
@@ -20198,6 +20262,30 @@ class PasteCleanup {
20198
20262
  }
20199
20263
  }
20200
20264
  }
20265
+ fireFoxImageUpload() {
20266
+ // Timeout 500 is added to capture after default paste image from file manager is completed.
20267
+ setTimeout(() => {
20268
+ if (Browser.userAgent.indexOf('Firefox') !== -1) {
20269
+ let currentFocusNode = this.nodeSelectionObj.getRange(this.contentRenderer.getDocument()).startContainer;
20270
+ if (currentFocusNode.nodeName !== '#text') {
20271
+ currentFocusNode = currentFocusNode.childNodes[this.nodeSelectionObj.getRange(this.contentRenderer.getDocument()).startOffset];
20272
+ }
20273
+ if (currentFocusNode.previousSibling.nodeName === 'IMG') {
20274
+ currentFocusNode.previousSibling.classList.add('pasteContent_Img');
20275
+ currentFocusNode.previousSibling.classList.add(CLS_RTE_IMAGE);
20276
+ if (this.parent.insertImageSettings.display === 'inline') {
20277
+ currentFocusNode.previousSibling.classList.add(CLS_IMGINLINE);
20278
+ }
20279
+ else {
20280
+ currentFocusNode.previousSibling.classList.add(CLS_IMGBREAK);
20281
+ }
20282
+ currentFocusNode.previousSibling.classList.add();
20283
+ this.setImageProperties(currentFocusNode.previousSibling);
20284
+ }
20285
+ }
20286
+ this.imgUploading(this.parent.inputElement);
20287
+ }, 500);
20288
+ }
20201
20289
  splitBreakLine(value) {
20202
20290
  const enterSplitText = value.split('\n');
20203
20291
  let contentInnerElem = '';
@@ -20677,24 +20765,7 @@ class PasteCleanup {
20677
20765
  const allImg = clipBoardElem.querySelectorAll('img');
20678
20766
  for (let i = 0; i < allImg.length; i++) {
20679
20767
  allImg[i].classList.add('pasteContent_Img');
20680
- if (this.parent.insertImageSettings.width !== 'auto') {
20681
- allImg[i].setAttribute('width', this.parent.insertImageSettings.width);
20682
- }
20683
- if (this.parent.insertImageSettings.minWidth !== '0' && this.parent.insertImageSettings.minWidth !== 0) {
20684
- allImg[i].style.minWidth = this.parent.insertImageSettings.minWidth.toString();
20685
- }
20686
- if (this.parent.insertImageSettings.maxWidth !== null) {
20687
- allImg[i].style.maxWidth = this.parent.getInsertImgMaxWidth().toString();
20688
- }
20689
- if (this.parent.insertImageSettings.height !== 'auto') {
20690
- allImg[i].setAttribute('height', this.parent.insertImageSettings.height);
20691
- }
20692
- if (this.parent.insertImageSettings.minHeight !== '0' && this.parent.insertImageSettings.minHeight !== 0) {
20693
- allImg[i].style.minHeight = this.parent.insertImageSettings.minHeight.toString();
20694
- }
20695
- if (this.parent.insertImageSettings.maxHeight !== null) {
20696
- allImg[i].style.maxHeight = this.parent.insertImageSettings.maxHeight.toString();
20697
- }
20768
+ this.setImageProperties(allImg[i]);
20698
20769
  }
20699
20770
  this.addTempClass(clipBoardElem);
20700
20771
  if (clipBoardElem.textContent !== '' || !isNullOrUndefined(clipBoardElem.querySelector('img')) ||
@@ -20711,6 +20782,26 @@ class PasteCleanup {
20711
20782
  }
20712
20783
  }
20713
20784
  }
20785
+ setImageProperties(allImg) {
20786
+ if (this.parent.insertImageSettings.width !== 'auto') {
20787
+ allImg.setAttribute('width', this.parent.insertImageSettings.width);
20788
+ }
20789
+ if (this.parent.insertImageSettings.minWidth !== '0' && this.parent.insertImageSettings.minWidth !== 0) {
20790
+ allImg.style.minWidth = this.parent.insertImageSettings.minWidth.toString();
20791
+ }
20792
+ if (this.parent.insertImageSettings.maxWidth !== null) {
20793
+ allImg.style.maxWidth = this.parent.getInsertImgMaxWidth().toString();
20794
+ }
20795
+ if (this.parent.insertImageSettings.height !== 'auto') {
20796
+ allImg.setAttribute('height', this.parent.insertImageSettings.height);
20797
+ }
20798
+ if (this.parent.insertImageSettings.minHeight !== '0' && this.parent.insertImageSettings.minHeight !== 0) {
20799
+ allImg.style.minHeight = this.parent.insertImageSettings.minHeight.toString();
20800
+ }
20801
+ if (this.parent.insertImageSettings.maxHeight !== null) {
20802
+ allImg.style.maxHeight = this.parent.insertImageSettings.maxHeight.toString();
20803
+ }
20804
+ }
20714
20805
  addTempClass(clipBoardElem) {
20715
20806
  const allChild = clipBoardElem.children;
20716
20807
  for (let i = 0; i < allChild.length; i++) {
@@ -22698,7 +22789,7 @@ class Image {
22698
22789
  if (isNullOrUndefined(img.width)) {
22699
22790
  return;
22700
22791
  }
22701
- // eslint-disable-next-line security/detect-unsafe-regex
22792
+ // eslint-disable-next-line
22702
22793
  const width = img.style.width !== '' ? img.style.width.match(/^\d+(\.\d*)?%$/g) ? parseFloat(img.style.width) :
22703
22794
  parseInt(img.style.width, 10) : img.width;
22704
22795
  const height = img.style.height !== '' ? parseInt(img.style.height, 10) : img.height;
@@ -22736,7 +22827,7 @@ class Image {
22736
22827
  img.setAttribute('width', (img.width + this.mouseX).toString());
22737
22828
  }
22738
22829
  else {
22739
- const currentWidth = img.offsetWidth === 0 ? img.width + this.mouseX + parseInt(img.style.outlineWidth.split('p')[0]) : img.offsetWidth + this.mouseX;
22830
+ const currentWidth = img.offsetWidth === 0 ? img.width + this.mouseX + parseInt(img.style.outlineWidth.split('p')[0], 10) : img.offsetWidth + this.mouseX;
22740
22831
  img.setAttribute('width', (currentWidth).toString());
22741
22832
  }
22742
22833
  }
@@ -26646,7 +26737,7 @@ class Video {
26646
26737
  videoUrl.appendChild(urlContent);
26647
26738
  this.embedInputUrl = this.parent.createElement('textarea', {
26648
26739
  className: 'e-input e-embed-video-url',
26649
- attrs: { placeholder: 'Paste Embed URL here', type: 'text', tabindex: '-1', 'aria-label': this.i10n.getConstant('embedVideoLinkHeader') }
26740
+ attrs: { placeholder: 'Paste Embedded Code here', type: 'text', tabindex: '-1', 'aria-label': this.i10n.getConstant('embedVideoLinkHeader') }
26650
26741
  });
26651
26742
  this.embedInputUrl.addEventListener('keyup', () => {
26652
26743
  if (!isNullOrUndefined(this.embedInputUrl)) {
@@ -26673,7 +26764,7 @@ class Video {
26673
26764
  }
26674
26765
  });
26675
26766
  const embedUrlBtn = new RadioButton({
26676
- label: 'Embed URL',
26767
+ label: 'Embedded Code',
26677
26768
  checked: true,
26678
26769
  name: 'URL',
26679
26770
  created: () => {
@@ -30442,7 +30533,7 @@ let RichTextEditor = class RichTextEditor extends Component {
30442
30533
  currentLastElem = currentLastElem.lastChild;
30443
30534
  }
30444
30535
  if (isDetached) {
30445
- let currentLast = currentLastElem.nodeName === 'BR' && !isNullOrUndefined(currentLastElem.previousSibling) ?
30536
+ const currentLast = currentLastElem.nodeName === 'BR' && !isNullOrUndefined(currentLastElem.previousSibling) ?
30446
30537
  currentLastElem.previousSibling : currentLastElem;
30447
30538
  this.formatter.editorManager.nodeSelection.setSelectionText(this.contentModule.getDocument(), isSameContainer ? currentLast : currentStartContainer, currentLast, currentStartOffset, (currentLast.nodeName === 'BR' ? 0 : currentLast.textContent.length));
30448
30539
  }
@@ -30536,6 +30627,9 @@ let RichTextEditor = class RichTextEditor extends Component {
30536
30627
  if ((!isNullOrUndefined(this.placeHolderWrapper)) && (this.inputElement.textContent.length !== 1)) {
30537
30628
  this.placeHolderWrapper.style.display = 'none';
30538
30629
  }
30630
+ else if (this.iframeSettings.enable && this.inputElement.classList.contains("e-rte-placeholder")) {
30631
+ removeClass([this.inputElement], "e-rte-placeholder");
30632
+ }
30539
30633
  else {
30540
30634
  this.setPlaceHolder();
30541
30635
  }
@@ -31237,6 +31331,17 @@ let RichTextEditor = class RichTextEditor extends Component {
31237
31331
  this.inputElement.setAttribute('placeholder', this.placeholder);
31238
31332
  }
31239
31333
  }
31334
+ if (this.placeholder && this.iframeSettings.enable) {
31335
+ if (this.inputElement.textContent.length === 0 && this.inputElement.childNodes.length < 2 && !isNullOrUndefined(this.inputElement.firstChild) && (this.inputElement.firstChild.nodeName === 'BR' ||
31336
+ ((this.inputElement.firstChild.nodeName === 'P' || this.inputElement.firstChild.nodeName === 'DIV') && !isNullOrUndefined(this.inputElement.firstChild.firstChild) &&
31337
+ this.inputElement.firstChild.firstChild.nodeName === 'BR'))) {
31338
+ addClass([this.inputElement], "e-rte-placeholder");
31339
+ this.inputElement.setAttribute('placeholder', this.placeholder);
31340
+ }
31341
+ else {
31342
+ removeClass([this.inputElement], "e-rte-placeholder");
31343
+ }
31344
+ }
31240
31345
  }
31241
31346
  setWidth(width) {
31242
31347
  if (width !== 'auto') {
@@ -31960,6 +32065,9 @@ let RichTextEditor = class RichTextEditor extends Component {
31960
32065
  clearInterval(this.timeInterval);
31961
32066
  this.timeInterval = null;
31962
32067
  }
32068
+ if (!isNullOrUndefined(this.placeHolderWrapper) && this.element.querySelector('[title = Preview]')) {
32069
+ this.placeHolderWrapper.style.display = "none";
32070
+ }
31963
32071
  EventHandler.remove(document, 'mousedown', this.onDocumentClick);
31964
32072
  }
31965
32073
  else {