roosterjs 8.44.1 → 8.45.0

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/dist/rooster.js CHANGED
@@ -2214,6 +2214,9 @@ function changeCapitalization(editor, capitalization, language) {
2214
2214
  }
2215
2215
  }, 'changeCapitalization');
2216
2216
  function getCapitalizedText(originalText, language) {
2217
+ if (originalText === null) {
2218
+ return originalText;
2219
+ }
2217
2220
  switch (capitalization) {
2218
2221
  case "lowercase" /* Lowercase */:
2219
2222
  return originalText.toLocaleLowerCase(language);
@@ -2238,6 +2241,8 @@ function changeCapitalization(editor, capitalization, language) {
2238
2241
  return originalText.toLocaleLowerCase(language).replace(regex, function (match) {
2239
2242
  return match.toLocaleUpperCase(language);
2240
2243
  });
2244
+ default:
2245
+ return originalText;
2241
2246
  }
2242
2247
  }
2243
2248
  }
@@ -2381,11 +2386,11 @@ var TAGS_TO_STOP_UNWRAP = ['TD', 'TH', 'TR', 'TABLE', 'TBODY', 'THEAD'];
2381
2386
  */
2382
2387
  function isMultiBlockSelection(editor) {
2383
2388
  var transverser = editor.getSelectionTraverser();
2384
- var blockElement = transverser.currentBlockElement;
2389
+ var blockElement = transverser === null || transverser === void 0 ? void 0 : transverser.currentBlockElement;
2385
2390
  if (!blockElement) {
2386
2391
  return false;
2387
2392
  }
2388
- var nextBlockElement = transverser.getNextBlockElement();
2393
+ var nextBlockElement = transverser === null || transverser === void 0 ? void 0 : transverser.getNextBlockElement();
2389
2394
  //At least two blocks are selected
2390
2395
  return !!nextBlockElement;
2391
2396
  }
@@ -2468,7 +2473,8 @@ function isNodeWholeBlock(node, editor) {
2468
2473
  }
2469
2474
  var isOnlySiblingWithContent_1 = true;
2470
2475
  (_a = currentNode.parentNode) === null || _a === void 0 ? void 0 : _a.childNodes.forEach(function (node) {
2471
- if (node != currentNode && node.textContent.length) {
2476
+ var _a;
2477
+ if (node != currentNode && ((_a = node.textContent) === null || _a === void 0 ? void 0 : _a.length)) {
2472
2478
  isOnlySiblingWithContent_1 = false;
2473
2479
  }
2474
2480
  });
@@ -2493,7 +2499,7 @@ function clearAutoDetectFormat(editor) {
2493
2499
  var isMultiBlock = isMultiBlockSelection(editor);
2494
2500
  if (!isMultiBlock) {
2495
2501
  var transverser = editor.getSelectionTraverser();
2496
- var inlineElement = transverser.currentInlineElement;
2502
+ var inlineElement = transverser === null || transverser === void 0 ? void 0 : transverser.currentInlineElement;
2497
2503
  var isPartial = inlineElement instanceof roosterjs_editor_dom_1.PartialInlineElement ||
2498
2504
  (inlineElement instanceof roosterjs_editor_dom_1.NodeInlineElement &&
2499
2505
  !isNodeWholeBlock(inlineElement.getContainerNode(), editor));
@@ -2523,8 +2529,11 @@ function clearBlockFormat(editor) {
2523
2529
  (0, roosterjs_editor_dom_1.setStyles)(wrapper, nonborderStyles);
2524
2530
  }
2525
2531
  }
2526
- while (nodes.length > 0 && (0, roosterjs_editor_dom_1.isNodeInRegion)(region, nodes[0].parentNode)) {
2527
- nodes = [(0, roosterjs_editor_dom_1.splitBalancedNodeRange)(nodes)];
2532
+ while (nodes.length > 0 &&
2533
+ nodes[0].parentNode &&
2534
+ (0, roosterjs_editor_dom_1.isNodeInRegion)(region, nodes[0].parentNode)) {
2535
+ var balancedNodes = (0, roosterjs_editor_dom_1.splitBalancedNodeRange)(nodes);
2536
+ nodes = balancedNodes ? [balancedNodes] : [];
2528
2537
  }
2529
2538
  nodes.forEach(clearNodeFormat);
2530
2539
  });
@@ -2576,7 +2585,7 @@ function setDefaultFormat(editor) {
2576
2585
  var setColorIgnoredElements_1 = editor.queryElements('a *, a', 1 /* OnSelection */);
2577
2586
  var shouldApplyInlineStyle = setColorIgnoredElements_1.length > 0
2578
2587
  ? function (element) { return setColorIgnoredElements_1.indexOf(element) == -1; }
2579
- : null;
2588
+ : undefined;
2580
2589
  if (defaultFormat.textColors) {
2581
2590
  (0, setTextColor_1.default)(editor, defaultFormat.textColors, shouldApplyInlineStyle);
2582
2591
  }
@@ -2733,12 +2742,12 @@ function createLink(editor, link, altText, displayText, target) {
2733
2742
  .getDocument()
2734
2743
  .execCommand("createLink" /* CreateLink */, false, normalizedUrl_1);
2735
2744
  var traverser = editor.getSelectionTraverser();
2736
- var currentInline = traverser.getNextInlineElement();
2745
+ var currentInline = traverser === null || traverser === void 0 ? void 0 : traverser.getNextInlineElement();
2737
2746
  // list for removing unwanted lines
2738
2747
  var deletionInlineList = [];
2739
2748
  while (currentInline) {
2740
2749
  deletionInlineList.push(currentInline.getContainerNode());
2741
- currentInline = traverser.getNextInlineElement();
2750
+ currentInline = traverser === null || traverser === void 0 ? void 0 : traverser.getNextInlineElement();
2742
2751
  }
2743
2752
  deletionInlineList.forEach(function (node) { return editor.deleteNode(node); });
2744
2753
  anchor = getAnchorNodeAtCursor(editor);
@@ -2821,7 +2830,7 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
2821
2830
  * @returns An ElementBasedFormatState object
2822
2831
  */
2823
2832
  function getElementBasedFormatState(editor, event) {
2824
- var listTag = (0, roosterjs_editor_dom_1.getTagOfNode)(editor.getElementAtCursor('OL,UL', null /*startFrom*/, event));
2833
+ var listTag = (0, roosterjs_editor_dom_1.getTagOfNode)(editor.getElementAtCursor('OL,UL', undefined /*startFrom*/, event));
2825
2834
  // Check if selection is multiline, spans more than one block
2826
2835
  var range = editor.getSelectionRange();
2827
2836
  var multiline = false;
@@ -2830,7 +2839,7 @@ function getElementBasedFormatState(editor, event) {
2830
2839
  var endingBlock = editor.getBlockElementAtNode(range.endContainer);
2831
2840
  multiline = endingBlock && startingBlock ? !endingBlock.equals(startingBlock) : false;
2832
2841
  }
2833
- var headerTag = (0, roosterjs_editor_dom_1.getTagOfNode)(editor.getElementAtCursor('H1,H2,H3,H4,H5,H6', null /*startFrom*/, event));
2842
+ var headerTag = (0, roosterjs_editor_dom_1.getTagOfNode)(editor.getElementAtCursor('H1,H2,H3,H4,H5,H6', undefined /*startFrom*/, event));
2834
2843
  var table = editor.queryElements('table', 1 /* OnSelection */)[0];
2835
2844
  var tableFormat = table ? (0, roosterjs_editor_dom_1.getTableFormatInfo)(table) : undefined;
2836
2845
  var hasHeader = (table === null || table === void 0 ? void 0 : table.rows[0])
@@ -2847,7 +2856,7 @@ function getElementBasedFormatState(editor, event) {
2847
2856
  isCodeInline: !!editor.queryElements('code', 1 /* OnSelection */)[0],
2848
2857
  isCodeBlock: !!editor.queryElements('pre>code', 1 /* OnSelection */)[0],
2849
2858
  isInTable: !!table,
2850
- tableFormat: tableFormat,
2859
+ tableFormat: tableFormat || {},
2851
2860
  tableHasHeader: hasHeader,
2852
2861
  canMergeTableCell: canMergeTableCell(editor),
2853
2862
  };
@@ -2913,6 +2922,7 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
2913
2922
  * Parent nodes will be split if need
2914
2923
  */
2915
2924
  function insertEntity(editor, type, contentNode, isBlock, isReadonly, position, insertToRegionRoot) {
2925
+ var _a;
2916
2926
  var wrapper = (0, roosterjs_editor_dom_1.wrap)(contentNode, isBlock ? 'DIV' : 'SPAN');
2917
2927
  // For inline & readonly entity, we need to set display to "inline-block" otherwise
2918
2928
  // there will be some weird behavior when move cursor around the entity node.
@@ -2925,7 +2935,7 @@ function insertEntity(editor, type, contentNode, isBlock, isReadonly, position,
2925
2935
  }
2926
2936
  (0, roosterjs_editor_dom_1.commitEntity)(wrapper, type, isReadonly);
2927
2937
  if (!editor.contains(wrapper)) {
2928
- var currentRange = void 0;
2938
+ var currentRange = null;
2929
2939
  var contentPosition = void 0;
2930
2940
  if (typeof position == 'number') {
2931
2941
  contentPosition = position;
@@ -2970,7 +2980,7 @@ function insertEntity(editor, type, contentNode, isBlock, isReadonly, position,
2970
2980
  // Insert an extra empty line for block entity to make sure
2971
2981
  // user can still put cursor below the entity.
2972
2982
  var br = editor.getDocument().createElement('BR');
2973
- wrapper.parentNode.insertBefore(br, wrapper.nextSibling);
2983
+ (_a = wrapper.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(br, wrapper.nextSibling);
2974
2984
  }
2975
2985
  var entity = (0, roosterjs_editor_dom_1.getEntityFromElement)(wrapper);
2976
2986
  if (!isBlock &&
@@ -3029,7 +3039,6 @@ function insertImageWithSrc(editor, src, attributes) {
3029
3039
  return image.setAttribute(attribute, attributes[attribute]);
3030
3040
  });
3031
3041
  }
3032
- image.style.maxWidth = '100%';
3033
3042
  editor.insertNode(image);
3034
3043
  }, 'insertImage');
3035
3044
  }
@@ -3059,7 +3068,9 @@ function removeLink(editor) {
3059
3068
  editor.focus();
3060
3069
  (0, formatUndoSnapshot_1.default)(editor, function (start, end) {
3061
3070
  editor.queryElements('a[href]', 1 /* OnSelection */, roosterjs_editor_dom_1.unwrap);
3062
- editor.select(start, end);
3071
+ if (start && end) {
3072
+ editor.select(start, end);
3073
+ }
3063
3074
  }, 'removeLink');
3064
3075
  }
3065
3076
  exports.default = removeLink;
@@ -3078,14 +3089,15 @@ exports.default = removeLink;
3078
3089
 
3079
3090
  Object.defineProperty(exports, "__esModule", { value: true });
3080
3091
  function replaceWithNode(editor, textOrRange, node, exactMatch, searcher) {
3092
+ var _a, _b;
3081
3093
  // Make sure the text and node is valid
3082
3094
  if (!textOrRange || !node) {
3083
3095
  return false;
3084
3096
  }
3085
3097
  var range;
3086
3098
  if (typeof textOrRange == 'string') {
3087
- searcher = searcher || editor.getContentSearcherOfCursor();
3088
- range = searcher && searcher.getRangeFromText(textOrRange, exactMatch);
3099
+ searcher = (_a = (searcher || editor.getContentSearcherOfCursor())) !== null && _a !== void 0 ? _a : undefined;
3100
+ range = (_b = searcher === null || searcher === void 0 ? void 0 : searcher.getRangeFromText(textOrRange, exactMatch)) !== null && _b !== void 0 ? _b : null;
3089
3101
  }
3090
3102
  else {
3091
3103
  range = textOrRange;
@@ -3093,7 +3105,7 @@ function replaceWithNode(editor, textOrRange, node, exactMatch, searcher) {
3093
3105
  if (range) {
3094
3106
  var backupRange = editor.getSelectionRange();
3095
3107
  // If the range to replace is right before current cursor, it is actually an exact match
3096
- if (backupRange.collapsed &&
3108
+ if ((backupRange === null || backupRange === void 0 ? void 0 : backupRange.collapsed) &&
3097
3109
  range.endContainer == backupRange.startContainer &&
3098
3110
  range.endOffset == backupRange.startOffset) {
3099
3111
  exactMatch = true;
@@ -3170,10 +3182,12 @@ function setAlignment(editor, alignment) {
3170
3182
  var isATable = selection && selection.type === 1 /* TableSelection */;
3171
3183
  var elementAtCursor = editor.getElementAtCursor();
3172
3184
  if (isATable &&
3185
+ selection.coordinates &&
3173
3186
  (0, roosterjs_editor_dom_1.isWholeTableSelected)(new roosterjs_editor_dom_1.VTable(selection.table), selection.coordinates)) {
3174
3187
  alignTable(selection, alignment);
3175
3188
  }
3176
- else if (isList(elementAtCursor) &&
3189
+ else if (elementAtCursor &&
3190
+ isList(elementAtCursor) &&
3177
3191
  editor.isFeatureEnabled("ListItemAlignment" /* ListItemAlignment */)) {
3178
3192
  alignList(editor, alignment);
3179
3193
  }
@@ -3230,7 +3244,9 @@ function alignText(editor, alignment) {
3230
3244
  });
3231
3245
  if (elements.length == 0) {
3232
3246
  var node = editor.getElementAtCursor();
3233
- (0, normalizeBlockquote_1.default)(node);
3247
+ if (node) {
3248
+ (0, normalizeBlockquote_1.default)(node);
3249
+ }
3234
3250
  }
3235
3251
  }
3236
3252
  function isList(element) {
@@ -3241,7 +3257,9 @@ function alignList(editor, alignment) {
3241
3257
  var blocks = (0, roosterjs_editor_dom_1.getSelectedBlockElementsInRegion)(region, undefined /* createBlockIfEmpty */, editor.isFeatureEnabled("DefaultFormatInSpan" /* DefaultFormatInSpan */));
3242
3258
  var startNode = blocks[0].getStartNode();
3243
3259
  var vList = (0, roosterjs_editor_dom_1.createVListFromRegion)(region, true /*includeSiblingLists*/, startNode);
3244
- vList.setAlignment(start, end, alignment);
3260
+ if (start && end) {
3261
+ vList === null || vList === void 0 ? void 0 : vList.setAlignment(start, end, alignment);
3262
+ }
3245
3263
  }, undefined /* beforeRunCallback */, 'alignList');
3246
3264
  }
3247
3265
 
@@ -3305,7 +3323,9 @@ function setDirection(editor, direction) {
3305
3323
  element.setAttribute('dir', direction == 0 /* LeftToRight */ ? 'ltr' : 'rtl');
3306
3324
  element.style.textAlign = direction == 0 /* LeftToRight */ ? 'left' : 'right';
3307
3325
  });
3308
- editor.select(start, end);
3326
+ if (start && end) {
3327
+ editor.select(start, end);
3328
+ }
3309
3329
  }, 'setDirection');
3310
3330
  }
3311
3331
  exports.default = setDirection;
@@ -3447,14 +3467,18 @@ function setIndentation(editor, indentation) {
3447
3467
  isFirstItem(vList, startNode) &&
3448
3468
  shouldHandleWithBlockquotes(indentation, editor, startNode)) {
3449
3469
  var block = editor.getBlockElementAtNode(vList.rootList);
3450
- blockGroups.push([block]);
3470
+ if (block) {
3471
+ blockGroups.push([block]);
3472
+ }
3451
3473
  }
3452
3474
  else {
3453
- indentation == 1 /* Decrease */
3454
- ? vList.setIndentation(start, end, indentation, false /* softOutdent */, isTabKeyTextFeaturesEnabled /* preventItemRemoval */)
3455
- : vList.setIndentation(start, end, indentation);
3456
- vList.writeBack(editor.isFeatureEnabled("ReuseAllAncestorListElements" /* ReuseAllAncestorListElements */));
3457
- blockGroups.push([]);
3475
+ if (start && end) {
3476
+ indentation == 1 /* Decrease */
3477
+ ? vList.setIndentation(start, end, indentation, false /* softOutdent */, isTabKeyTextFeaturesEnabled /* preventItemRemoval */)
3478
+ : vList.setIndentation(start, end, indentation);
3479
+ vList.writeBack(editor.isFeatureEnabled("ReuseAllAncestorListElements" /* ReuseAllAncestorListElements */));
3480
+ blockGroups.push([]);
3481
+ }
3458
3482
  }
3459
3483
  }
3460
3484
  else {
@@ -3465,10 +3489,13 @@ function setIndentation(editor, indentation) {
3465
3489
  }, function () {
3466
3490
  var selection = editor.getSelectionRangeEx();
3467
3491
  if (selection.type == 1 /* TableSelection */ &&
3492
+ selection.coordinates &&
3468
3493
  (0, roosterjs_editor_dom_1.isWholeTableSelected)(new roosterjs_editor_dom_1.VTable(selection.table), selection.coordinates)) {
3469
3494
  if (indentation == 1 /* Decrease */) {
3470
3495
  var quote = editor.getElementAtCursor('blockquote', selection.table);
3471
- (0, roosterjs_editor_dom_1.unwrap)(quote);
3496
+ if (quote) {
3497
+ (0, roosterjs_editor_dom_1.unwrap)(quote);
3498
+ }
3472
3499
  }
3473
3500
  else if (indentation == 0 /* Increase */) {
3474
3501
  (0, roosterjs_editor_dom_1.wrap)(selection.table, 2 /* BlockquoteWrapper */);
@@ -3709,7 +3736,9 @@ function toggleCodeBlock(editor, styler) {
3709
3736
  if (!code.previousSibling && !code.nextSibling) {
3710
3737
  var parent_1 = code.parentNode;
3711
3738
  (0, roosterjs_editor_dom_1.unwrap)(code);
3712
- (0, roosterjs_editor_dom_1.unwrap)(parent_1);
3739
+ if (parent_1) {
3740
+ (0, roosterjs_editor_dom_1.unwrap)(parent_1);
3741
+ }
3713
3742
  }
3714
3743
  }).length == 0;
3715
3744
  }, 'toggleCodeBlock');
@@ -3754,7 +3783,7 @@ function toggleHeader(editor, level) {
3754
3783
  });
3755
3784
  if (level > 0) {
3756
3785
  var traverser = editor.getSelectionTraverser();
3757
- var blockElement = traverser ? traverser.currentBlockElement : null;
3786
+ var blockElement = traverser === null || traverser === void 0 ? void 0 : traverser.currentBlockElement;
3758
3787
  var sanitizer = new roosterjs_editor_dom_1.HtmlSanitizer({
3759
3788
  cssStyleCallbacks: {
3760
3789
  'font-size': function () { return false; },
@@ -3763,7 +3792,7 @@ function toggleHeader(editor, level) {
3763
3792
  while (blockElement) {
3764
3793
  var element = blockElement.collapseToSingleElement();
3765
3794
  sanitizer.sanitize(element);
3766
- blockElement = traverser.getNextBlockElement();
3795
+ blockElement = traverser === null || traverser === void 0 ? void 0 : traverser.getNextBlockElement();
3767
3796
  }
3768
3797
  editor.getDocument().execCommand("formatBlock" /* FormatBlock */, false, "<H" + level + ">");
3769
3798
  }
@@ -4098,12 +4127,21 @@ function editTable(editor, operation) {
4098
4127
  vtable.writeBack();
4099
4128
  editor.transformToDarkColor(vtable.table);
4100
4129
  editor.focus();
4101
- var cellToSelect = calculateCellToSelect(operation, vtable.row, vtable.col);
4102
- editor.select(vtable.getCell(cellToSelect.newRow, cellToSelect.newCol).td, 0 /* Begin */);
4130
+ if (isUndefined(vtable.row) || isUndefined(vtable.col)) {
4131
+ return;
4132
+ }
4133
+ var _a = calculateCellToSelect(operation, vtable.row, vtable.col), newCol = _a.newCol, newRow = _a.newRow;
4134
+ var newTd = vtable.getCell(newRow, newCol).td;
4135
+ if (newTd) {
4136
+ editor.select(newTd, 0 /* Begin */);
4137
+ }
4103
4138
  }, 'editTable');
4104
4139
  }
4105
4140
  }
4106
4141
  exports.default = editTable;
4142
+ function isUndefined(n) {
4143
+ return n == undefined;
4144
+ }
4107
4145
  function calculateCellToSelect(operation, currentRow, currentCol) {
4108
4146
  var newRow = currentRow;
4109
4147
  var newCol = currentCol;
@@ -4129,9 +4167,10 @@ function calculateCellToSelect(operation, currentRow, currentCol) {
4129
4167
  };
4130
4168
  }
4131
4169
  function saveTableSelection(editor, vtable) {
4170
+ var _a;
4132
4171
  var selection = editor.getSelectionRangeEx();
4133
4172
  if (selection && selection.type === 1 /* TableSelection */) {
4134
- vtable.selection = selection.coordinates;
4173
+ vtable.selection = (_a = selection.coordinates) !== null && _a !== void 0 ? _a : null;
4135
4174
  }
4136
4175
  }
4137
4176
 
@@ -4160,12 +4199,17 @@ function formatTable(editor, format, table) {
4160
4199
  table = table || editor.getElementAtCursor('TABLE');
4161
4200
  if (table) {
4162
4201
  (0, formatUndoSnapshot_1.default)(editor, function (start, end) {
4202
+ if (!table) {
4203
+ return;
4204
+ }
4163
4205
  var vtable = new roosterjs_editor_dom_1.VTable(table);
4164
4206
  vtable.applyFormat(format);
4165
4207
  vtable.writeBack();
4166
4208
  editor.transformToDarkColor(vtable.table);
4167
4209
  editor.focus();
4168
- editor.select(start, end);
4210
+ if (start && end) {
4211
+ editor.select(start, end);
4212
+ }
4169
4213
  }, 'formatTable');
4170
4214
  }
4171
4215
  }
@@ -4218,7 +4262,7 @@ function insertTable(editor, columns, rows, format) {
4218
4262
  (0, setBackgroundColor_1.default)(editor, 'transparent');
4219
4263
  }
4220
4264
  var vtable = new roosterjs_editor_dom_1.VTable(table);
4221
- vtable.applyFormat(format);
4265
+ vtable.applyFormat(format || {});
4222
4266
  vtable.writeBack();
4223
4267
  editor.insertNode(table);
4224
4268
  editor.runAsync(function (editor) {
@@ -4294,6 +4338,9 @@ function applyInlineStyle(editor, callback, apiName) {
4294
4338
  var lastNode;
4295
4339
  selection.ranges.forEach(function (range) {
4296
4340
  var contentTraverser = editor.getSelectionTraverser(range);
4341
+ if (!contentTraverser) {
4342
+ return;
4343
+ }
4297
4344
  var inlineElement = contentTraverser && contentTraverser.currentInlineElement;
4298
4345
  while (inlineElement) {
4299
4346
  var nextInlineElement = contentTraverser.getNextInlineElement();
@@ -4392,7 +4439,7 @@ function blockFormat(editor, callback, beforeRunCallback, apiName) {
4392
4439
  (0, commitListChains_1.default)(editor, chains_1);
4393
4440
  }
4394
4441
  }
4395
- if (selection.type == 0 /* Normal */) {
4442
+ if (selection.type == 0 /* Normal */ && start && end) {
4396
4443
  editor.select(start, end);
4397
4444
  }
4398
4445
  else {
@@ -4441,9 +4488,11 @@ function blockWrap(editor, wrapFunction, beforeRunCallback, apiName) {
4441
4488
  }
4442
4489
  }
4443
4490
  while (nodes[0] &&
4491
+ nodes[0].parentNode &&
4444
4492
  (0, roosterjs_editor_dom_1.isNodeInRegion)(region, nodes[0].parentNode) &&
4445
4493
  nodes.some(function (node) { return (0, roosterjs_editor_dom_1.getTagOfNode)(node) == 'LI'; })) {
4446
- nodes = [(0, roosterjs_editor_dom_1.splitBalancedNodeRange)(nodes)];
4494
+ var result = (0, roosterjs_editor_dom_1.splitBalancedNodeRange)(nodes);
4495
+ nodes = result ? [result] : [];
4447
4496
  }
4448
4497
  wrapFunction(nodes);
4449
4498
  }
@@ -4473,7 +4522,10 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
4473
4522
  */
4474
4523
  function collapseSelectedBlocks(editor, forEachCallback) {
4475
4524
  var traverser = editor.getSelectionTraverser();
4476
- var block = traverser && traverser.currentBlockElement;
4525
+ if (!traverser) {
4526
+ return;
4527
+ }
4528
+ var block = traverser.currentBlockElement;
4477
4529
  var blocks = [];
4478
4530
  while (block) {
4479
4531
  if (!isEmptyBlockUnderTR(block)) {
@@ -4521,7 +4573,9 @@ function commitListChains(editor, chains) {
4521
4573
  var end = range && roosterjs_editor_dom_1.Position.getEnd(range);
4522
4574
  var shouldReuseAllAncestorListElements_1 = editor.isFeatureEnabled("ReuseAllAncestorListElements" /* ReuseAllAncestorListElements */);
4523
4575
  chains.forEach(function (chain) { return chain.commit(shouldReuseAllAncestorListElements_1); });
4524
- editor.select(start, end);
4576
+ if (start && end) {
4577
+ editor.select(start, end);
4578
+ }
4525
4579
  }
4526
4580
  }
4527
4581
  exports.default = commitListChains;
@@ -4558,7 +4612,7 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
4558
4612
  */
4559
4613
  function execCommand(editor, command, apiName) {
4560
4614
  editor.focus();
4561
- var formatter = function () { return editor.getDocument().execCommand(command, false, null); };
4615
+ var formatter = function () { return editor.getDocument().execCommand(command, false, undefined); };
4562
4616
  var selection = editor.getSelectionRangeEx();
4563
4617
  if (selection && selection.areAllCollapsed) {
4564
4618
  editor.addUndoSnapshot();
@@ -4611,9 +4665,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
4611
4665
  * Default value is false.
4612
4666
  */
4613
4667
  function formatUndoSnapshot(editor, callback, apiName) {
4614
- editor.addUndoSnapshot(callback, "Format" /* Format */, undefined /* canUndoByBackspace */, apiName && {
4615
- formatApiName: apiName,
4616
- });
4668
+ editor.addUndoSnapshot(callback, "Format" /* Format */, undefined /* canUndoByBackspace */, apiName && apiName != ''
4669
+ ? {
4670
+ formatApiName: apiName,
4671
+ }
4672
+ : undefined);
4617
4673
  }
4618
4674
  exports.default = formatUndoSnapshot;
4619
4675
 
@@ -4641,6 +4697,9 @@ function normalizeBlockquote(node, quotesHandled) {
4641
4697
  if ((0, roosterjs_editor_dom_1.safeInstanceOf)(node, 'HTMLElement')) {
4642
4698
  var alignment = node.style.textAlign;
4643
4699
  var quote = (0, roosterjs_editor_dom_1.findClosestElementAncestor)(node, undefined /* root */, 'blockquote');
4700
+ if (!quote) {
4701
+ return;
4702
+ }
4644
4703
  var isNodeRTL = isRTL(node);
4645
4704
  if (quotesHandled) {
4646
4705
  if (quotesHandled.indexOf(quote) > -1) {
@@ -4651,17 +4710,17 @@ function normalizeBlockquote(node, quotesHandled) {
4651
4710
  while (quote) {
4652
4711
  if (alignment == 'center') {
4653
4712
  if (isNodeRTL) {
4654
- delete quote.style.marginInlineEnd;
4713
+ quote.style.removeProperty('marginInlineEnd');
4655
4714
  quote.style.marginInlineStart = 'auto';
4656
4715
  }
4657
4716
  else {
4658
- delete quote.style.marginInlineStart;
4717
+ quote.style.removeProperty('marginInlineStart');
4659
4718
  quote.style.marginInlineEnd = 'auto';
4660
4719
  }
4661
4720
  }
4662
4721
  else {
4663
- delete quote.style.marginInlineStart;
4664
- delete quote.style.marginInlineEnd;
4722
+ quote.style.removeProperty('marginInlineEnd');
4723
+ quote.style.removeProperty('marginInlineStart');
4665
4724
  }
4666
4725
  quote = (0, roosterjs_editor_dom_1.findClosestElementAncestor)(quote.parentElement, undefined /* root */, 'blockquote');
4667
4726
  }
@@ -4708,14 +4767,19 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
4708
4767
  * @param apiNameOverride (Optional) Set a new api name, if empty the api name will be 'toggleListType'.
4709
4768
  */
4710
4769
  function toggleListType(editor, listType, startNumber, includeSiblingLists, orderedStyle, unorderedStyle, apiNameOverride) {
4770
+ if (startNumber === void 0) { startNumber = 0; }
4711
4771
  if (includeSiblingLists === void 0) { includeSiblingLists = true; }
4712
4772
  (0, blockFormat_1.default)(editor, function (region, start, end, chains) {
4713
- var _a;
4773
+ var _a, _b;
4714
4774
  var chain = startNumber > 0 && chains.filter(function (chain) { return chain.canAppendAtCursor(startNumber); })[0];
4715
- var vList = chain && start.equalTo(end)
4716
- ? chain.createVListAtBlock((_a = (0, roosterjs_editor_dom_1.getBlockElementAtNode)(region.rootNode, start.node)) === null || _a === void 0 ? void 0 : _a.collapseToSingleElement(), startNumber)
4775
+ var block = (_b = (0, roosterjs_editor_dom_1.getBlockElementAtNode)(region.rootNode, (_a = start === null || start === void 0 ? void 0 : start.node) !== null && _a !== void 0 ? _a : null)) === null || _b === void 0 ? void 0 : _b.collapseToSingleElement();
4776
+ if (!block) {
4777
+ return;
4778
+ }
4779
+ var vList = chain && end && (start === null || start === void 0 ? void 0 : start.equalTo(end))
4780
+ ? chain.createVListAtBlock(block, startNumber)
4717
4781
  : (0, roosterjs_editor_dom_1.createVListFromRegion)(region, startNumber === 1 ? false : includeSiblingLists);
4718
- if (vList) {
4782
+ if (vList && start && end) {
4719
4783
  vList.changeListType(start, end, listType);
4720
4784
  if (editor.isFeatureEnabled("AutoFormatList" /* AutoFormatList */)) {
4721
4785
  vList.setListStyleType(orderedStyle, unorderedStyle);
@@ -4921,6 +4985,7 @@ var getStyleBasedFormatState_1 = __webpack_require__(/*! ./getStyleBasedFormatSt
4921
4985
  var hasFocus_1 = __webpack_require__(/*! ./hasFocus */ "./packages/roosterjs-editor-core/lib/coreApi/hasFocus.ts");
4922
4986
  var insertNode_1 = __webpack_require__(/*! ./insertNode */ "./packages/roosterjs-editor-core/lib/coreApi/insertNode.ts");
4923
4987
  var restoreUndoSnapshot_1 = __webpack_require__(/*! ./restoreUndoSnapshot */ "./packages/roosterjs-editor-core/lib/coreApi/restoreUndoSnapshot.ts");
4988
+ var select_1 = __webpack_require__(/*! ./select */ "./packages/roosterjs-editor-core/lib/coreApi/select.ts");
4924
4989
  var selectImage_1 = __webpack_require__(/*! ./selectImage */ "./packages/roosterjs-editor-core/lib/coreApi/selectImage.ts");
4925
4990
  var selectRange_1 = __webpack_require__(/*! ./selectRange */ "./packages/roosterjs-editor-core/lib/coreApi/selectRange.ts");
4926
4991
  var selectTable_1 = __webpack_require__(/*! ./selectTable */ "./packages/roosterjs-editor-core/lib/coreApi/selectTable.ts");
@@ -4945,6 +5010,7 @@ exports.coreApiMap = {
4945
5010
  hasFocus: hasFocus_1.hasFocus,
4946
5011
  insertNode: insertNode_1.insertNode,
4947
5012
  restoreUndoSnapshot: restoreUndoSnapshot_1.restoreUndoSnapshot,
5013
+ select: select_1.select,
4948
5014
  selectRange: selectRange_1.selectRange,
4949
5015
  setContent: setContent_1.setContent,
4950
5016
  switchShadowEdit: switchShadowEdit_1.switchShadowEdit,
@@ -4984,8 +5050,9 @@ var TAB_SPACES = 6;
4984
5050
  * @param applyCurrentStyle True if apply format of current selection to the pasted content,
4985
5051
  * false to keep original format
4986
5052
  */
4987
- var createPasteFragment = function (core, clipboardData, position, pasteAsText, applyCurrentStyle) {
5053
+ var createPasteFragment = function (core, clipboardData, position, pasteAsText, applyCurrentStyle, pasteAsImage) {
4988
5054
  var _a, _b;
5055
+ if (pasteAsImage === void 0) { pasteAsImage = false; }
4989
5056
  if (!clipboardData) {
4990
5057
  return null;
4991
5058
  }
@@ -5044,7 +5111,7 @@ var createPasteFragment = function (core, clipboardData, position, pasteAsText,
5044
5111
  }
5045
5112
  }
5046
5113
  // Step 3: Fill the BeforePasteEvent object, especially the fragment for paste
5047
- if (!pasteAsText && !text && imageDataUri) {
5114
+ if ((pasteAsImage && imageDataUri) || (!pasteAsText && !text && imageDataUri)) {
5048
5115
  // Paste image
5049
5116
  var img = document.createElement('img');
5050
5117
  img.style.maxWidth = '100%';
@@ -5986,6 +6053,136 @@ var restoreUndoSnapshot = function (core, step) {
5986
6053
  exports.restoreUndoSnapshot = restoreUndoSnapshot;
5987
6054
 
5988
6055
 
6056
+ /***/ }),
6057
+
6058
+ /***/ "./packages/roosterjs-editor-core/lib/coreApi/select.ts":
6059
+ /*!**************************************************************!*\
6060
+ !*** ./packages/roosterjs-editor-core/lib/coreApi/select.ts ***!
6061
+ \**************************************************************/
6062
+ /*! no static exports found */
6063
+ /***/ (function(module, exports, __webpack_require__) {
6064
+
6065
+ "use strict";
6066
+
6067
+ Object.defineProperty(exports, "__esModule", { value: true });
6068
+ exports.select = void 0;
6069
+ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
6070
+ /**
6071
+ * @internal
6072
+ * Select content according to the given information.
6073
+ * There are a bunch of allowed combination of parameters. See IEditor.select for more details
6074
+ * @param core The editor core object
6075
+ * @param arg1 A DOM Range, or SelectionRangeEx, or NodePosition, or Node, or Selection Path
6076
+ * @param arg2 (optional) A NodePosition, or an offset number, or a PositionType, or a TableSelection
6077
+ * @param arg3 (optional) A Node
6078
+ * @param arg4 (optional) An offset number, or a PositionType
6079
+ */
6080
+ var select = function (core, arg1, arg2, arg3, arg4) {
6081
+ var rangeEx = null;
6082
+ if (isSelectionRangeEx(arg1)) {
6083
+ rangeEx = arg1;
6084
+ }
6085
+ else if ((0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'HTMLTableElement') && isTableSelection(arg2)) {
6086
+ rangeEx = {
6087
+ type: 1 /* TableSelection */,
6088
+ ranges: [],
6089
+ areAllCollapsed: false,
6090
+ table: arg1,
6091
+ coordinates: arg2,
6092
+ };
6093
+ }
6094
+ else if ((0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'HTMLImageElement') && typeof arg2 == 'undefined') {
6095
+ rangeEx = {
6096
+ type: 2 /* ImageSelection */,
6097
+ ranges: [],
6098
+ areAllCollapsed: false,
6099
+ image: arg1,
6100
+ };
6101
+ }
6102
+ else {
6103
+ var range = !arg1
6104
+ ? null
6105
+ : (0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'Range')
6106
+ ? arg1
6107
+ : isSelectionPath(arg1)
6108
+ ? (0, roosterjs_editor_dom_1.createRange)(core.contentDiv, arg1.start, arg1.end)
6109
+ : isNodePosition(arg1) || (0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'Node')
6110
+ ? (0, roosterjs_editor_dom_1.createRange)(arg1, arg2, arg3, arg4)
6111
+ : null;
6112
+ rangeEx = range
6113
+ ? {
6114
+ type: 0 /* Normal */,
6115
+ ranges: [range],
6116
+ areAllCollapsed: range.collapsed,
6117
+ }
6118
+ : null;
6119
+ }
6120
+ if (rangeEx) {
6121
+ switch (rangeEx.type) {
6122
+ case 1 /* TableSelection */:
6123
+ if ((0, roosterjs_editor_dom_1.contains)(core.contentDiv, rangeEx.table)) {
6124
+ core.domEvent.imageSelectionRange = core.api.selectImage(core, null);
6125
+ core.domEvent.tableSelectionRange = core.api.selectTable(core, rangeEx.table, rangeEx.coordinates);
6126
+ rangeEx = core.domEvent.tableSelectionRange;
6127
+ }
6128
+ break;
6129
+ case 2 /* ImageSelection */:
6130
+ if ((0, roosterjs_editor_dom_1.contains)(core.contentDiv, rangeEx.image)) {
6131
+ core.domEvent.tableSelectionRange = core.api.selectTable(core, null);
6132
+ core.domEvent.imageSelectionRange = core.api.selectImage(core, rangeEx.image);
6133
+ rangeEx = core.domEvent.imageSelectionRange;
6134
+ }
6135
+ break;
6136
+ case 0 /* Normal */:
6137
+ core.domEvent.tableSelectionRange = core.api.selectTable(core, null);
6138
+ core.domEvent.imageSelectionRange = core.api.selectImage(core, null);
6139
+ if ((0, roosterjs_editor_dom_1.contains)(core.contentDiv, rangeEx.ranges[0])) {
6140
+ core.api.selectRange(core, rangeEx.ranges[0]);
6141
+ }
6142
+ else {
6143
+ rangeEx = null;
6144
+ }
6145
+ break;
6146
+ }
6147
+ core.api.triggerEvent(core, {
6148
+ eventType: 22 /* SelectionChanged */,
6149
+ selectionRangeEx: rangeEx,
6150
+ }, true /** broadcast **/);
6151
+ }
6152
+ else {
6153
+ core.domEvent.tableSelectionRange = core.api.selectTable(core, null);
6154
+ core.domEvent.imageSelectionRange = core.api.selectImage(core, null);
6155
+ }
6156
+ return !!rangeEx;
6157
+ };
6158
+ exports.select = select;
6159
+ function isSelectionRangeEx(obj) {
6160
+ var rangeEx = obj;
6161
+ return (rangeEx &&
6162
+ typeof rangeEx == 'object' &&
6163
+ typeof rangeEx.type == 'number' &&
6164
+ Array.isArray(rangeEx.ranges));
6165
+ }
6166
+ function isTableSelection(obj) {
6167
+ var selection = obj;
6168
+ return (selection &&
6169
+ typeof selection == 'object' &&
6170
+ typeof selection.firstCell == 'object' &&
6171
+ typeof selection.lastCell == 'object');
6172
+ }
6173
+ function isSelectionPath(obj) {
6174
+ var path = obj;
6175
+ return path && typeof path == 'object' && Array.isArray(path.start) && Array.isArray(path.end);
6176
+ }
6177
+ function isNodePosition(obj) {
6178
+ var pos = obj;
6179
+ return (pos &&
6180
+ typeof pos == 'object' &&
6181
+ typeof pos.node == 'object' &&
6182
+ typeof pos.offset == 'number');
6183
+ }
6184
+
6185
+
5989
6186
  /***/ }),
5990
6187
 
5991
6188
  /***/ "./packages/roosterjs-editor-core/lib/coreApi/selectImage.ts":
@@ -6220,7 +6417,7 @@ function buildCss(table, coordinates, contentDivSelector) {
6220
6417
  ranges.push(rowRange);
6221
6418
  }
6222
6419
  });
6223
- var css = selectors.join(',') + " {background-color: rgba(198,198,198,0.7) !important; caret-color: transparent}";
6420
+ var css = selectors.join(',') + " {background-color: rgb(198,198,198) !important; caret-color: transparent}";
6224
6421
  return { css: css, ranges: ranges };
6225
6422
  }
6226
6423
  function select(core, table, coordinates) {
@@ -7745,6 +7942,17 @@ exports.default = ImageSelection;
7745
7942
 
7746
7943
  "use strict";
7747
7944
 
7945
+ var __assign = (this && this.__assign) || function () {
7946
+ __assign = Object.assign || function(t) {
7947
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
7948
+ s = arguments[i];
7949
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7950
+ t[p] = s[p];
7951
+ }
7952
+ return t;
7953
+ };
7954
+ return __assign.apply(this, arguments);
7955
+ };
7748
7956
  var _a, _b;
7749
7957
  Object.defineProperty(exports, "__esModule", { value: true });
7750
7958
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
@@ -7789,12 +7997,11 @@ var LifecyclePlugin = /** @class */ (function () {
7789
7997
  */
7790
7998
  function LifecyclePlugin(options, contentDiv) {
7791
7999
  var _this = this;
7792
- var _a, _b, _c;
8000
+ var _a, _b;
7793
8001
  this.editor = null;
7794
8002
  this.initializer = null;
7795
8003
  this.disposer = null;
7796
8004
  this.initialContent = options.initialContent || contentDiv.innerHTML || '';
7797
- this.contentDivFormat = (0, roosterjs_editor_dom_1.getComputedStyles)(contentDiv);
7798
8005
  // Make the container editable and set its selection styles
7799
8006
  if (contentDiv.getAttribute(CONTENT_EDITABLE_ATTRIBUTE_NAME) === null) {
7800
8007
  this.initializer = function () {
@@ -7818,12 +8025,30 @@ var LifecyclePlugin = /** @class */ (function () {
7818
8025
  (0, roosterjs_editor_dom_1.setColor)(contentDiv, textColors, false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
7819
8026
  (0, roosterjs_editor_dom_1.setColor)(contentDiv, backgroundColors, true /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
7820
8027
  };
8028
+ var getDarkColor = (_a = options.getDarkColor) !== null && _a !== void 0 ? _a : (function (color) { return color; });
8029
+ var defaultFormat = options.defaultFormat ? __assign({}, options.defaultFormat) : null;
8030
+ if (defaultFormat) {
8031
+ if (defaultFormat.textColor && !defaultFormat.textColors) {
8032
+ defaultFormat.textColors = {
8033
+ lightModeColor: defaultFormat.textColor,
8034
+ darkModeColor: getDarkColor(defaultFormat.textColor),
8035
+ };
8036
+ delete defaultFormat.textColor;
8037
+ }
8038
+ if (defaultFormat.backgroundColor && !defaultFormat.backgroundColors) {
8039
+ defaultFormat.backgroundColors = {
8040
+ lightModeColor: defaultFormat.backgroundColor,
8041
+ darkModeColor: getDarkColor(defaultFormat.backgroundColor),
8042
+ };
8043
+ delete defaultFormat.backgroundColor;
8044
+ }
8045
+ }
7821
8046
  this.state = {
7822
8047
  customData: {},
7823
- defaultFormat: (_a = options.defaultFormat) !== null && _a !== void 0 ? _a : null,
8048
+ defaultFormat: defaultFormat,
7824
8049
  isDarkMode: !!options.inDarkMode,
7825
- getDarkColor: (_b = options.getDarkColor) !== null && _b !== void 0 ? _b : (function (color) { return color; }),
7826
- onExternalContentTransform: (_c = options.onExternalContentTransform) !== null && _c !== void 0 ? _c : null,
8050
+ getDarkColor: getDarkColor,
8051
+ onExternalContentTransform: (_b = options.onExternalContentTransform) !== null && _b !== void 0 ? _b : null,
7827
8052
  experimentalFeatures: options.experimentalFeatures || [],
7828
8053
  shadowEditFragment: null,
7829
8054
  shadowEditEntities: null,
@@ -7845,8 +8070,6 @@ var LifecyclePlugin = /** @class */ (function () {
7845
8070
  LifecyclePlugin.prototype.initialize = function (editor) {
7846
8071
  var _a;
7847
8072
  this.editor = editor;
7848
- // Calculate default format
7849
- this.recalculateDefaultFormat();
7850
8073
  // Ensure initial content and its format
7851
8074
  this.editor.setContent(this.initialContent, false /*triggerContentChangedEvent*/);
7852
8075
  // Set content DIV to be editable
@@ -7894,7 +8117,6 @@ var LifecyclePlugin = /** @class */ (function () {
7894
8117
  (event.source == "SwitchToDarkMode" /* SwitchToDarkMode */ ||
7895
8118
  event.source == "SwitchToLightMode" /* SwitchToLightMode */)) {
7896
8119
  this.state.isDarkMode = event.source == "SwitchToDarkMode" /* SwitchToDarkMode */;
7897
- this.recalculateDefaultFormat();
7898
8120
  this.adjustColor();
7899
8121
  }
7900
8122
  };
@@ -7909,45 +8131,6 @@ var LifecyclePlugin = /** @class */ (function () {
7909
8131
  catch (_b) { }
7910
8132
  });
7911
8133
  };
7912
- LifecyclePlugin.prototype.recalculateDefaultFormat = function () {
7913
- var _a = this.state, baseFormat = _a.defaultFormat, isDarkMode = _a.isDarkMode;
7914
- if (isDarkMode && baseFormat) {
7915
- if (!baseFormat.backgroundColors) {
7916
- baseFormat.backgroundColors = DARK_MODE_DEFAULT_FORMAT.backgroundColors;
7917
- }
7918
- if (!baseFormat.textColors) {
7919
- baseFormat.textColors = DARK_MODE_DEFAULT_FORMAT.textColors;
7920
- }
7921
- }
7922
- if (baseFormat && (0, roosterjs_editor_dom_1.getObjectKeys)(baseFormat).length === 0) {
7923
- return;
7924
- }
7925
- var _b = baseFormat || {}, fontFamily = _b.fontFamily, fontSize = _b.fontSize, textColor = _b.textColor, textColors = _b.textColors, backgroundColor = _b.backgroundColor, backgroundColors = _b.backgroundColors, bold = _b.bold, italic = _b.italic, underline = _b.underline;
7926
- var defaultFormat = this.contentDivFormat;
7927
- this.state.defaultFormat = {
7928
- fontFamily: fontFamily || defaultFormat[0],
7929
- fontSize: fontSize || defaultFormat[1],
7930
- get textColor() {
7931
- return textColors
7932
- ? isDarkMode
7933
- ? textColors.darkModeColor
7934
- : textColors.lightModeColor
7935
- : textColor || defaultFormat[2];
7936
- },
7937
- textColors: textColors,
7938
- get backgroundColor() {
7939
- return backgroundColors
7940
- ? isDarkMode
7941
- ? backgroundColors.darkModeColor
7942
- : backgroundColors.lightModeColor
7943
- : backgroundColor || '';
7944
- },
7945
- backgroundColors: backgroundColors,
7946
- bold: bold,
7947
- italic: italic,
7948
- underline: underline,
7949
- };
7950
- };
7951
8134
  return LifecyclePlugin;
7952
8135
  }());
7953
8136
  exports.default = LifecyclePlugin;
@@ -8566,11 +8749,7 @@ var UndoPlugin = /** @class */ (function () {
8566
8749
  this.addUndoSnapshot();
8567
8750
  break;
8568
8751
  case 7 /* ContentChanged */:
8569
- if (!(this.state.isRestoring ||
8570
- event.source == "SwitchToDarkMode" /* SwitchToDarkMode */ ||
8571
- event.source == "SwitchToLightMode" /* SwitchToLightMode */)) {
8572
- this.clearRedoForInput();
8573
- }
8752
+ this.onContentChanged(event);
8574
8753
  break;
8575
8754
  }
8576
8755
  };
@@ -8634,6 +8813,25 @@ var UndoPlugin = /** @class */ (function () {
8634
8813
  }
8635
8814
  this.lastKeyPress = evt.which;
8636
8815
  };
8816
+ UndoPlugin.prototype.onContentChanged = function (event) {
8817
+ if (event.source == "Keyboard" /* Keyboard */) {
8818
+ if (Number.isInteger(event.data)) {
8819
+ // For keyboard event (triggered from Content Model), we can get its keycode from event.data
8820
+ // And when user is keep pressing the same key, mark editor with "hasNewContent" so that next time user
8821
+ // do some other action or press a different key, we will add undo snapshot
8822
+ if (event.data != this.lastKeyPress) {
8823
+ this.addUndoSnapshot();
8824
+ }
8825
+ this.lastKeyPress = event.data;
8826
+ this.state.hasNewContent = true;
8827
+ }
8828
+ }
8829
+ else if (!(this.state.isRestoring ||
8830
+ event.source == "SwitchToDarkMode" /* SwitchToDarkMode */ ||
8831
+ event.source == "SwitchToLightMode" /* SwitchToLightMode */)) {
8832
+ this.clearRedoForInput();
8833
+ }
8834
+ };
8637
8835
  UndoPlugin.prototype.clearRedoForInput = function () {
8638
8836
  this.state.snapshotsService.clearRedo();
8639
8837
  this.lastKeyPress = 0;
@@ -8807,7 +9005,6 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
8807
9005
  var DELIMITER_SELECTOR = '.' + "entityDelimiterAfter" /* DELIMITER_AFTER */ + ',.' + "entityDelimiterBefore" /* DELIMITER_BEFORE */;
8808
9006
  var ZERO_WIDTH_SPACE = '\u200B';
8809
9007
  var INLINE_ENTITY_SELECTOR = 'span' + (0, roosterjs_editor_dom_1.getEntitySelector)();
8810
- var NBSP = '\u00A0';
8811
9008
  function inlineEntityOnPluginEvent(event, editor) {
8812
9009
  switch (event.eventType) {
8813
9010
  case 7 /* ContentChanged */:
@@ -8819,7 +9016,14 @@ function inlineEntityOnPluginEvent(event, editor) {
8819
9016
  normalizeDelimitersInEditor(editor);
8820
9017
  break;
8821
9018
  case 10 /* BeforePaste */:
8822
- addDelimitersIfNeeded(event.fragment.querySelectorAll(INLINE_ENTITY_SELECTOR));
9019
+ var fragment = event.fragment, sanitizingOption = event.sanitizingOption;
9020
+ addDelimitersIfNeeded(fragment.querySelectorAll(INLINE_ENTITY_SELECTOR));
9021
+ if (sanitizingOption.additionalAllowedCssClasses) {
9022
+ (0, roosterjs_editor_dom_1.arrayPush)(sanitizingOption.additionalAllowedCssClasses, [
9023
+ "entityDelimiterAfter" /* DELIMITER_AFTER */,
9024
+ "entityDelimiterBefore" /* DELIMITER_BEFORE */,
9025
+ ]);
9026
+ }
8823
9027
  break;
8824
9028
  case 8 /* ExtractContentWithDom */:
8825
9029
  case 9 /* BeforeCutCopy */:
@@ -8865,12 +9069,12 @@ function normalizeDelimitersInEditor(editor) {
8865
9069
  exports.normalizeDelimitersInEditor = normalizeDelimitersInEditor;
8866
9070
  function addDelimitersIfNeeded(nodes) {
8867
9071
  nodes.forEach(function (node) {
8868
- if (tryGetEntityFromNode(node)) {
9072
+ if (isEntityElement(node)) {
8869
9073
  (0, roosterjs_editor_dom_1.addDelimiters)(node);
8870
9074
  }
8871
9075
  });
8872
9076
  }
8873
- function tryGetEntityFromNode(node) {
9077
+ function isEntityElement(node) {
8874
9078
  return !!(node &&
8875
9079
  (0, roosterjs_editor_dom_1.safeInstanceOf)(node, 'HTMLElement') &&
8876
9080
  isReadOnly((0, roosterjs_editor_dom_1.getEntityFromElement)(node)));
@@ -8899,13 +9103,14 @@ function removeInvalidDelimiters(nodes) {
8899
9103
  }
8900
9104
  });
8901
9105
  }
8902
- function removeDelimiterAttr(node) {
9106
+ function removeDelimiterAttr(node, checkEntity) {
9107
+ if (checkEntity === void 0) { checkEntity = true; }
8903
9108
  if (!node) {
8904
9109
  return;
8905
9110
  }
8906
9111
  var isAfter = node.classList.contains("entityDelimiterAfter" /* DELIMITER_AFTER */);
8907
9112
  var entitySibling = isAfter ? node.previousElementSibling : node.nextElementSibling;
8908
- if (entitySibling && tryGetEntityFromNode(entitySibling)) {
9113
+ if (checkEntity && entitySibling && isEntityElement(entitySibling)) {
8909
9114
  return;
8910
9115
  }
8911
9116
  node.classList.remove("entityDelimiterAfter" /* DELIMITER_AFTER */, "entityDelimiterBefore" /* DELIMITER_BEFORE */);
@@ -8919,31 +9124,34 @@ function removeDelimiterAttr(node) {
8919
9124
  });
8920
9125
  }
8921
9126
  function handleCollapsedEnter(editor, delimiter) {
9127
+ var _a;
8922
9128
  var isAfter = delimiter.classList.contains("entityDelimiterAfter" /* DELIMITER_AFTER */);
8923
- var sibling = isAfter ? delimiter.nextSibling : delimiter.previousSibling;
8924
- var positionToUse;
8925
- var element;
8926
- if (sibling) {
8927
- positionToUse = new roosterjs_editor_dom_1.Position(sibling, isAfter ? 0 /* Begin */ : -1 /* End */);
8928
- }
8929
- else {
8930
- element = delimiter.insertAdjacentElement(isAfter ? 'afterend' : 'beforebegin', (0, roosterjs_editor_dom_1.createElement)({
8931
- tag: 'span',
8932
- children: [NBSP],
8933
- }, editor.getDocument()));
8934
- if (!element) {
9129
+ var entity = !isAfter ? delimiter.nextSibling : delimiter.previousSibling;
9130
+ var block = (_a = editor.getBlockElementAtNode(delimiter)) === null || _a === void 0 ? void 0 : _a.getStartNode();
9131
+ editor.runAsync(function () {
9132
+ if (!block) {
8935
9133
  return;
8936
9134
  }
8937
- positionToUse = new roosterjs_editor_dom_1.Position(element, 0 /* Begin */);
8938
- }
8939
- if (positionToUse) {
8940
- editor.select(positionToUse);
8941
- editor.runAsync(function (aEditor) {
8942
- var elAfter = aEditor.getElementAtCursor();
8943
- removeDelimiterAttr(elAfter);
8944
- removeNode(element);
8945
- });
8946
- }
9135
+ var blockToCheck = isAfter ? block.nextSibling : block.previousSibling;
9136
+ if (blockToCheck && (0, roosterjs_editor_dom_1.safeInstanceOf)(blockToCheck, 'HTMLElement')) {
9137
+ var delimiters = blockToCheck.querySelectorAll(DELIMITER_SELECTOR);
9138
+ // Check if the last or first delimiter still contain the delimiter class and remove it.
9139
+ var delimiterToCheck = delimiters.item(isAfter ? 0 : delimiters.length - 1);
9140
+ removeDelimiterAttr(delimiterToCheck);
9141
+ }
9142
+ if (isEntityElement(entity)) {
9143
+ var nextElementSibling = entity.nextElementSibling, previousElementSibling = entity.previousElementSibling;
9144
+ [nextElementSibling, previousElementSibling].forEach(function (el) {
9145
+ // Check if after Enter the ZWS got removed but we still have a element with the class
9146
+ // Remove the attributes of the element if it is invalid now.
9147
+ if (el && (0, roosterjs_editor_dom_1.matchesSelector)(el, DELIMITER_SELECTOR) && !(0, roosterjs_editor_dom_1.getDelimiterFromElement)(el)) {
9148
+ removeDelimiterAttr(el, false /* checkEntity */);
9149
+ }
9150
+ });
9151
+ // Add delimiters to the entity if needed because on Enter we can sometimes lose the ZWS of the element.
9152
+ (0, roosterjs_editor_dom_1.addDelimiters)(entity);
9153
+ }
9154
+ });
8947
9155
  }
8948
9156
  var getPosition = function (container) {
8949
9157
  if (container && (0, roosterjs_editor_dom_1.getDelimiterFromElement)(container)) {
@@ -9197,6 +9405,54 @@ exports.default = DarkColorHandlerImpl;
9197
9405
 
9198
9406
  "use strict";
9199
9407
 
9408
+ var __extends = (this && this.__extends) || (function () {
9409
+ var extendStatics = function (d, b) {
9410
+ extendStatics = Object.setPrototypeOf ||
9411
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
9412
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
9413
+ return extendStatics(d, b);
9414
+ };
9415
+ return function (d, b) {
9416
+ if (typeof b !== "function" && b !== null)
9417
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
9418
+ extendStatics(d, b);
9419
+ function __() { this.constructor = d; }
9420
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
9421
+ };
9422
+ })();
9423
+ Object.defineProperty(exports, "__esModule", { value: true });
9424
+ var createEditorCore_1 = __webpack_require__(/*! ./createEditorCore */ "./packages/roosterjs-editor-core/lib/editor/createEditorCore.ts");
9425
+ var EditorBase_1 = __webpack_require__(/*! ./EditorBase */ "./packages/roosterjs-editor-core/lib/editor/EditorBase.ts");
9426
+ /**
9427
+ * RoosterJs core editor class
9428
+ */
9429
+ var Editor = /** @class */ (function (_super) {
9430
+ __extends(Editor, _super);
9431
+ /**
9432
+ * Creates an instance of EditorBase
9433
+ * @param contentDiv The DIV HTML element which will be the container element of editor
9434
+ * @param options An optional options object to customize the editor
9435
+ */
9436
+ function Editor(contentDiv, options) {
9437
+ if (options === void 0) { options = {}; }
9438
+ return _super.call(this, contentDiv, options, createEditorCore_1.createEditorCore) || this;
9439
+ }
9440
+ return Editor;
9441
+ }(EditorBase_1.EditorBase));
9442
+ exports.default = Editor;
9443
+
9444
+
9445
+ /***/ }),
9446
+
9447
+ /***/ "./packages/roosterjs-editor-core/lib/editor/EditorBase.ts":
9448
+ /*!*****************************************************************!*\
9449
+ !*** ./packages/roosterjs-editor-core/lib/editor/EditorBase.ts ***!
9450
+ \*****************************************************************/
9451
+ /*! no static exports found */
9452
+ /***/ (function(module, exports, __webpack_require__) {
9453
+
9454
+ "use strict";
9455
+
9200
9456
  var __assign = (this && this.__assign) || function () {
9201
9457
  __assign = Object.assign || function(t) {
9202
9458
  for (var s, i = 1, n = arguments.length; i < n; i++) {
@@ -9209,53 +9465,28 @@ var __assign = (this && this.__assign) || function () {
9209
9465
  return __assign.apply(this, arguments);
9210
9466
  };
9211
9467
  Object.defineProperty(exports, "__esModule", { value: true });
9212
- var createCorePlugins_1 = __webpack_require__(/*! ../corePlugins/createCorePlugins */ "./packages/roosterjs-editor-core/lib/corePlugins/createCorePlugins.ts");
9213
- var DarkColorHandlerImpl_1 = __webpack_require__(/*! ./DarkColorHandlerImpl */ "./packages/roosterjs-editor-core/lib/editor/DarkColorHandlerImpl.ts");
9214
- var coreApiMap_1 = __webpack_require__(/*! ../coreApi/coreApiMap */ "./packages/roosterjs-editor-core/lib/coreApi/coreApiMap.ts");
9468
+ exports.EditorBase = void 0;
9469
+ var isFeatureEnabled_1 = __webpack_require__(/*! ./isFeatureEnabled */ "./packages/roosterjs-editor-core/lib/editor/isFeatureEnabled.ts");
9215
9470
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
9216
9471
  /**
9217
- * RoosterJs core editor class
9472
+ * Base class of editor
9218
9473
  */
9219
- var Editor = /** @class */ (function () {
9474
+ var EditorBase = /** @class */ (function () {
9220
9475
  //#region Lifecycle
9221
9476
  /**
9222
- * Creates an instance of Editor
9477
+ * Creates an instance of EditorBase
9223
9478
  * @param contentDiv The DIV HTML element which will be the container element of editor
9224
9479
  * @param options An optional options object to customize the editor
9225
9480
  */
9226
- function Editor(contentDiv, options) {
9481
+ function EditorBase(contentDiv, options, coreCreator) {
9227
9482
  var _this = this;
9228
- if (options === void 0) { options = {}; }
9229
- var _a;
9230
9483
  this.core = null;
9231
9484
  // 1. Make sure all parameters are valid
9232
9485
  if ((0, roosterjs_editor_dom_1.getTagOfNode)(contentDiv) != 'DIV') {
9233
9486
  throw new Error('contentDiv must be an HTML DIV element');
9234
9487
  }
9235
- // 2. Store options values to local variables
9236
- var corePlugins = (0, createCorePlugins_1.default)(contentDiv, options);
9237
- var plugins = [];
9238
- (0, roosterjs_editor_dom_1.getObjectKeys)(corePlugins).forEach(function (name) {
9239
- if (name == '_placeholder') {
9240
- if (options.plugins) {
9241
- (0, roosterjs_editor_dom_1.arrayPush)(plugins, options.plugins);
9242
- }
9243
- }
9244
- else {
9245
- plugins.push(corePlugins[name]);
9246
- }
9247
- });
9248
- var zoomScale = ((_a = options.zoomScale) !== null && _a !== void 0 ? _a : -1) > 0 ? options.zoomScale : 1;
9249
- this.core = __assign(__assign({ contentDiv: contentDiv, api: __assign(__assign({}, coreApiMap_1.coreApiMap), (options.coreApiOverride || {})), originalApi: coreApiMap_1.coreApiMap, plugins: plugins.filter(function (x) { return !!x; }) }, (0, createCorePlugins_1.getPluginState)(corePlugins)), { trustedHTMLHandler: options.trustedHTMLHandler || (function (html) { return html; }), zoomScale: zoomScale, sizeTransformer: options.sizeTransformer || (function (size) { return size / zoomScale; }), getVisibleViewport: options.getVisibleViewport ||
9250
- (function () {
9251
- var scrollContainer = _this.getScrollContainer();
9252
- return (0, roosterjs_editor_dom_1.getIntersectedRect)(scrollContainer == contentDiv
9253
- ? [scrollContainer]
9254
- : [scrollContainer, contentDiv]);
9255
- }), imageSelectionBorderColor: options.imageSelectionBorderColor });
9256
- if (this.isFeatureEnabled("VariableBasedDarkColor" /* VariableBasedDarkColor */)) {
9257
- this.core.darkColorHandler = new DarkColorHandlerImpl_1.default(contentDiv, this.core.lifecycle.getDarkColor);
9258
- }
9488
+ // 2. Create editor core
9489
+ this.core = coreCreator(contentDiv, options);
9259
9490
  // 3. Initialize plugins
9260
9491
  this.core.plugins.forEach(function (plugin) { return plugin.initialize(_this); });
9261
9492
  // 4. Ensure user will type in a container node, not the editor content DIV
@@ -9264,7 +9495,7 @@ var Editor = /** @class */ (function () {
9264
9495
  /**
9265
9496
  * Dispose this editor, dispose all plugins and custom data
9266
9497
  */
9267
- Editor.prototype.dispose = function () {
9498
+ EditorBase.prototype.dispose = function () {
9268
9499
  var _a;
9269
9500
  var core = this.getCore();
9270
9501
  for (var i = core.plugins.length - 1; i >= 0; i--) {
@@ -9277,7 +9508,7 @@ var Editor = /** @class */ (function () {
9277
9508
  * Get whether this editor is disposed
9278
9509
  * @returns True if editor is disposed, otherwise false
9279
9510
  */
9280
- Editor.prototype.isDisposed = function () {
9511
+ EditorBase.prototype.isDisposed = function () {
9281
9512
  return !this.core;
9282
9513
  };
9283
9514
  //#endregion
@@ -9292,7 +9523,7 @@ var Editor = /** @class */ (function () {
9292
9523
  * insertOnNewLine: false
9293
9524
  * @returns true if node is inserted. Otherwise false
9294
9525
  */
9295
- Editor.prototype.insertNode = function (node, option) {
9526
+ EditorBase.prototype.insertNode = function (node, option) {
9296
9527
  var core = this.getCore();
9297
9528
  return node ? core.api.insertNode(core, node, option !== null && option !== void 0 ? option : null) : false;
9298
9529
  };
@@ -9301,7 +9532,7 @@ var Editor = /** @class */ (function () {
9301
9532
  * @param node The node to delete
9302
9533
  * @returns true if node is deleted. Otherwise false
9303
9534
  */
9304
- Editor.prototype.deleteNode = function (node) {
9535
+ EditorBase.prototype.deleteNode = function (node) {
9305
9536
  // Only remove the node when it falls within editor
9306
9537
  if (node && this.contains(node) && node.parentNode) {
9307
9538
  node.parentNode.removeChild(node);
@@ -9316,7 +9547,7 @@ var Editor = /** @class */ (function () {
9316
9547
  * @param transformColorForDarkMode (optional) Whether to transform new node to dark mode. Default is false
9317
9548
  * @returns true if node is replaced. Otherwise false
9318
9549
  */
9319
- Editor.prototype.replaceNode = function (existingNode, toNode, transformColorForDarkMode) {
9550
+ EditorBase.prototype.replaceNode = function (existingNode, toNode, transformColorForDarkMode) {
9320
9551
  var core = this.getCore();
9321
9552
  // Only replace the node when it falls within editor
9322
9553
  if (this.contains(existingNode) && toNode) {
@@ -9330,16 +9561,16 @@ var Editor = /** @class */ (function () {
9330
9561
  * @param node The node to create InlineElement
9331
9562
  * @returns The BlockElement result
9332
9563
  */
9333
- Editor.prototype.getBlockElementAtNode = function (node) {
9564
+ EditorBase.prototype.getBlockElementAtNode = function (node) {
9334
9565
  return (0, roosterjs_editor_dom_1.getBlockElementAtNode)(this.getCore().contentDiv, node);
9335
9566
  };
9336
- Editor.prototype.contains = function (arg) {
9567
+ EditorBase.prototype.contains = function (arg) {
9337
9568
  if (!arg) {
9338
9569
  return false;
9339
9570
  }
9340
9571
  return (0, roosterjs_editor_dom_1.contains)(this.getCore().contentDiv, arg);
9341
9572
  };
9342
- Editor.prototype.queryElements = function (selector, scopeOrCallback, callback) {
9573
+ EditorBase.prototype.queryElements = function (selector, scopeOrCallback, callback) {
9343
9574
  if (scopeOrCallback === void 0) { scopeOrCallback = 0 /* Body */; }
9344
9575
  var core = this.getCore();
9345
9576
  var result = [];
@@ -9367,7 +9598,7 @@ var Editor = /** @class */ (function () {
9367
9598
  * @returns When canSplitParent is true, returns all node from start through end after splitting,
9368
9599
  * otherwise just return start and end
9369
9600
  */
9370
- Editor.prototype.collapseNodes = function (start, end, canSplitParent) {
9601
+ EditorBase.prototype.collapseNodes = function (start, end, canSplitParent) {
9371
9602
  return (0, roosterjs_editor_dom_1.collapseNodes)(this.getCore().contentDiv, start, end, canSplitParent);
9372
9603
  };
9373
9604
  //#endregion
@@ -9377,7 +9608,7 @@ var Editor = /** @class */ (function () {
9377
9608
  * @param trim Whether trim the content string before check. Default is false
9378
9609
  * @returns True if there's no visible content, otherwise false
9379
9610
  */
9380
- Editor.prototype.isEmpty = function (trim) {
9611
+ EditorBase.prototype.isEmpty = function (trim) {
9381
9612
  return (0, roosterjs_editor_dom_1.isNodeEmpty)(this.getCore().contentDiv, trim);
9382
9613
  };
9383
9614
  /**
@@ -9385,7 +9616,7 @@ var Editor = /** @class */ (function () {
9385
9616
  * @param mode specify what kind of HTML content to retrieve
9386
9617
  * @returns HTML string representing current editor content
9387
9618
  */
9388
- Editor.prototype.getContent = function (mode) {
9619
+ EditorBase.prototype.getContent = function (mode) {
9389
9620
  if (mode === void 0) { mode = 0 /* CleanHTML */; }
9390
9621
  var core = this.getCore();
9391
9622
  return core.api.getContent(core, mode);
@@ -9395,7 +9626,7 @@ var Editor = /** @class */ (function () {
9395
9626
  * @param content HTML content to set in
9396
9627
  * @param triggerContentChangedEvent True to trigger a ContentChanged event. Default value is true
9397
9628
  */
9398
- Editor.prototype.setContent = function (content, triggerContentChangedEvent) {
9629
+ EditorBase.prototype.setContent = function (content, triggerContentChangedEvent) {
9399
9630
  if (triggerContentChangedEvent === void 0) { triggerContentChangedEvent = true; }
9400
9631
  var core = this.getCore();
9401
9632
  core.api.setContent(core, content, triggerContentChangedEvent);
@@ -9409,7 +9640,7 @@ var Editor = /** @class */ (function () {
9409
9640
  * replaceSelection: true
9410
9641
  * insertOnNewLine: false
9411
9642
  */
9412
- Editor.prototype.insertContent = function (content, option) {
9643
+ EditorBase.prototype.insertContent = function (content, option) {
9413
9644
  var _a;
9414
9645
  if (content) {
9415
9646
  var doc = this.getDocument();
@@ -9429,7 +9660,7 @@ var Editor = /** @class */ (function () {
9429
9660
  /**
9430
9661
  * Delete selected content
9431
9662
  */
9432
- Editor.prototype.deleteSelectedContent = function () {
9663
+ EditorBase.prototype.deleteSelectedContent = function () {
9433
9664
  var range = this.getSelectionRange();
9434
9665
  if (range && !range.collapsed) {
9435
9666
  return (0, roosterjs_editor_dom_1.deleteSelectedContent)(this.getCore().contentDiv, range);
@@ -9443,10 +9674,11 @@ var Editor = /** @class */ (function () {
9443
9674
  * @param applyCurrentStyle True if apply format of current selection to the pasted content,
9444
9675
  * false to keep original format. Default value is false. When pasteAsText is true, this parameter is ignored
9445
9676
  */
9446
- Editor.prototype.paste = function (clipboardData, pasteAsText, applyCurrentFormat) {
9677
+ EditorBase.prototype.paste = function (clipboardData, pasteAsText, applyCurrentFormat, pasteAsImage) {
9447
9678
  var _this = this;
9448
9679
  if (pasteAsText === void 0) { pasteAsText = false; }
9449
9680
  if (applyCurrentFormat === void 0) { applyCurrentFormat = false; }
9681
+ if (pasteAsImage === void 0) { pasteAsImage = false; }
9450
9682
  var core = this.getCore();
9451
9683
  if (!clipboardData) {
9452
9684
  return;
@@ -9460,7 +9692,7 @@ var Editor = /** @class */ (function () {
9460
9692
  }
9461
9693
  var range = this.getSelectionRange();
9462
9694
  var pos = range && roosterjs_editor_dom_1.Position.getStart(range);
9463
- var fragment = core.api.createPasteFragment(core, clipboardData, pos, pasteAsText, applyCurrentFormat);
9695
+ var fragment = core.api.createPasteFragment(core, clipboardData, pos, pasteAsText, applyCurrentFormat, pasteAsImage);
9464
9696
  if (fragment) {
9465
9697
  this.addUndoSnapshot(function () {
9466
9698
  _this.insertNode(fragment);
@@ -9477,7 +9709,7 @@ var Editor = /** @class */ (function () {
9477
9709
  * Default value is true
9478
9710
  * @returns current selection range, or null if editor never got focus before
9479
9711
  */
9480
- Editor.prototype.getSelectionRange = function (tryGetFromCache) {
9712
+ EditorBase.prototype.getSelectionRange = function (tryGetFromCache) {
9481
9713
  if (tryGetFromCache === void 0) { tryGetFromCache = true; }
9482
9714
  var core = this.getCore();
9483
9715
  return core.api.getSelectionRange(core, tryGetFromCache);
@@ -9489,7 +9721,7 @@ var Editor = /** @class */ (function () {
9489
9721
  * Default value is true
9490
9722
  * @returns current selection range, or null if editor never got focus before
9491
9723
  */
9492
- Editor.prototype.getSelectionRangeEx = function () {
9724
+ EditorBase.prototype.getSelectionRangeEx = function () {
9493
9725
  var core = this.getCore();
9494
9726
  return core.api.getSelectionRangeEx(core);
9495
9727
  };
@@ -9498,7 +9730,7 @@ var Editor = /** @class */ (function () {
9498
9730
  * It does a live pull on the selection, if nothing retrieved, return whatever we have in cache.
9499
9731
  * @returns current selection path, or null if editor never got focus before
9500
9732
  */
9501
- Editor.prototype.getSelectionPath = function () {
9733
+ EditorBase.prototype.getSelectionPath = function () {
9502
9734
  var range = this.getSelectionRange();
9503
9735
  return range && (0, roosterjs_editor_dom_1.getSelectionPath)(this.getCore().contentDiv, range);
9504
9736
  };
@@ -9506,99 +9738,25 @@ var Editor = /** @class */ (function () {
9506
9738
  * Check if focus is in editor now
9507
9739
  * @returns true if focus is in editor, otherwise false
9508
9740
  */
9509
- Editor.prototype.hasFocus = function () {
9741
+ EditorBase.prototype.hasFocus = function () {
9510
9742
  var core = this.getCore();
9511
9743
  return core.api.hasFocus(core);
9512
9744
  };
9513
9745
  /**
9514
9746
  * Focus to this editor, the selection was restored to where it was before, no unexpected scroll.
9515
9747
  */
9516
- Editor.prototype.focus = function () {
9748
+ EditorBase.prototype.focus = function () {
9517
9749
  var core = this.getCore();
9518
9750
  core.api.focus(core);
9519
9751
  };
9520
- Editor.prototype.select = function (arg1, arg2, arg3, arg4) {
9752
+ EditorBase.prototype.select = function (arg1, arg2, arg3, arg4) {
9521
9753
  var core = this.getCore();
9522
- var rangeEx = null;
9523
- if (isSelectionRangeEx(arg1)) {
9524
- rangeEx = arg1;
9525
- }
9526
- else if ((0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'HTMLTableElement') && isTableSelection(arg2)) {
9527
- rangeEx = {
9528
- type: 1 /* TableSelection */,
9529
- ranges: [],
9530
- areAllCollapsed: false,
9531
- table: arg1,
9532
- coordinates: arg2,
9533
- };
9534
- }
9535
- else if ((0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'HTMLImageElement') && typeof arg2 == 'undefined') {
9536
- rangeEx = {
9537
- type: 2 /* ImageSelection */,
9538
- ranges: [],
9539
- areAllCollapsed: false,
9540
- image: arg1,
9541
- };
9542
- }
9543
- else {
9544
- var range = !arg1
9545
- ? null
9546
- : (0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'Range')
9547
- ? arg1
9548
- : isSelectionPath(arg1)
9549
- ? (0, roosterjs_editor_dom_1.createRange)(core.contentDiv, arg1.start, arg1.end)
9550
- : isNodePosition(arg1) || (0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'Node')
9551
- ? (0, roosterjs_editor_dom_1.createRange)(arg1, arg2, arg3, arg4)
9552
- : null;
9553
- rangeEx = range
9554
- ? {
9555
- type: 0 /* Normal */,
9556
- ranges: [range],
9557
- areAllCollapsed: range.collapsed,
9558
- }
9559
- : null;
9560
- }
9561
- if (rangeEx) {
9562
- switch (rangeEx.type) {
9563
- case 1 /* TableSelection */:
9564
- if (this.contains(rangeEx.table)) {
9565
- core.domEvent.imageSelectionRange = core.api.selectImage(core, null);
9566
- core.domEvent.tableSelectionRange = core.api.selectTable(core, rangeEx.table, rangeEx.coordinates);
9567
- rangeEx = core.domEvent.tableSelectionRange;
9568
- }
9569
- break;
9570
- case 2 /* ImageSelection */:
9571
- if (this.contains(rangeEx.image)) {
9572
- core.domEvent.tableSelectionRange = core.api.selectTable(core, null);
9573
- core.domEvent.imageSelectionRange = core.api.selectImage(core, rangeEx.image);
9574
- rangeEx = core.domEvent.imageSelectionRange;
9575
- }
9576
- break;
9577
- case 0 /* Normal */:
9578
- core.domEvent.tableSelectionRange = core.api.selectTable(core, null);
9579
- core.domEvent.imageSelectionRange = core.api.selectImage(core, null);
9580
- if (this.contains(rangeEx.ranges[0])) {
9581
- core.api.selectRange(core, rangeEx.ranges[0]);
9582
- }
9583
- else {
9584
- rangeEx = null;
9585
- }
9586
- break;
9587
- }
9588
- this.triggerPluginEvent(22 /* SelectionChanged */, {
9589
- selectionRangeEx: rangeEx,
9590
- }, true /** broadcast **/);
9591
- }
9592
- else {
9593
- core.domEvent.tableSelectionRange = core.api.selectTable(core, null);
9594
- core.domEvent.imageSelectionRange = core.api.selectImage(core, null);
9595
- }
9596
- return !!rangeEx;
9754
+ return core.api.select(core, arg1, arg2, arg3, arg4);
9597
9755
  };
9598
9756
  /**
9599
9757
  * Get current focused position. Return null if editor doesn't have focus at this time.
9600
9758
  */
9601
- Editor.prototype.getFocusedPosition = function () {
9759
+ EditorBase.prototype.getFocusedPosition = function () {
9602
9760
  var _a;
9603
9761
  var sel = (_a = this.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
9604
9762
  if ((sel === null || sel === void 0 ? void 0 : sel.focusNode) && this.contains(sel.focusNode)) {
@@ -9622,7 +9780,7 @@ var Editor = /** @class */ (function () {
9622
9780
  * @param event Optional, if specified, editor will try to get cached result from the event object first.
9623
9781
  * If it is not cached before, query from DOM and cache the result into the event object
9624
9782
  */
9625
- Editor.prototype.getElementAtCursor = function (selector, startFrom, event) {
9783
+ EditorBase.prototype.getElementAtCursor = function (selector, startFrom, event) {
9626
9784
  var _this = this;
9627
9785
  var _a;
9628
9786
  event = startFrom ? undefined : event; // Only use cache when startFrom is not specified, for different start position can have different result
@@ -9641,13 +9799,13 @@ var Editor = /** @class */ (function () {
9641
9799
  * @param position The position to check
9642
9800
  * @returns True if position is at beginning of the editor, otherwise false
9643
9801
  */
9644
- Editor.prototype.isPositionAtBeginning = function (position) {
9802
+ EditorBase.prototype.isPositionAtBeginning = function (position) {
9645
9803
  return (0, roosterjs_editor_dom_1.isPositionAtBeginningOf)(position, this.getCore().contentDiv);
9646
9804
  };
9647
9805
  /**
9648
9806
  * Get impacted regions from selection
9649
9807
  */
9650
- Editor.prototype.getSelectedRegions = function (type) {
9808
+ EditorBase.prototype.getSelectedRegions = function (type) {
9651
9809
  if (type === void 0) { type = 0 /* Table */; }
9652
9810
  var selection = this.getSelectionRangeEx();
9653
9811
  var result = [];
@@ -9661,7 +9819,7 @@ var Editor = /** @class */ (function () {
9661
9819
  };
9662
9820
  //#endregion
9663
9821
  //#region EVENT API
9664
- Editor.prototype.addDomEventHandler = function (nameOrMap, handler) {
9822
+ EditorBase.prototype.addDomEventHandler = function (nameOrMap, handler) {
9665
9823
  var _a;
9666
9824
  var eventsToMap = typeof nameOrMap == 'string' ? (_a = {}, _a[nameOrMap] = handler, _a) : nameOrMap;
9667
9825
  var core = this.getCore();
@@ -9676,7 +9834,7 @@ var Editor = /** @class */ (function () {
9676
9834
  * @returns the event object which is really passed into plugins. Some plugin may modify the event object so
9677
9835
  * the result of this function provides a chance to read the modified result
9678
9836
  */
9679
- Editor.prototype.triggerPluginEvent = function (eventType, data, broadcast) {
9837
+ EditorBase.prototype.triggerPluginEvent = function (eventType, data, broadcast) {
9680
9838
  if (broadcast === void 0) { broadcast = false; }
9681
9839
  var core = this.getCore();
9682
9840
  var event = __assign({ eventType: eventType }, data);
@@ -9688,7 +9846,7 @@ var Editor = /** @class */ (function () {
9688
9846
  * @param source Source of this event, by default is 'SetContent'
9689
9847
  * @param data additional data for this event
9690
9848
  */
9691
- Editor.prototype.triggerContentChangedEvent = function (source, data) {
9849
+ EditorBase.prototype.triggerContentChangedEvent = function (source, data) {
9692
9850
  if (source === void 0) { source = "SetContent" /* SetContent */; }
9693
9851
  this.triggerPluginEvent(7 /* ContentChanged */, {
9694
9852
  source: source,
@@ -9700,7 +9858,7 @@ var Editor = /** @class */ (function () {
9700
9858
  /**
9701
9859
  * Undo last edit operation
9702
9860
  */
9703
- Editor.prototype.undo = function () {
9861
+ EditorBase.prototype.undo = function () {
9704
9862
  this.focus();
9705
9863
  var core = this.getCore();
9706
9864
  core.api.restoreUndoSnapshot(core, -1 /*step*/);
@@ -9708,7 +9866,7 @@ var Editor = /** @class */ (function () {
9708
9866
  /**
9709
9867
  * Redo next edit operation
9710
9868
  */
9711
- Editor.prototype.redo = function () {
9869
+ EditorBase.prototype.redo = function () {
9712
9870
  this.focus();
9713
9871
  var core = this.getCore();
9714
9872
  core.api.restoreUndoSnapshot(core, 1 /*step*/);
@@ -9723,14 +9881,14 @@ var Editor = /** @class */ (function () {
9723
9881
  * a ContentChangedEvent will be fired with change source equal to this value
9724
9882
  * @param canUndoByBackspace True if this action can be undone when user press Backspace key (aka Auto Complete).
9725
9883
  */
9726
- Editor.prototype.addUndoSnapshot = function (callback, changeSource, canUndoByBackspace, additionalData) {
9884
+ EditorBase.prototype.addUndoSnapshot = function (callback, changeSource, canUndoByBackspace, additionalData) {
9727
9885
  var core = this.getCore();
9728
9886
  core.api.addUndoSnapshot(core, callback !== null && callback !== void 0 ? callback : null, changeSource !== null && changeSource !== void 0 ? changeSource : null, canUndoByBackspace !== null && canUndoByBackspace !== void 0 ? canUndoByBackspace : false, additionalData);
9729
9887
  };
9730
9888
  /**
9731
9889
  * Whether there is an available undo/redo snapshot
9732
9890
  */
9733
- Editor.prototype.getUndoState = function () {
9891
+ EditorBase.prototype.getUndoState = function () {
9734
9892
  var _a = this.getCore().undo, hasNewContent = _a.hasNewContent, snapshotsService = _a.snapshotsService;
9735
9893
  return {
9736
9894
  canUndo: hasNewContent || snapshotsService.canMove(-1 /*previousSnapshot*/),
@@ -9743,13 +9901,13 @@ var Editor = /** @class */ (function () {
9743
9901
  * Get document which contains this editor
9744
9902
  * @returns The HTML document which contains this editor
9745
9903
  */
9746
- Editor.prototype.getDocument = function () {
9904
+ EditorBase.prototype.getDocument = function () {
9747
9905
  return this.getCore().contentDiv.ownerDocument;
9748
9906
  };
9749
9907
  /**
9750
9908
  * Get the scroll container of the editor
9751
9909
  */
9752
- Editor.prototype.getScrollContainer = function () {
9910
+ EditorBase.prototype.getScrollContainer = function () {
9753
9911
  return this.getCore().domEvent.scrollContainer;
9754
9912
  };
9755
9913
  /**
@@ -9760,7 +9918,7 @@ var Editor = /** @class */ (function () {
9760
9918
  * @param disposer An optional disposer function to dispose this custom data when
9761
9919
  * dispose editor.
9762
9920
  */
9763
- Editor.prototype.getCustomData = function (key, getter, disposer) {
9921
+ EditorBase.prototype.getCustomData = function (key, getter, disposer) {
9764
9922
  var core = this.getCore();
9765
9923
  return (core.lifecycle.customData[key] = core.lifecycle.customData[key] || {
9766
9924
  value: getter ? getter() : undefined,
@@ -9771,14 +9929,14 @@ var Editor = /** @class */ (function () {
9771
9929
  * Check if editor is in IME input sequence
9772
9930
  * @returns True if editor is in IME input sequence, otherwise false
9773
9931
  */
9774
- Editor.prototype.isInIME = function () {
9932
+ EditorBase.prototype.isInIME = function () {
9775
9933
  return this.getCore().domEvent.isInIME;
9776
9934
  };
9777
9935
  /**
9778
9936
  * Get default format of this editor
9779
9937
  * @returns Default format object of this editor
9780
9938
  */
9781
- Editor.prototype.getDefaultFormat = function () {
9939
+ EditorBase.prototype.getDefaultFormat = function () {
9782
9940
  var _a;
9783
9941
  return (_a = this.getCore().lifecycle.defaultFormat) !== null && _a !== void 0 ? _a : {};
9784
9942
  };
@@ -9786,14 +9944,14 @@ var Editor = /** @class */ (function () {
9786
9944
  * Get a content traverser for the whole editor
9787
9945
  * @param startNode The node to start from. If not passed, it will start from the beginning of the body
9788
9946
  */
9789
- Editor.prototype.getBodyTraverser = function (startNode) {
9947
+ EditorBase.prototype.getBodyTraverser = function (startNode) {
9790
9948
  return roosterjs_editor_dom_1.ContentTraverser.createBodyTraverser(this.getCore().contentDiv, startNode);
9791
9949
  };
9792
9950
  /**
9793
9951
  * Get a content traverser for current selection
9794
9952
  * @returns A content traverser, or null if editor never got focus before
9795
9953
  */
9796
- Editor.prototype.getSelectionTraverser = function (range) {
9954
+ EditorBase.prototype.getSelectionTraverser = function (range) {
9797
9955
  var _a;
9798
9956
  range = (_a = range !== null && range !== void 0 ? range : this.getSelectionRange()) !== null && _a !== void 0 ? _a : undefined;
9799
9957
  return range
@@ -9805,7 +9963,7 @@ var Editor = /** @class */ (function () {
9805
9963
  * @param startFrom Start position of the traverser. Default value is ContentPosition.SelectionStart
9806
9964
  * @returns A content traverser, or null if editor never got focus before
9807
9965
  */
9808
- Editor.prototype.getBlockTraverser = function (startFrom) {
9966
+ EditorBase.prototype.getBlockTraverser = function (startFrom) {
9809
9967
  if (startFrom === void 0) { startFrom = 3 /* SelectionStart */; }
9810
9968
  var range = this.getSelectionRange();
9811
9969
  return range
@@ -9818,7 +9976,7 @@ var Editor = /** @class */ (function () {
9818
9976
  * If it is not cached before, query from DOM and cache the result into the event object
9819
9977
  * @returns A content traverser, or null if editor never got focus before
9820
9978
  */
9821
- Editor.prototype.getContentSearcherOfCursor = function (event) {
9979
+ EditorBase.prototype.getContentSearcherOfCursor = function (event) {
9822
9980
  var _this = this;
9823
9981
  return (0, roosterjs_editor_dom_1.cacheGetEventData)(event !== null && event !== void 0 ? event : null, 'ContentSearcher', function () {
9824
9982
  var range = _this.getSelectionRange();
@@ -9831,7 +9989,7 @@ var Editor = /** @class */ (function () {
9831
9989
  * @param callback The callback function to run
9832
9990
  * @returns a function to cancel this async run
9833
9991
  */
9834
- Editor.prototype.runAsync = function (callback) {
9992
+ EditorBase.prototype.runAsync = function (callback) {
9835
9993
  var _this = this;
9836
9994
  var win = this.getCore().contentDiv.ownerDocument.defaultView || window;
9837
9995
  var handle = win.requestAnimationFrame(function () {
@@ -9848,7 +10006,7 @@ var Editor = /** @class */ (function () {
9848
10006
  * @param name Name of the attribute
9849
10007
  * @param value Value of the attribute
9850
10008
  */
9851
- Editor.prototype.setEditorDomAttribute = function (name, value) {
10009
+ EditorBase.prototype.setEditorDomAttribute = function (name, value) {
9852
10010
  if (value === null) {
9853
10011
  this.getCore().contentDiv.removeAttribute(name);
9854
10012
  }
@@ -9860,7 +10018,7 @@ var Editor = /** @class */ (function () {
9860
10018
  * Get DOM attribute of editor content DIV, null if there is no such attribute.
9861
10019
  * @param name Name of the attribute
9862
10020
  */
9863
- Editor.prototype.getEditorDomAttribute = function (name) {
10021
+ EditorBase.prototype.getEditorDomAttribute = function (name) {
9864
10022
  return this.getCore().contentDiv.getAttribute(name);
9865
10023
  };
9866
10024
  /**
@@ -9872,7 +10030,7 @@ var Editor = /** @class */ (function () {
9872
10030
  * may be different than what user is seeing from the view. When pass false, scroll position will be ignored.
9873
10031
  * @returns An [x, y] array which contains the left and top distances, or null if the given element is not in editor.
9874
10032
  */
9875
- Editor.prototype.getRelativeDistanceToEditor = function (element, addScroll) {
10033
+ EditorBase.prototype.getRelativeDistanceToEditor = function (element, addScroll) {
9876
10034
  if (this.contains(element)) {
9877
10035
  var contentDiv = this.getCore().contentDiv;
9878
10036
  var editorRect = contentDiv.getBoundingClientRect();
@@ -9893,7 +10051,7 @@ var Editor = /** @class */ (function () {
9893
10051
  * Add a Content Edit feature.
9894
10052
  * @param feature The feature to add
9895
10053
  */
9896
- Editor.prototype.addContentEditFeature = function (feature) {
10054
+ EditorBase.prototype.addContentEditFeature = function (feature) {
9897
10055
  var core = this.getCore();
9898
10056
  feature === null || feature === void 0 ? void 0 : feature.keys.forEach(function (key) {
9899
10057
  var array = core.edit.features[key] || [];
@@ -9905,7 +10063,7 @@ var Editor = /** @class */ (function () {
9905
10063
  * Remove a Content Edit feature.
9906
10064
  * @param feature The feature to remove
9907
10065
  */
9908
- Editor.prototype.removeContentEditFeature = function (feature) {
10066
+ EditorBase.prototype.removeContentEditFeature = function (feature) {
9909
10067
  var core = this.getCore();
9910
10068
  feature === null || feature === void 0 ? void 0 : feature.keys.forEach(function (key) {
9911
10069
  var _a;
@@ -9922,7 +10080,7 @@ var Editor = /** @class */ (function () {
9922
10080
  /**
9923
10081
  * Get style based format state from current selection, including font name/size and colors
9924
10082
  */
9925
- Editor.prototype.getStyleBasedFormatState = function (node) {
10083
+ EditorBase.prototype.getStyleBasedFormatState = function (node) {
9926
10084
  var _a;
9927
10085
  if (!node) {
9928
10086
  var range = this.getSelectionRange();
@@ -9936,7 +10094,7 @@ var Editor = /** @class */ (function () {
9936
10094
  * @param forceGetStateFromDOM If set to true, will force get the format state from DOM tree.
9937
10095
  * @returns The pending format state
9938
10096
  */
9939
- Editor.prototype.getPendableFormatState = function (forceGetStateFromDOM) {
10097
+ EditorBase.prototype.getPendableFormatState = function (forceGetStateFromDOM) {
9940
10098
  if (forceGetStateFromDOM === void 0) { forceGetStateFromDOM = false; }
9941
10099
  var core = this.getCore();
9942
10100
  return core.api.getPendableFormatState(core, forceGetStateFromDOM);
@@ -9946,7 +10104,7 @@ var Editor = /** @class */ (function () {
9946
10104
  * @param position The position that user is about to type to
9947
10105
  * @param keyboardEvent Optional keyboard event object
9948
10106
  */
9949
- Editor.prototype.ensureTypeInContainer = function (position, keyboardEvent) {
10107
+ EditorBase.prototype.ensureTypeInContainer = function (position, keyboardEvent) {
9950
10108
  var core = this.getCore();
9951
10109
  core.api.ensureTypeInContainer(core, position, keyboardEvent, this.isFeatureEnabled("DefaultFormatInSpan" /* DefaultFormatInSpan */));
9952
10110
  };
@@ -9956,7 +10114,7 @@ var Editor = /** @class */ (function () {
9956
10114
  * Set the dark mode state and transforms the content to match the new state.
9957
10115
  * @param nextDarkMode The next status of dark mode. True if the editor should be in dark mode, false if not.
9958
10116
  */
9959
- Editor.prototype.setDarkModeState = function (nextDarkMode) {
10117
+ EditorBase.prototype.setDarkModeState = function (nextDarkMode) {
9960
10118
  var isDarkMode = this.isDarkMode();
9961
10119
  if (isDarkMode == !!nextDarkMode) {
9962
10120
  return;
@@ -9971,21 +10129,21 @@ var Editor = /** @class */ (function () {
9971
10129
  * Check if the editor is in dark mode
9972
10130
  * @returns True if the editor is in dark mode, otherwise false
9973
10131
  */
9974
- Editor.prototype.isDarkMode = function () {
10132
+ EditorBase.prototype.isDarkMode = function () {
9975
10133
  return this.getCore().lifecycle.isDarkMode;
9976
10134
  };
9977
10135
  /**
9978
10136
  * Transform the given node and all its child nodes to dark mode color if editor is in dark mode
9979
10137
  * @param node The node to transform
9980
10138
  */
9981
- Editor.prototype.transformToDarkColor = function (node) {
10139
+ EditorBase.prototype.transformToDarkColor = function (node) {
9982
10140
  var core = this.getCore();
9983
10141
  core.api.transformColor(core, node, true /*includeSelf*/, null /*callback*/, 0 /* LightToDark */);
9984
10142
  };
9985
10143
  /**
9986
10144
  * Get a darkColorHandler object for this editor. It will return null if experimental feature "VariableBasedDarkColor" is not enabled
9987
10145
  */
9988
- Editor.prototype.getDarkColorHandler = function () {
10146
+ EditorBase.prototype.getDarkColorHandler = function () {
9989
10147
  return this.getCore().darkColorHandler || null;
9990
10148
  };
9991
10149
  /**
@@ -9996,29 +10154,29 @@ var Editor = /** @class */ (function () {
9996
10154
  * This function can be called repeated. If editor is already in shadow edit mode, we can still
9997
10155
  * use this function to do more shadow edit operation.
9998
10156
  */
9999
- Editor.prototype.startShadowEdit = function () {
10157
+ EditorBase.prototype.startShadowEdit = function () {
10000
10158
  var core = this.getCore();
10001
10159
  core.api.switchShadowEdit(core, true /*isOn*/);
10002
10160
  };
10003
10161
  /**
10004
10162
  * Leave "Shadow Edit" mode, all changes made during shadow edit will be discarded
10005
10163
  */
10006
- Editor.prototype.stopShadowEdit = function () {
10164
+ EditorBase.prototype.stopShadowEdit = function () {
10007
10165
  var core = this.getCore();
10008
10166
  core.api.switchShadowEdit(core, false /*isOn*/);
10009
10167
  };
10010
10168
  /**
10011
10169
  * Check if editor is in Shadow Edit mode
10012
10170
  */
10013
- Editor.prototype.isInShadowEdit = function () {
10171
+ EditorBase.prototype.isInShadowEdit = function () {
10014
10172
  return !!this.getCore().lifecycle.shadowEditFragment;
10015
10173
  };
10016
10174
  /**
10017
10175
  * Check if the given experimental feature is enabled
10018
10176
  * @param feature The feature to check
10019
10177
  */
10020
- Editor.prototype.isFeatureEnabled = function (feature) {
10021
- return this.getCore().lifecycle.experimentalFeatures.indexOf(feature) >= 0;
10178
+ EditorBase.prototype.isFeatureEnabled = function (feature) {
10179
+ return (0, isFeatureEnabled_1.isFeatureEnabled)(this.getCore().lifecycle.experimentalFeatures, feature);
10022
10180
  };
10023
10181
  /**
10024
10182
  * Get a function to convert HTML string to trusted HTML string.
@@ -10026,13 +10184,13 @@ var Editor = /** @class */ (function () {
10026
10184
  * pass your own trusted HTML handler to EditorOptions.trustedHTMLHandler
10027
10185
  * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types
10028
10186
  */
10029
- Editor.prototype.getTrustedHTMLHandler = function () {
10187
+ EditorBase.prototype.getTrustedHTMLHandler = function () {
10030
10188
  return this.getCore().trustedHTMLHandler;
10031
10189
  };
10032
10190
  /**
10033
10191
  * @deprecated Use getZoomScale() instead
10034
10192
  */
10035
- Editor.prototype.getSizeTransformer = function () {
10193
+ EditorBase.prototype.getSizeTransformer = function () {
10036
10194
  return this.getCore().sizeTransformer;
10037
10195
  };
10038
10196
  /**
@@ -10041,7 +10199,7 @@ var Editor = /** @class */ (function () {
10041
10199
  * to let editor behave correctly especially for those mouse drag/drop behaviors
10042
10200
  * @returns current zoom scale number
10043
10201
  */
10044
- Editor.prototype.getZoomScale = function () {
10202
+ EditorBase.prototype.getZoomScale = function () {
10045
10203
  return this.getCore().zoomScale;
10046
10204
  };
10047
10205
  /**
@@ -10050,7 +10208,7 @@ var Editor = /** @class */ (function () {
10050
10208
  * to let editor behave correctly especially for those mouse drag/drop behaviors
10051
10209
  * @param scale The new scale number to set. It should be positive number and no greater than 10, otherwise it will be ignored.
10052
10210
  */
10053
- Editor.prototype.setZoomScale = function (scale) {
10211
+ EditorBase.prototype.setZoomScale = function (scale) {
10054
10212
  var core = this.getCore();
10055
10213
  if (scale > 0 && scale <= 10) {
10056
10214
  var oldValue = core.zoomScale;
@@ -10066,47 +10224,112 @@ var Editor = /** @class */ (function () {
10066
10224
  /**
10067
10225
  * Retrieves the rect of the visible viewport of the editor.
10068
10226
  */
10069
- Editor.prototype.getVisibleViewport = function () {
10227
+ EditorBase.prototype.getVisibleViewport = function () {
10070
10228
  return this.getCore().getVisibleViewport();
10071
10229
  };
10072
10230
  /**
10073
10231
  * @returns the current EditorCore object
10074
10232
  * @throws a standard Error if there's no core object
10075
10233
  */
10076
- Editor.prototype.getCore = function () {
10234
+ EditorBase.prototype.getCore = function () {
10077
10235
  if (!this.core) {
10078
10236
  throw new Error('Editor is already disposed');
10079
10237
  }
10080
10238
  return this.core;
10081
10239
  };
10082
- return Editor;
10240
+ return EditorBase;
10083
10241
  }());
10084
- exports.default = Editor;
10085
- function isSelectionRangeEx(obj) {
10086
- var rangeEx = obj;
10087
- return (rangeEx &&
10088
- typeof rangeEx == 'object' &&
10089
- typeof rangeEx.type == 'number' &&
10090
- Array.isArray(rangeEx.ranges));
10091
- }
10092
- function isTableSelection(obj) {
10093
- var selection = obj;
10094
- return (selection &&
10095
- typeof selection == 'object' &&
10096
- typeof selection.firstCell == 'object' &&
10097
- typeof selection.lastCell == 'object');
10098
- }
10099
- function isSelectionPath(obj) {
10100
- var path = obj;
10101
- return path && typeof path == 'object' && Array.isArray(path.start) && Array.isArray(path.end);
10102
- }
10103
- function isNodePosition(obj) {
10104
- var pos = obj;
10105
- return (pos &&
10106
- typeof pos == 'object' &&
10107
- typeof pos.node == 'object' &&
10108
- typeof pos.offset == 'number');
10242
+ exports.EditorBase = EditorBase;
10243
+
10244
+
10245
+ /***/ }),
10246
+
10247
+ /***/ "./packages/roosterjs-editor-core/lib/editor/createEditorCore.ts":
10248
+ /*!***********************************************************************!*\
10249
+ !*** ./packages/roosterjs-editor-core/lib/editor/createEditorCore.ts ***!
10250
+ \***********************************************************************/
10251
+ /*! no static exports found */
10252
+ /***/ (function(module, exports, __webpack_require__) {
10253
+
10254
+ "use strict";
10255
+
10256
+ var __assign = (this && this.__assign) || function () {
10257
+ __assign = Object.assign || function(t) {
10258
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
10259
+ s = arguments[i];
10260
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
10261
+ t[p] = s[p];
10262
+ }
10263
+ return t;
10264
+ };
10265
+ return __assign.apply(this, arguments);
10266
+ };
10267
+ Object.defineProperty(exports, "__esModule", { value: true });
10268
+ exports.createEditorCore = void 0;
10269
+ var createCorePlugins_1 = __webpack_require__(/*! ../corePlugins/createCorePlugins */ "./packages/roosterjs-editor-core/lib/corePlugins/createCorePlugins.ts");
10270
+ var DarkColorHandlerImpl_1 = __webpack_require__(/*! ./DarkColorHandlerImpl */ "./packages/roosterjs-editor-core/lib/editor/DarkColorHandlerImpl.ts");
10271
+ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
10272
+ var coreApiMap_1 = __webpack_require__(/*! ../coreApi/coreApiMap */ "./packages/roosterjs-editor-core/lib/coreApi/coreApiMap.ts");
10273
+ var isFeatureEnabled_1 = __webpack_require__(/*! ./isFeatureEnabled */ "./packages/roosterjs-editor-core/lib/editor/isFeatureEnabled.ts");
10274
+ /**
10275
+ * Create a new instance of Editor Core
10276
+ * @param contentDiv The DIV HTML element which will be the container element of editor
10277
+ * @param options An optional options object to customize the editor
10278
+ */
10279
+ var createEditorCore = function (contentDiv, options) {
10280
+ var _a;
10281
+ var corePlugins = (0, createCorePlugins_1.default)(contentDiv, options);
10282
+ var plugins = [];
10283
+ (0, roosterjs_editor_dom_1.getObjectKeys)(corePlugins).forEach(function (name) {
10284
+ if (name == '_placeholder') {
10285
+ if (options.plugins) {
10286
+ (0, roosterjs_editor_dom_1.arrayPush)(plugins, options.plugins);
10287
+ }
10288
+ }
10289
+ else {
10290
+ plugins.push(corePlugins[name]);
10291
+ }
10292
+ });
10293
+ var pluginState = (0, createCorePlugins_1.getPluginState)(corePlugins);
10294
+ var zoomScale = ((_a = options.zoomScale) !== null && _a !== void 0 ? _a : -1) > 0 ? options.zoomScale : 1;
10295
+ var getVisibleViewport = options.getVisibleViewport ||
10296
+ (function () {
10297
+ var scrollContainer = pluginState.domEvent.scrollContainer;
10298
+ return (0, roosterjs_editor_dom_1.getIntersectedRect)(scrollContainer == core.contentDiv
10299
+ ? [scrollContainer]
10300
+ : [scrollContainer, core.contentDiv]);
10301
+ });
10302
+ var core = __assign(__assign({ contentDiv: contentDiv, api: __assign(__assign({}, coreApiMap_1.coreApiMap), (options.coreApiOverride || {})), originalApi: coreApiMap_1.coreApiMap, plugins: plugins.filter(function (x) { return !!x; }) }, pluginState), { trustedHTMLHandler: options.trustedHTMLHandler || (function (html) { return html; }), zoomScale: zoomScale, sizeTransformer: options.sizeTransformer || (function (size) { return size / zoomScale; }), getVisibleViewport: getVisibleViewport, imageSelectionBorderColor: options.imageSelectionBorderColor, darkColorHandler: (0, isFeatureEnabled_1.isFeatureEnabled)(options.experimentalFeatures, "VariableBasedDarkColor" /* VariableBasedDarkColor */)
10303
+ ? new DarkColorHandlerImpl_1.default(contentDiv, pluginState.lifecycle.getDarkColor)
10304
+ : undefined });
10305
+ return core;
10306
+ };
10307
+ exports.createEditorCore = createEditorCore;
10308
+
10309
+
10310
+ /***/ }),
10311
+
10312
+ /***/ "./packages/roosterjs-editor-core/lib/editor/isFeatureEnabled.ts":
10313
+ /*!***********************************************************************!*\
10314
+ !*** ./packages/roosterjs-editor-core/lib/editor/isFeatureEnabled.ts ***!
10315
+ \***********************************************************************/
10316
+ /*! no static exports found */
10317
+ /***/ (function(module, exports, __webpack_require__) {
10318
+
10319
+ "use strict";
10320
+
10321
+ Object.defineProperty(exports, "__esModule", { value: true });
10322
+ exports.isFeatureEnabled = void 0;
10323
+ /**
10324
+ * Check if the given experimental feature is enabled
10325
+ * @param featureSet All enabled features
10326
+ * @param feature The feature to check
10327
+ * @returns True if the given feature is enabled, otherwise false
10328
+ */
10329
+ function isFeatureEnabled(featureSet, feature) {
10330
+ return (featureSet || []).indexOf(feature) >= 0;
10109
10331
  }
10332
+ exports.isFeatureEnabled = isFeatureEnabled;
10110
10333
 
10111
10334
 
10112
10335
  /***/ }),
@@ -10121,10 +10344,16 @@ function isNodePosition(obj) {
10121
10344
  "use strict";
10122
10345
 
10123
10346
  Object.defineProperty(exports, "__esModule", { value: true });
10124
- exports.Editor = void 0;
10347
+ exports.createEditorCore = exports.isFeatureEnabled = exports.EditorBase = exports.Editor = void 0;
10125
10348
  // Classes
10126
10349
  var Editor_1 = __webpack_require__(/*! ./editor/Editor */ "./packages/roosterjs-editor-core/lib/editor/Editor.ts");
10127
10350
  Object.defineProperty(exports, "Editor", { enumerable: true, get: function () { return Editor_1.default; } });
10351
+ var EditorBase_1 = __webpack_require__(/*! ./editor/EditorBase */ "./packages/roosterjs-editor-core/lib/editor/EditorBase.ts");
10352
+ Object.defineProperty(exports, "EditorBase", { enumerable: true, get: function () { return EditorBase_1.EditorBase; } });
10353
+ var isFeatureEnabled_1 = __webpack_require__(/*! ./editor/isFeatureEnabled */ "./packages/roosterjs-editor-core/lib/editor/isFeatureEnabled.ts");
10354
+ Object.defineProperty(exports, "isFeatureEnabled", { enumerable: true, get: function () { return isFeatureEnabled_1.isFeatureEnabled; } });
10355
+ var createEditorCore_1 = __webpack_require__(/*! ./editor/createEditorCore */ "./packages/roosterjs-editor-core/lib/editor/createEditorCore.ts");
10356
+ Object.defineProperty(exports, "createEditorCore", { enumerable: true, get: function () { return createEditorCore_1.createEditorCore; } });
10128
10357
 
10129
10358
 
10130
10359
  /***/ }),
@@ -10379,6 +10608,9 @@ function getBlockElementAtNode(rootNode, node) {
10379
10608
  // Find the head and leaf node in the block
10380
10609
  var headNode = findHeadTailLeafNode(node, containerBlockNode, false /*isTail*/);
10381
10610
  var tailNode = findHeadTailLeafNode(node, containerBlockNode, true /*isTail*/);
10611
+ if (!headNode || !tailNode) {
10612
+ return null;
10613
+ }
10382
10614
  // At this point, we have the head and tail of a block, here are some examples and where head and tail point to
10383
10615
  // 1) &lt;root&gt;&lt;div&gt;hello&lt;br&gt;&lt;/div&gt;&lt;/root&gt;, head: hello, tail: &lt;br&gt;
10384
10616
  // 2) &lt;root&gt;&lt;div&gt;hello&lt;span style="font-family: Arial"&gt;world&lt;/span&gt;&lt;/div&gt;&lt;/root&gt;, head: hello, tail: world
@@ -11504,7 +11736,7 @@ function insertDelimiter(element, delimiterClass) {
11504
11736
  var insertPosition = delimiterClass == "entityDelimiterAfter" /* DELIMITER_AFTER */ ? 'afterend' : 'beforebegin';
11505
11737
  element.insertAdjacentElement(insertPosition, span);
11506
11738
  }
11507
- return element;
11739
+ return span;
11508
11740
  }
11509
11741
 
11510
11742
 
@@ -21081,15 +21313,16 @@ var ContentEdit = /** @class */ (function () {
21081
21313
  this.editor = editor;
21082
21314
  var allFeatures = (0, getAllFeatures_1.default)();
21083
21315
  (0, roosterjs_editor_dom_1.getObjectKeys)(allFeatures).forEach(function (key) {
21316
+ var _a;
21084
21317
  var feature = allFeatures[key];
21085
21318
  var hasSettingForKey = _this.settingsOverride && _this.settingsOverride[key] !== undefined;
21086
- if ((hasSettingForKey && _this.settingsOverride[key]) ||
21319
+ if ((hasSettingForKey && ((_a = _this.settingsOverride) === null || _a === void 0 ? void 0 : _a[key])) ||
21087
21320
  (!hasSettingForKey && !feature.defaultDisabled)) {
21088
21321
  _this.features.push(feature);
21089
21322
  }
21090
21323
  });
21091
21324
  this.features = this.features.concat(this.additionalFeatures || []);
21092
- this.features.forEach(function (feature) { return _this.editor.addContentEditFeature(feature); });
21325
+ this.features.forEach(function (feature) { var _a; return (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.addContentEditFeature(feature); });
21093
21326
  };
21094
21327
  ContentEdit.prototype.disposeFeatures = function () {
21095
21328
  var _this = this;
@@ -21161,14 +21394,15 @@ function cacheGetLinkData(event, editor) {
21161
21394
  // This helps when we paste a link next to some existing character, and the text we got
21162
21395
  // from clipboard will only contain what we pasted, any existing characters will not
21163
21396
  // be included.
21164
- var clipboardData = event.eventType == 7 /* ContentChanged */ &&
21397
+ var clipboardData = (event.eventType == 7 /* ContentChanged */ &&
21165
21398
  event.source == "Paste" /* Paste */ &&
21166
- event.data;
21167
- var link = (0, roosterjs_editor_dom_1.matchLink)((clipboardData.text || '').trim());
21399
+ event.data) ||
21400
+ null;
21401
+ var link = (0, roosterjs_editor_dom_1.matchLink)(((clipboardData === null || clipboardData === void 0 ? void 0 : clipboardData.text) || '').trim());
21168
21402
  var searcher = editor.getContentSearcherOfCursor(event);
21169
21403
  // In case the matched link is already inside a <A> tag, we do a range search.
21170
21404
  // getRangeFromText will return null if the given text is already in a LinkInlineElement
21171
- if (link && searcher.getRangeFromText(link.originalUrl, false /*exactMatch*/)) {
21405
+ if (link && (searcher === null || searcher === void 0 ? void 0 : searcher.getRangeFromText(link.originalUrl, false /*exactMatch*/))) {
21172
21406
  return link;
21173
21407
  }
21174
21408
  var word = searcher && searcher.getWordBefore();
@@ -21193,12 +21427,15 @@ function cacheGetLinkData(event, editor) {
21193
21427
  }
21194
21428
  function hasLinkBeforeCursor(event, editor) {
21195
21429
  var contentSearcher = editor.getContentSearcherOfCursor(event);
21196
- var inline = contentSearcher.getInlineElementBefore();
21430
+ var inline = contentSearcher === null || contentSearcher === void 0 ? void 0 : contentSearcher.getInlineElementBefore();
21197
21431
  return inline instanceof roosterjs_editor_dom_1.LinkInlineElement;
21198
21432
  }
21199
21433
  function autoLink(event, editor) {
21200
- var anchor = editor.getDocument().createElement('a');
21201
21434
  var linkData = cacheGetLinkData(event, editor);
21435
+ if (!linkData) {
21436
+ return;
21437
+ }
21438
+ var anchor = editor.getDocument().createElement('a');
21202
21439
  // Need to get searcher before we enter the async callback since the callback can happen when cursor is moved to next line
21203
21440
  // and at that time a new searcher won't be able to find the link text to replace
21204
21441
  var searcher = editor.getContentSearcherOfCursor();
@@ -21206,7 +21443,7 @@ function autoLink(event, editor) {
21206
21443
  anchor.href = linkData.normalizedUrl;
21207
21444
  editor.runAsync(function (editor) {
21208
21445
  editor.addUndoSnapshot(function () {
21209
- (0, roosterjs_editor_api_1.replaceWithNode)(editor, linkData.originalUrl, anchor, false /* exactMatch */, searcher);
21446
+ (0, roosterjs_editor_api_1.replaceWithNode)(editor, linkData.originalUrl, anchor, false /* exactMatch */, searcher !== null && searcher !== void 0 ? searcher : undefined);
21210
21447
  // The content at cursor has changed. Should also clear the cursor data cache
21211
21448
  (0, roosterjs_editor_dom_1.clearEventDataCache)(event);
21212
21449
  return anchor;
@@ -21222,6 +21459,91 @@ exports.AutoLinkFeatures = {
21222
21459
  };
21223
21460
 
21224
21461
 
21462
+ /***/ }),
21463
+
21464
+ /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/codeFeatures.ts":
21465
+ /*!********************************************************************************************!*\
21466
+ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/codeFeatures.ts ***!
21467
+ \********************************************************************************************/
21468
+ /*! no static exports found */
21469
+ /***/ (function(module, exports, __webpack_require__) {
21470
+
21471
+ "use strict";
21472
+
21473
+ Object.defineProperty(exports, "__esModule", { value: true });
21474
+ exports.CodeFeatures = void 0;
21475
+ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
21476
+ var RemoveCodeWhenEnterOnEmptyLine = {
21477
+ keys: [13 /* ENTER */],
21478
+ shouldHandleEvent: function (event, editor) {
21479
+ var childOfCode = cacheGetCodeChild(event, editor);
21480
+ return childOfCode && (0, roosterjs_editor_dom_1.isNodeEmpty)(childOfCode);
21481
+ },
21482
+ handleEvent: function (event, editor) {
21483
+ event.rawEvent.preventDefault();
21484
+ editor.addUndoSnapshot(function () {
21485
+ splitCode(event, editor);
21486
+ }, undefined /* changeSource */, true /* canUndoByBackspace */);
21487
+ },
21488
+ };
21489
+ var RemoveCodeWhenBackspaceOnEmptyFirstLine = {
21490
+ keys: [8 /* BACKSPACE */],
21491
+ shouldHandleEvent: function (event, editor) {
21492
+ var childOfCode = cacheGetCodeChild(event, editor);
21493
+ return childOfCode && (0, roosterjs_editor_dom_1.isNodeEmpty)(childOfCode) && !childOfCode.previousSibling;
21494
+ },
21495
+ handleEvent: function (event, editor) {
21496
+ event.rawEvent.preventDefault();
21497
+ editor.addUndoSnapshot(function () { return splitCode(event, editor); });
21498
+ },
21499
+ };
21500
+ function cacheGetCodeChild(event, editor) {
21501
+ return (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'CODE_CHILD', function () {
21502
+ var _a;
21503
+ var codeElement = (_a = editor.getElementAtCursor('code')) !== null && _a !== void 0 ? _a : editor.queryElements('code', 1 /* OnSelection */)[0];
21504
+ if (codeElement) {
21505
+ var pos = editor.getFocusedPosition();
21506
+ var block = pos && editor.getBlockElementAtNode(pos.normalize().node);
21507
+ if (block) {
21508
+ var node = block.getStartNode() == codeElement.parentNode
21509
+ ? block.getStartNode()
21510
+ : block.collapseToSingleElement();
21511
+ return (0, roosterjs_editor_dom_1.isNodeEmpty)(node) ? node : null;
21512
+ }
21513
+ }
21514
+ return null;
21515
+ });
21516
+ }
21517
+ function splitCode(event, editor) {
21518
+ var currentContainer = cacheGetCodeChild(event, editor);
21519
+ if (!(0, roosterjs_editor_dom_1.safeInstanceOf)(currentContainer, 'HTMLElement')) {
21520
+ return;
21521
+ }
21522
+ var codeChild = currentContainer.querySelector('code');
21523
+ if (!codeChild) {
21524
+ var codeParent = (0, roosterjs_editor_dom_1.splitBalancedNodeRange)(currentContainer);
21525
+ if (codeParent) {
21526
+ (0, roosterjs_editor_dom_1.unwrap)(codeParent);
21527
+ }
21528
+ if ((0, roosterjs_editor_dom_1.safeInstanceOf)(currentContainer.parentElement, 'HTMLPreElement')) {
21529
+ var preParent = (0, roosterjs_editor_dom_1.splitBalancedNodeRange)(currentContainer);
21530
+ if (preParent) {
21531
+ (0, roosterjs_editor_dom_1.unwrap)(preParent);
21532
+ }
21533
+ }
21534
+ }
21535
+ else {
21536
+ //Content model
21537
+ (0, roosterjs_editor_dom_1.unwrap)(codeChild);
21538
+ }
21539
+ editor.select(currentContainer, 0 /* Begin */);
21540
+ }
21541
+ exports.CodeFeatures = {
21542
+ removeCodeWhenEnterOnEmptyLine: RemoveCodeWhenEnterOnEmptyLine,
21543
+ removeCodeWhenBackspaceOnEmptyFirstLine: RemoveCodeWhenBackspaceOnEmptyFirstLine,
21544
+ };
21545
+
21546
+
21225
21547
  /***/ }),
21226
21548
 
21227
21549
  /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/cursorFeatures.ts":
@@ -21240,7 +21562,7 @@ var NoCycleCursorMove = {
21240
21562
  keys: [37 /* LEFT */, 39 /* RIGHT */],
21241
21563
  allowFunctionKeys: true,
21242
21564
  shouldHandleEvent: function (event, editor, ctrlOrMeta) {
21243
- var range;
21565
+ var range = null;
21244
21566
  var position;
21245
21567
  if (!ctrlOrMeta ||
21246
21568
  !(range = editor.getSelectionRange()) ||
@@ -21280,6 +21602,7 @@ exports.CursorFeatures = {
21280
21602
  Object.defineProperty(exports, "__esModule", { value: true });
21281
21603
  exports.EntityFeatures = void 0;
21282
21604
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
21605
+ var roosterjs_editor_dom_2 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
21283
21606
  /**
21284
21607
  * A content edit feature to trigger EntityOperation event with operation "Click" when user
21285
21608
  * clicks on a readonly entity.
@@ -21303,13 +21626,13 @@ var EscapeFromEntityFeature = {
21303
21626
  },
21304
21627
  };
21305
21628
  function cacheGetReadonlyEntityElement(event, editor, operation) {
21306
- var element = (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'READONLY_ENTITY_ELEMENT', function () {
21629
+ var element = (0, roosterjs_editor_dom_2.cacheGetEventData)(event, 'READONLY_ENTITY_ELEMENT', function () {
21307
21630
  var node = event.rawEvent.target;
21308
- var entityElement = node && editor.getElementAtCursor((0, roosterjs_editor_dom_1.getEntitySelector)(), node);
21631
+ var entityElement = node && editor.getElementAtCursor((0, roosterjs_editor_dom_2.getEntitySelector)(), node);
21309
21632
  return entityElement && !entityElement.isContentEditable ? entityElement : null;
21310
21633
  });
21311
21634
  if (element && operation !== undefined) {
21312
- var entity = (0, roosterjs_editor_dom_1.getEntityFromElement)(element);
21635
+ var entity = (0, roosterjs_editor_dom_2.getEntityFromElement)(element);
21313
21636
  if (entity) {
21314
21637
  editor.triggerPluginEvent(15 /* EntityOperation */, {
21315
21638
  operation: operation,
@@ -21338,7 +21661,7 @@ var EnterBeforeReadonlyEntityFeature = {
21338
21661
  if (!range) {
21339
21662
  return;
21340
21663
  }
21341
- var node = roosterjs_editor_dom_1.Position.getEnd(range).normalize().node;
21664
+ var node = roosterjs_editor_dom_2.Position.getEnd(range).normalize().node;
21342
21665
  var br = editor.getDocument().createElement('BR');
21343
21666
  (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(br, node.nextSibling);
21344
21667
  var block = editor.getBlockElementAtNode(node);
@@ -21380,13 +21703,13 @@ var DeleteBeforeEntityFeature = {
21380
21703
  },
21381
21704
  };
21382
21705
  function cacheGetNeighborEntityElement(event, editor, isNext, collapseOnly, operation) {
21383
- var element = (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'NEIGHBOR_ENTITY_ELEMENT_' + isNext + '_' + collapseOnly, function () {
21706
+ var element = (0, roosterjs_editor_dom_2.cacheGetEventData)(event, 'NEIGHBOR_ENTITY_ELEMENT_' + isNext + '_' + collapseOnly, function () {
21384
21707
  var range = editor.getSelectionRange();
21385
21708
  if (!range || (collapseOnly && !range.collapsed)) {
21386
21709
  return null;
21387
21710
  }
21388
21711
  range.commonAncestorContainer.normalize();
21389
- var pos = roosterjs_editor_dom_1.Position.getEnd(range).normalize();
21712
+ var pos = roosterjs_editor_dom_2.Position.getEnd(range).normalize();
21390
21713
  var isAtBeginOrEnd = pos.offset == 0 || pos.isAtEnd;
21391
21714
  var entityNode = null;
21392
21715
  if (isAtBeginOrEnd) {
@@ -21405,12 +21728,12 @@ function cacheGetNeighborEntityElement(event, editor, isNext, collapseOnly, oper
21405
21728
  node = null;
21406
21729
  }
21407
21730
  }
21408
- entityNode = node && editor.getElementAtCursor((0, roosterjs_editor_dom_1.getEntitySelector)(), node);
21731
+ entityNode = node && editor.getElementAtCursor((0, roosterjs_editor_dom_2.getEntitySelector)(), node);
21409
21732
  }
21410
21733
  return entityNode;
21411
21734
  });
21412
21735
  if (element && operation !== undefined) {
21413
- var entity = (0, roosterjs_editor_dom_1.getEntityFromElement)(element);
21736
+ var entity = (0, roosterjs_editor_dom_2.getEntityFromElement)(element);
21414
21737
  if (entity) {
21415
21738
  triggerOperation(entity, editor, operation, event);
21416
21739
  }
@@ -21423,15 +21746,17 @@ function cacheGetNeighborEntityElement(event, editor, isNext, collapseOnly, oper
21423
21746
  */
21424
21747
  var MoveBetweenDelimitersFeature = {
21425
21748
  keys: [39 /* RIGHT */, 37 /* LEFT */],
21749
+ allowFunctionKeys: true,
21426
21750
  shouldHandleEvent: function (event, editor) {
21427
- if (!editor.isFeatureEnabled("InlineEntityReadOnlyDelimiters" /* InlineEntityReadOnlyDelimiters */)) {
21751
+ if (event.rawEvent.altKey ||
21752
+ !editor.isFeatureEnabled("InlineEntityReadOnlyDelimiters" /* InlineEntityReadOnlyDelimiters */)) {
21428
21753
  return false;
21429
21754
  }
21430
21755
  var element = editor.getElementAtCursor();
21431
21756
  if (!element) {
21432
21757
  return false;
21433
21758
  }
21434
- var isRTL = (0, roosterjs_editor_dom_1.getComputedStyle)(element, 'direction') === 'rtl';
21759
+ var isRTL = (0, roosterjs_editor_dom_2.getComputedStyle)(element, 'direction') === 'rtl';
21435
21760
  var shouldCheckBefore = isRTL == (event.rawEvent.which === 37 /* LEFT */);
21436
21761
  return getIsDelimiterAtCursor(event, editor, shouldCheckBefore);
21437
21762
  },
@@ -21441,8 +21766,8 @@ var MoveBetweenDelimitersFeature = {
21441
21766
  if (!delimiter) {
21442
21767
  return;
21443
21768
  }
21444
- var _a = getRelatedElements(delimiter, checkBefore), delimiterPair = _a.delimiterPair, entity = _a.entity;
21445
- if (delimiterPair && entity && (0, roosterjs_editor_dom_1.matchesSelector)(entity, (0, roosterjs_editor_dom_1.getEntitySelector)())) {
21769
+ var _a = getRelatedElements(delimiter, checkBefore, editor), delimiterPair = _a.delimiterPair, entity = _a.entity;
21770
+ if (delimiterPair && entity && (0, roosterjs_editor_dom_2.matchesSelector)(entity, (0, roosterjs_editor_dom_2.getEntitySelector)())) {
21446
21771
  event.rawEvent.preventDefault();
21447
21772
  editor.runAsync(function () {
21448
21773
  var positionType = checkBefore
@@ -21450,7 +21775,7 @@ var MoveBetweenDelimitersFeature = {
21450
21775
  ? -3 /* After */
21451
21776
  : -1 /* End */
21452
21777
  : -2 /* Before */;
21453
- var position = new roosterjs_editor_dom_1.Position(delimiterPair, positionType);
21778
+ var position = new roosterjs_editor_dom_2.Position(delimiterPair, positionType);
21454
21779
  if (event.rawEvent.shiftKey) {
21455
21780
  var selection = delimiterPair.ownerDocument.getSelection();
21456
21781
  selection === null || selection === void 0 ? void 0 : selection.extend(position.node, position.offset);
@@ -21504,51 +21829,65 @@ function getIsDelimiterAtCursor(event, editor, checkBefore) {
21504
21829
  : position.node == position.element
21505
21830
  ? position.element.childNodes.item(position.offset)
21506
21831
  : position.element;
21507
- var searcher = editor.getContentSearcherOfCursor(event);
21508
21832
  var data = checkBefore
21509
21833
  ? {
21510
21834
  class: "entityDelimiterBefore" /* DELIMITER_BEFORE */,
21511
21835
  pairClass: "entityDelimiterAfter" /* DELIMITER_AFTER */,
21512
- getDelimiterPair: function (element) { var _a; return (_a = element.nextElementSibling) === null || _a === void 0 ? void 0 : _a.nextElementSibling; },
21513
- getNextSibling: function () {
21514
- var _a;
21515
- return (_a = searcher === null || searcher === void 0 ? void 0 : searcher.getInlineElementAfter()) === null || _a === void 0 ? void 0 : _a.getContainerNode();
21516
- },
21517
21836
  isAtEndOrBeginning: position.isAtEnd,
21518
21837
  }
21519
21838
  : {
21520
21839
  class: "entityDelimiterAfter" /* DELIMITER_AFTER */,
21521
21840
  pairClass: "entityDelimiterBefore" /* DELIMITER_BEFORE */,
21522
- getDelimiterPair: function (element) { var _a; return (_a = element.previousElementSibling) === null || _a === void 0 ? void 0 : _a.previousElementSibling; },
21523
- getNextSibling: function () {
21524
- var _a;
21525
- return (_a = searcher === null || searcher === void 0 ? void 0 : searcher.getInlineElementBefore()) === null || _a === void 0 ? void 0 : _a.getContainerNode();
21526
- },
21527
21841
  isAtEndOrBeginning: position.offset == 0,
21528
21842
  };
21529
- var sibling = data.getNextSibling();
21843
+ var sibling = getNextSibling(editor, focusedElement, checkBefore);
21530
21844
  if (data.isAtEndOrBeginning && sibling) {
21531
21845
  var elAtCursor = editor.getElementAtCursor('.' + data.class, sibling);
21532
21846
  if (elAtCursor && !!shouldHandle(elAtCursor)) {
21533
21847
  return true;
21534
21848
  }
21535
21849
  }
21536
- var entityAtCursor = editor.getElementAtCursor('.' + data.class, focusedElement);
21850
+ var entityAtCursor = focusedElement && editor.getElementAtCursor('.' + data.class, focusedElement);
21537
21851
  return !!shouldHandle(entityAtCursor);
21538
21852
  function shouldHandle(element) {
21539
- var _a;
21540
- return (element &&
21541
- (((_a = data.getDelimiterPair(element)) === null || _a === void 0 ? void 0 : _a.className) || '').indexOf(data.pairClass) > -1 &&
21853
+ if (!element) {
21854
+ return false;
21855
+ }
21856
+ var delimiterPair = getRelatedElements(element, checkBefore, editor).delimiterPair;
21857
+ return (delimiterPair &&
21858
+ (delimiterPair.className || '').indexOf(data.pairClass) > -1 &&
21542
21859
  cacheDelimiter(event, checkBefore, element));
21543
21860
  }
21544
21861
  }
21862
+ function getNextSibling(editor, element, checkBefore) {
21863
+ var traverser = getBlockTraverser(editor, element);
21864
+ if (!traverser) {
21865
+ return undefined;
21866
+ }
21867
+ var traverseFn = function (t) {
21868
+ return checkBefore ? t.getNextInlineElement() : t.getPreviousInlineElement();
21869
+ };
21870
+ var currentInline = traverser.currentInlineElement;
21871
+ while (currentInline && currentInline.getContainerNode() === element) {
21872
+ currentInline = traverseFn(traverser);
21873
+ }
21874
+ return currentInline === null || currentInline === void 0 ? void 0 : currentInline.getContainerNode();
21875
+ }
21876
+ function getBlockTraverser(editor, element) {
21877
+ var _a;
21878
+ if (!element) {
21879
+ return undefined;
21880
+ }
21881
+ var blockElement = (_a = editor.getBlockElementAtNode(element)) === null || _a === void 0 ? void 0 : _a.getStartNode();
21882
+ return blockElement ? roosterjs_editor_dom_1.ContentTraverser.createBodyTraverser(blockElement, element) : undefined;
21883
+ }
21545
21884
  function cacheDelimiter(event, checkBefore, delimiter) {
21546
- return (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'delimiter_cache_key_' + checkBefore, function () { return delimiter; });
21885
+ return (0, roosterjs_editor_dom_2.cacheGetEventData)(event, 'delimiter_cache_key_' + checkBefore, function () { return delimiter; });
21547
21886
  }
21548
21887
  function cacheEntityBetweenDelimiter(event, editor, checkBefore, entity, operation) {
21549
- var element = (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'entity_delimiter_cache_key_' + checkBefore, function () { return entity && editor.getElementAtCursor((0, roosterjs_editor_dom_1.getEntitySelector)(), entity); });
21888
+ var element = (0, roosterjs_editor_dom_2.cacheGetEventData)(event, 'entity_delimiter_cache_key_' + checkBefore, function () { return entity && editor.getElementAtCursor((0, roosterjs_editor_dom_2.getEntitySelector)(), entity); });
21550
21889
  if (element && operation !== undefined) {
21551
- var entity_1 = (0, roosterjs_editor_dom_1.getEntityFromElement)(element);
21890
+ var entity_1 = (0, roosterjs_editor_dom_2.getEntityFromElement)(element);
21552
21891
  if (entity_1) {
21553
21892
  triggerOperation(entity_1, editor, operation, event);
21554
21893
  }
@@ -21563,7 +21902,7 @@ function triggerOperation(entity, editor, operation, event) {
21563
21902
  entity: entity,
21564
21903
  });
21565
21904
  if (entity.isReadonly &&
21566
- !(0, roosterjs_editor_dom_1.isBlockElement)(entity.wrapper) &&
21905
+ !(0, roosterjs_editor_dom_2.isBlockElement)(entity.wrapper) &&
21567
21906
  editor.isFeatureEnabled("InlineEntityReadOnlyDelimiters" /* InlineEntityReadOnlyDelimiters */)) {
21568
21907
  if (event.rawEvent.defaultPrevented) {
21569
21908
  editor.runAsync(function () {
@@ -21571,41 +21910,58 @@ function triggerOperation(entity, editor, operation, event) {
21571
21910
  removeDelimiters(nextElementSibling, previousElementSibling);
21572
21911
  }
21573
21912
  else {
21574
- var delimiterAfter = (0, roosterjs_editor_dom_1.addDelimiters)(entity.wrapper)[0];
21913
+ var delimiterAfter = (0, roosterjs_editor_dom_2.addDelimiters)(entity.wrapper)[0];
21575
21914
  if (delimiterAfter) {
21576
21915
  editor.select(delimiterAfter, -3 /* After */);
21577
21916
  }
21578
21917
  }
21579
21918
  });
21580
21919
  }
21581
- else if ((0, roosterjs_editor_dom_1.getDelimiterFromElement)(nextElementSibling) &&
21582
- (0, roosterjs_editor_dom_1.getDelimiterFromElement)(previousElementSibling)) {
21583
- editor.select((0, roosterjs_editor_dom_1.createRange)(previousElementSibling, nextElementSibling));
21920
+ else if ((0, roosterjs_editor_dom_2.getDelimiterFromElement)(nextElementSibling) &&
21921
+ (0, roosterjs_editor_dom_2.getDelimiterFromElement)(previousElementSibling)) {
21922
+ editor.select((0, roosterjs_editor_dom_2.createRange)(previousElementSibling, nextElementSibling));
21584
21923
  }
21585
21924
  }
21586
21925
  }
21587
21926
  function removeDelimiters(nextElementSibling, previousElementSibling) {
21588
21927
  [nextElementSibling, previousElementSibling].forEach(function (sibling) {
21589
21928
  var _a;
21590
- if ((0, roosterjs_editor_dom_1.getDelimiterFromElement)(sibling)) {
21929
+ if ((0, roosterjs_editor_dom_2.getDelimiterFromElement)(sibling)) {
21591
21930
  (_a = sibling === null || sibling === void 0 ? void 0 : sibling.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(sibling);
21592
21931
  }
21593
21932
  });
21594
21933
  }
21595
21934
  function cacheGetCheckBefore(event, checkBefore) {
21596
- return !!(0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'Check_Before', function () { return checkBefore; });
21935
+ return !!(0, roosterjs_editor_dom_2.cacheGetEventData)(event, 'Check_Before', function () { return checkBefore; });
21597
21936
  }
21598
- function getRelatedElements(delimiter, checkBefore) {
21599
- var _a, _b;
21600
- var entity;
21601
- var delimiterPair;
21602
- if (checkBefore) {
21603
- entity = delimiter.nextElementSibling;
21604
- delimiterPair = (_a = entity === null || entity === void 0 ? void 0 : entity.nextElementSibling) !== null && _a !== void 0 ? _a : null;
21937
+ function getRelatedElements(delimiter, checkBefore, editor) {
21938
+ var entity = null;
21939
+ var delimiterPair = null;
21940
+ var traverser = getBlockTraverser(editor, delimiter);
21941
+ if (!traverser) {
21942
+ return { delimiterPair: delimiterPair, entity: entity };
21605
21943
  }
21606
- else {
21607
- entity = delimiter.previousElementSibling;
21608
- delimiterPair = (_b = entity === null || entity === void 0 ? void 0 : entity.previousElementSibling) !== null && _b !== void 0 ? _b : null;
21944
+ var selector = "." + (checkBefore ? "entityDelimiterAfter" /* DELIMITER_AFTER */ : "entityDelimiterBefore" /* DELIMITER_BEFORE */);
21945
+ var traverseFn = function (t) {
21946
+ return checkBefore ? t.getNextInlineElement() : t.getPreviousInlineElement();
21947
+ };
21948
+ var getElementFromInline = function (element, selector) {
21949
+ var _a;
21950
+ var node = element === null || element === void 0 ? void 0 : element.getContainerNode();
21951
+ return (_a = (node && editor.getElementAtCursor(selector, node))) !== null && _a !== void 0 ? _a : null;
21952
+ };
21953
+ var entitySelector = (0, roosterjs_editor_dom_2.getEntitySelector)();
21954
+ var current = traverser.currentInlineElement;
21955
+ while (current && (!entity || !delimiterPair)) {
21956
+ entity = entity || getElementFromInline(current, entitySelector);
21957
+ delimiterPair = delimiterPair || getElementFromInline(current, selector);
21958
+ // If we found the entity but the next inline after the entity is not a delimiter,
21959
+ // it means that the delimiter pair got removed or is invalid, return null instead.
21960
+ if (entity && !delimiterPair && !getElementFromInline(current, entitySelector)) {
21961
+ delimiterPair = null;
21962
+ break;
21963
+ }
21964
+ current = traverseFn(traverser);
21609
21965
  }
21610
21966
  return { entity: entity, delimiterPair: delimiterPair };
21611
21967
  }
@@ -21656,8 +22012,10 @@ var shouldHandleIndentationEvent = function (indenting) { return function (event
21656
22012
  cacheGetListElement(event, editor));
21657
22013
  }; };
21658
22014
  var handleIndentationEvent = function (indenting) { return function (event, editor) {
22015
+ var currentElement = null;
21659
22016
  var isRTL = event.rawEvent.keyCode !== 9 /* TAB */ &&
21660
- (0, roosterjs_editor_dom_1.getComputedStyle)(editor.getElementAtCursor(), 'direction') == 'rtl';
22017
+ (currentElement = editor.getElementAtCursor()) &&
22018
+ (0, roosterjs_editor_dom_1.getComputedStyle)(currentElement, 'direction') == 'rtl';
21661
22019
  (0, roosterjs_editor_api_1.setIndentation)(editor, isRTL == indenting ? 1 /* Decrease */ : 0 /* Increase */);
21662
22020
  event.rawEvent.preventDefault();
21663
22021
  }; };
@@ -21665,17 +22023,34 @@ var handleIndentationEvent = function (indenting) { return function (event, edit
21665
22023
  * IndentWhenTab edit feature, provides the ability to indent current list when user press TAB
21666
22024
  */
21667
22025
  var IndentWhenTab = {
21668
- keys: [9 /* TAB */, 39 /* RIGHT */],
22026
+ keys: [9 /* TAB */],
21669
22027
  shouldHandleEvent: shouldHandleIndentationEvent(true),
21670
22028
  handleEvent: handleIndentationEvent(true),
21671
- allowFunctionKeys: true,
21672
- defaultDisabled: roosterjs_editor_dom_1.Browser.isMac,
21673
22029
  };
21674
22030
  /**
21675
22031
  * OutdentWhenShiftTab edit feature, provides the ability to outdent current list when user press Shift+TAB
21676
22032
  */
21677
22033
  var OutdentWhenShiftTab = {
21678
- keys: [9 /* TAB */, 37 /* LEFT */],
22034
+ keys: [9 /* TAB */],
22035
+ shouldHandleEvent: shouldHandleIndentationEvent(false),
22036
+ handleEvent: handleIndentationEvent(false),
22037
+ allowFunctionKeys: true,
22038
+ };
22039
+ /**
22040
+ * indentWhenAltShiftRight edit feature, provides the ability to indent or outdent current list when user press Alt+shift+Right
22041
+ */
22042
+ var IndentWhenAltShiftRight = {
22043
+ keys: [39 /* RIGHT */],
22044
+ shouldHandleEvent: shouldHandleIndentationEvent(true),
22045
+ handleEvent: handleIndentationEvent(true),
22046
+ allowFunctionKeys: true,
22047
+ defaultDisabled: roosterjs_editor_dom_1.Browser.isMac,
22048
+ };
22049
+ /**
22050
+ * outdentWhenAltShiftLeft edit feature, provides the ability to indent or outdent current list when user press Alt+shift+Left
22051
+ */
22052
+ var OutdentWhenAltShiftLeft = {
22053
+ keys: [37 /* LEFT */],
21679
22054
  shouldHandleEvent: shouldHandleIndentationEvent(false),
21680
22055
  handleEvent: handleIndentationEvent(false),
21681
22056
  allowFunctionKeys: true,
@@ -21688,16 +22063,16 @@ var OutdentWhenShiftTab = {
21688
22063
  var MergeInNewLine = {
21689
22064
  keys: [8 /* BACKSPACE */],
21690
22065
  shouldHandleEvent: function (event, editor) {
21691
- var li = editor.getElementAtCursor('LI', null /*startFrom*/, event);
22066
+ var li = editor.getElementAtCursor('LI', undefined /*startFrom*/, event);
21692
22067
  var range = editor.getSelectionRange();
21693
22068
  return li && (range === null || range === void 0 ? void 0 : range.collapsed) && (0, roosterjs_editor_dom_1.isPositionAtBeginningOf)(roosterjs_editor_dom_1.Position.getStart(range), li);
21694
22069
  },
21695
22070
  handleEvent: function (event, editor) {
21696
- var li = editor.getElementAtCursor('LI', null /*startFrom*/, event);
21697
- if (li.previousSibling) {
22071
+ var li = editor.getElementAtCursor('LI', undefined /*startFrom*/, event);
22072
+ if (li === null || li === void 0 ? void 0 : li.previousSibling) {
21698
22073
  (0, roosterjs_editor_api_1.blockFormat)(editor, function (region, start, end) {
21699
- var vList = (0, roosterjs_editor_dom_1.createVListFromRegion)(region, false /*includeSiblingList*/, li);
21700
- if (vList) {
22074
+ var vList = (0, roosterjs_editor_dom_1.createVListFromRegion)(region, false /*includeSiblingList*/, li !== null && li !== void 0 ? li : undefined);
22075
+ if (vList && start && end) {
21701
22076
  vList.setIndentation(start, end, 1 /* Decrease */, true /*softOutdent*/);
21702
22077
  vList.writeBack(editor.isFeatureEnabled("ReuseAllAncestorListElements" /* ReuseAllAncestorListElements */));
21703
22078
  event.rawEvent.preventDefault();
@@ -21717,7 +22092,7 @@ var MergeInNewLine = {
21717
22092
  var OutdentWhenBackOn1stEmptyLine = {
21718
22093
  keys: [8 /* BACKSPACE */],
21719
22094
  shouldHandleEvent: function (event, editor) {
21720
- var li = editor.getElementAtCursor('LI', null /*startFrom*/, event);
22095
+ var li = editor.getElementAtCursor('LI', undefined /*startFrom*/, event);
21721
22096
  return (li &&
21722
22097
  (0, roosterjs_editor_dom_1.isNodeEmpty)(li) &&
21723
22098
  !li.previousSibling &&
@@ -21732,12 +22107,13 @@ var OutdentWhenBackOn1stEmptyLine = {
21732
22107
  var MaintainListChainWhenDelete = {
21733
22108
  keys: [46 /* DELETE */],
21734
22109
  shouldHandleEvent: function (event, editor) {
21735
- var li = editor.getElementAtCursor('LI', null /*startFrom*/, event);
21736
- if (li) {
22110
+ var li = editor.getElementAtCursor('LI', undefined /*startFrom*/, event);
22111
+ var range = editor.getSelectionRange();
22112
+ if (li || !range) {
21737
22113
  return false;
21738
22114
  }
21739
- var isAtEnd = roosterjs_editor_dom_1.Position.getEnd(editor.getSelectionRange()).isAtEnd;
21740
- var nextSibling = isAtEnd ? getCacheNextSibling(event, editor) : null;
22115
+ var isAtEnd = roosterjs_editor_dom_1.Position.getEnd(range).isAtEnd;
22116
+ var nextSibling = isAtEnd ? getCacheNextSibling(event, editor) : undefined;
21741
22117
  var isAtEndAndBeforeLI = editor.getElementAtCursor('LI', nextSibling, event);
21742
22118
  return isAtEndAndBeforeLI;
21743
22119
  },
@@ -21753,11 +22129,11 @@ var MaintainListChainWhenDelete = {
21753
22129
  var OutdentWhenEnterOnEmptyLine = {
21754
22130
  keys: [13 /* ENTER */],
21755
22131
  shouldHandleEvent: function (event, editor) {
21756
- var li = editor.getElementAtCursor('LI', null /*startFrom*/, event);
22132
+ var li = editor.getElementAtCursor('LI', undefined /*startFrom*/, event);
21757
22133
  return !event.rawEvent.shiftKey && li && (0, roosterjs_editor_dom_1.isNodeEmpty)(li);
21758
22134
  },
21759
22135
  handleEvent: function (event, editor) {
21760
- editor.addUndoSnapshot(function () { return toggleListAndPreventDefault(event, editor, false /* includeSiblingLists */); }, null /*changeSource*/, true /*canUndoByBackspace*/);
22136
+ editor.addUndoSnapshot(function () { return toggleListAndPreventDefault(event, editor, false /* includeSiblingLists */); }, undefined /*changeSource*/, true /*canUndoByBackspace*/);
21761
22137
  },
21762
22138
  defaultDisabled: !roosterjs_editor_dom_1.Browser.isIE && !roosterjs_editor_dom_1.Browser.isChrome,
21763
22139
  };
@@ -21779,9 +22155,10 @@ function isAListPattern(textBeforeCursor) {
21779
22155
  var AutoBullet = {
21780
22156
  keys: [32 /* SPACE */],
21781
22157
  shouldHandleEvent: function (event, editor) {
22158
+ var searcher;
21782
22159
  if (!cacheGetListElement(event, editor) &&
21783
- !editor.isFeatureEnabled("AutoFormatList" /* AutoFormatList */)) {
21784
- var searcher = editor.getContentSearcherOfCursor(event);
22160
+ !editor.isFeatureEnabled("AutoFormatList" /* AutoFormatList */) &&
22161
+ (searcher = editor.getContentSearcherOfCursor(event))) {
21785
22162
  var textBeforeCursor = searcher.getSubStringBefore(4);
21786
22163
  // Auto list is triggered if:
21787
22164
  // 1. Text before cursor exactly matches '*', '-' or '1.'
@@ -21797,6 +22174,9 @@ var AutoBullet = {
21797
22174
  var _a;
21798
22175
  var regions;
21799
22176
  var searcher = editor.getContentSearcherOfCursor();
22177
+ if (!searcher) {
22178
+ return;
22179
+ }
21800
22180
  var textBeforeCursor = searcher.getSubStringBefore(4);
21801
22181
  var textRange = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/);
21802
22182
  if (!textRange) {
@@ -21817,7 +22197,7 @@ var AutoBullet = {
21817
22197
  (0, roosterjs_editor_api_1.toggleNumbering)(editor, num);
21818
22198
  }
21819
22199
  (_a = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/)) === null || _a === void 0 ? void 0 : _a.deleteContents();
21820
- }, null /*changeSource*/, true /*canUndoByBackspace*/);
22200
+ }, undefined /*changeSource*/, true /*canUndoByBackspace*/);
21821
22201
  },
21822
22202
  };
21823
22203
  /**
@@ -21839,15 +22219,18 @@ var AutoBulletList = {
21839
22219
  editor.addUndoSnapshot(function () {
21840
22220
  var _a;
21841
22221
  var searcher = editor.getContentSearcherOfCursor();
22222
+ if (!searcher) {
22223
+ return;
22224
+ }
21842
22225
  var textBeforeCursor = searcher.getSubStringBefore(5);
21843
22226
  var textRange = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/);
21844
22227
  var listStyle = (0, getAutoBulletListStyle_1.default)(textBeforeCursor);
21845
22228
  if (textRange) {
21846
22229
  prepareAutoBullet(editor, textRange);
21847
- (0, roosterjs_editor_api_1.toggleBullet)(editor, listStyle, 'autoToggleList' /** apiNameOverride */);
22230
+ (0, roosterjs_editor_api_1.toggleBullet)(editor, listStyle !== null && listStyle !== void 0 ? listStyle : undefined, 'autoToggleList' /** apiNameOverride */);
21848
22231
  }
21849
22232
  (_a = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/)) === null || _a === void 0 ? void 0 : _a.deleteContents();
21850
- }, null /*changeSource*/, true /*canUndoByBackspace*/);
22233
+ }, undefined /*changeSource*/, true /*canUndoByBackspace*/);
21851
22234
  },
21852
22235
  };
21853
22236
  /**
@@ -21867,8 +22250,11 @@ var AutoNumberingList = {
21867
22250
  editor.insertContent('&nbsp;');
21868
22251
  event.rawEvent.preventDefault();
21869
22252
  editor.addUndoSnapshot(function () {
21870
- var _a;
22253
+ var _a, _b;
21871
22254
  var searcher = editor.getContentSearcherOfCursor();
22255
+ if (!searcher) {
22256
+ return;
22257
+ }
21872
22258
  var textBeforeCursor = searcher.getSubStringBefore(5);
21873
22259
  var textRange = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/);
21874
22260
  if (textRange) {
@@ -21876,19 +22262,20 @@ var AutoNumberingList = {
21876
22262
  ? 1
21877
22263
  : parseInt(textBeforeCursor);
21878
22264
  var isLi = getPreviousListItem(editor, textRange);
21879
- var listStyle = (0, getAutoNumberingListStyle_1.default)(textBeforeCursor);
22265
+ var listStyle = (_a = (0, getAutoNumberingListStyle_1.default)(textBeforeCursor)) !== null && _a !== void 0 ? _a : undefined;
21880
22266
  prepareAutoBullet(editor, textRange);
21881
22267
  (0, roosterjs_editor_api_1.toggleNumbering)(editor, isLi && number !== 1 ? undefined : number /** startNumber */, listStyle, 'autoToggleList' /** apiNameOverride */);
21882
22268
  }
21883
- (_a = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/)) === null || _a === void 0 ? void 0 : _a.deleteContents();
21884
- }, null /*changeSource*/, true /*canUndoByBackspace*/);
22269
+ (_b = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/)) === null || _b === void 0 ? void 0 : _b.deleteContents();
22270
+ }, undefined /*changeSource*/, true /*canUndoByBackspace*/);
21885
22271
  },
21886
22272
  };
21887
22273
  var getPreviousListItem = function (editor, textRange) {
22274
+ var _a;
21888
22275
  var blockElement = editor
21889
22276
  .getBodyTraverser(textRange === null || textRange === void 0 ? void 0 : textRange.startContainer)
21890
22277
  .getPreviousBlockElement();
21891
- var previousNode = blockElement === null || blockElement === void 0 ? void 0 : blockElement.getEndNode();
22278
+ var previousNode = (_a = blockElement === null || blockElement === void 0 ? void 0 : blockElement.getEndNode()) !== null && _a !== void 0 ? _a : null;
21892
22279
  return (0, roosterjs_editor_dom_1.getTagOfNode)(previousNode) === 'LI' ? previousNode : undefined;
21893
22280
  };
21894
22281
  var getPreviousListType = function (editor, textRange, listType) {
@@ -21936,13 +22323,14 @@ function getCacheNextSibling(event, editor) {
21936
22323
  var element = (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'nextSibling', function () {
21937
22324
  var _a;
21938
22325
  var range = editor.getSelectionRange();
21939
- var pos = roosterjs_editor_dom_1.Position.getEnd(range).normalize();
21940
- var traverser = editor.getBodyTraverser(pos.node);
22326
+ var pos = range && roosterjs_editor_dom_1.Position.getEnd(range).normalize();
22327
+ var traverser = pos && editor.getBodyTraverser(pos.node);
21941
22328
  return (_a = traverser === null || traverser === void 0 ? void 0 : traverser.getNextBlockElement()) === null || _a === void 0 ? void 0 : _a.getStartNode();
21942
22329
  });
21943
22330
  return element;
21944
22331
  }
21945
22332
  function prepareAutoBullet(editor, range) {
22333
+ var _a;
21946
22334
  var block = editor.getBlockElementAtNode(range.startContainer);
21947
22335
  var endNode = block === null || block === void 0 ? void 0 : block.getEndNode();
21948
22336
  if (endNode && (0, roosterjs_editor_dom_1.getTagOfNode)(endNode) != 'BR') {
@@ -21951,7 +22339,7 @@ function prepareAutoBullet(editor, range) {
21951
22339
  endNode.appendChild(br);
21952
22340
  }
21953
22341
  else {
21954
- endNode.parentNode.insertBefore(br, endNode.nextSibling);
22342
+ (_a = endNode.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(br, endNode.nextSibling);
21955
22343
  }
21956
22344
  editor.select(range.startContainer, range.startOffset);
21957
22345
  }
@@ -21963,19 +22351,22 @@ function toggleListAndPreventDefault(event, editor, includeSiblingLists) {
21963
22351
  var listElement = listInfo[0];
21964
22352
  var tag = (0, roosterjs_editor_dom_1.getTagOfNode)(listElement);
21965
22353
  if (tag == 'UL' || tag == 'OL') {
21966
- (0, roosterjs_editor_api_1.toggleListType)(editor, tag == 'UL' ? 2 /* Unordered */ : 1 /* Ordered */, null /* startNumber */, includeSiblingLists);
22354
+ (0, roosterjs_editor_api_1.toggleListType)(editor, tag == 'UL' ? 2 /* Unordered */ : 1 /* Ordered */, undefined /* startNumber */, includeSiblingLists);
21967
22355
  }
21968
22356
  editor.focus();
21969
22357
  event.rawEvent.preventDefault();
21970
22358
  }
21971
22359
  }
21972
22360
  function cacheGetListElement(event, editor) {
21973
- var li = editor.getElementAtCursor('LI,TABLE', null /*startFrom*/, event);
22361
+ var li = editor.getElementAtCursor('LI,TABLE', undefined /*startFrom*/, event);
21974
22362
  var listElement = li && (0, roosterjs_editor_dom_1.getTagOfNode)(li) == 'LI' && editor.getElementAtCursor('UL,OL', li);
21975
22363
  return listElement ? [listElement, li] : null;
21976
22364
  }
21977
22365
  function shouldTriggerList(event, editor, getListStyle, listType) {
21978
22366
  var searcher = editor.getContentSearcherOfCursor(event);
22367
+ if (!searcher) {
22368
+ return false;
22369
+ }
21979
22370
  var textBeforeCursor = searcher.getSubStringBefore(4);
21980
22371
  var traverser = editor.getBlockTraverser();
21981
22372
  var text = traverser && traverser.currentBlockElement
@@ -21984,9 +22375,9 @@ function shouldTriggerList(event, editor, getListStyle, listType) {
21984
22375
  var isATheBeginning = text && text === textBeforeCursor;
21985
22376
  var listChains = getListChains(editor);
21986
22377
  var textRange = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/);
21987
- var previousListType = getPreviousListType(editor, textRange, listType);
22378
+ var previousListType = textRange && getPreviousListType(editor, textRange, listType);
21988
22379
  var isFirstItem = isFirstItemOfAList(textBeforeCursor);
21989
- var listStyle = getListStyle(textBeforeCursor, listChains, previousListType);
22380
+ var listStyle = getListStyle(textBeforeCursor, listChains, previousListType !== null && previousListType !== void 0 ? previousListType : undefined);
21990
22381
  var shouldTriggerNewListStyle = isFirstItem ||
21991
22382
  !previousListType ||
21992
22383
  previousListType === listStyle ||
@@ -22062,6 +22453,8 @@ exports.ListFeatures = {
22062
22453
  autoNumberingList: AutoNumberingList,
22063
22454
  autoBulletList: AutoBulletList,
22064
22455
  mergeListOnBackspaceAfterList: MergeListOnBackspaceAfterList,
22456
+ outdentWhenAltShiftLeft: OutdentWhenAltShiftLeft,
22457
+ indentWhenAltShiftRight: IndentWhenAltShiftRight,
22065
22458
  };
22066
22459
  function isList(element) {
22067
22460
  return (!!element &&
@@ -22102,8 +22495,8 @@ function generateBasicMarkdownFeature(key, triggerCharacter, elementTag, useShif
22102
22495
  function cacheGetRangeForMarkdownOperation(event, editor, triggerCharacter) {
22103
22496
  return (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'MARKDOWN_RANGE', function () {
22104
22497
  var searcher = editor.getContentSearcherOfCursor(event);
22105
- var startPosition;
22106
- var endPosition;
22498
+ var startPosition = null;
22499
+ var endPosition = null;
22107
22500
  searcher === null || searcher === void 0 ? void 0 : searcher.forEachTextInlineElement(function (textInlineElement) {
22108
22501
  if (endPosition && startPosition) {
22109
22502
  return true;
@@ -22141,12 +22534,15 @@ function cacheGetRangeForMarkdownOperation(event, editor, triggerCharacter) {
22141
22534
  }
22142
22535
  }
22143
22536
  });
22144
- return !!startPosition && !!endPosition && (0, roosterjs_editor_dom_1.createRange)(startPosition, endPosition);
22537
+ return startPosition && endPosition && (0, roosterjs_editor_dom_1.createRange)(startPosition, endPosition);
22145
22538
  });
22146
22539
  }
22147
22540
  function handleMarkdownEvent(event, editor, triggerCharacter, elementTag) {
22148
22541
  editor.addUndoSnapshot(function () {
22149
22542
  var range = cacheGetRangeForMarkdownOperation(event, editor, triggerCharacter);
22543
+ if (!range) {
22544
+ return;
22545
+ }
22150
22546
  var lastTypedTriggerPosition = new roosterjs_editor_dom_1.Position(range.endContainer, -1 /* End */);
22151
22547
  var hasLastTypedTrigger = range.endOffset + 1 <= lastTypedTriggerPosition.offset;
22152
22548
  if (!!range && hasLastTypedTrigger) {
@@ -22154,7 +22550,7 @@ function handleMarkdownEvent(event, editor, triggerCharacter, elementTag) {
22154
22550
  var textContentRange = range.cloneRange();
22155
22551
  textContentRange.setStart(textContentRange.startContainer, textContentRange.startOffset + 1);
22156
22552
  var text = textContentRange.extractContents().textContent;
22157
- var textNode = editor.getDocument().createTextNode(text);
22553
+ var textNode = editor.getDocument().createTextNode(text !== null && text !== void 0 ? text : '');
22158
22554
  // extract content and put it into a new element.
22159
22555
  var elementToWrap = (0, roosterjs_editor_dom_1.wrap)(textNode, elementTag);
22160
22556
  //include last typed character
@@ -22238,7 +22634,7 @@ var UnquoteWhenEnterOnEmptyLine = {
22238
22634
  return !shift && childOfQuote && (0, roosterjs_editor_dom_1.isNodeEmpty)(childOfQuote);
22239
22635
  },
22240
22636
  handleEvent: function (event, editor) {
22241
- return editor.addUndoSnapshot(function () { return splitQuote(event, editor); }, null /*changeSource*/, true /*canUndoByBackspace*/);
22637
+ return editor.addUndoSnapshot(function () { return splitQuote(event, editor); }, undefined /*changeSource*/, true /*canUndoByBackspace*/);
22242
22638
  },
22243
22639
  };
22244
22640
  function cacheGetQuoteChild(event, editor) {
@@ -22260,14 +22656,15 @@ function cacheGetQuoteChild(event, editor) {
22260
22656
  function splitQuote(event, editor) {
22261
22657
  editor.addUndoSnapshot(function () {
22262
22658
  var childOfQuote = cacheGetQuoteChild(event, editor);
22263
- var parent;
22264
- var shouldClearFormat;
22659
+ if (!childOfQuote) {
22660
+ return;
22661
+ }
22265
22662
  if ((0, roosterjs_editor_dom_1.getTagOfNode)(childOfQuote) == QUOTE_TAG) {
22266
22663
  childOfQuote = (0, roosterjs_editor_dom_1.wrap)((0, roosterjs_editor_dom_1.toArray)(childOfQuote.childNodes));
22267
22664
  }
22268
- parent = (0, roosterjs_editor_dom_1.splitBalancedNodeRange)(childOfQuote);
22269
- shouldClearFormat = isStyledBlockquote(parent);
22270
- var newParent = (0, roosterjs_editor_dom_1.unwrap)(parent);
22665
+ var parent = (0, roosterjs_editor_dom_1.splitBalancedNodeRange)(childOfQuote);
22666
+ var shouldClearFormat = !!parent && isStyledBlockquote(parent);
22667
+ var newParent = parent && (0, roosterjs_editor_dom_1.unwrap)(parent);
22271
22668
  editor.select(childOfQuote, 0 /* Begin */);
22272
22669
  if (shouldClearFormat) {
22273
22670
  if ((0, roosterjs_editor_dom_1.safeInstanceOf)(newParent, 'HTMLLIElement')) {
@@ -22433,7 +22830,8 @@ var InsertLineBeforeStructuredNodeFeature = {
22433
22830
  var element = cacheGetStructuredElement(event, editor);
22434
22831
  var div = (0, roosterjs_editor_dom_1.createElement)(1 /* EmptyLine */, editor.getDocument());
22435
22832
  editor.addUndoSnapshot(function () {
22436
- element.parentNode.insertBefore(div, element);
22833
+ var _a;
22834
+ (_a = element === null || element === void 0 ? void 0 : element.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(div, element);
22437
22835
  // Select the new line when we are in table. This is the same behavior with Word
22438
22836
  if ((0, roosterjs_editor_dom_1.getTagOfNode)(element) == 'TABLE') {
22439
22837
  editor.select(new roosterjs_editor_dom_1.Position(div, 0 /* Begin */).normalize());
@@ -22491,21 +22889,26 @@ var TabInTable = {
22491
22889
  return cacheGetTableCell(event, editor) && !cacheIsWholeTableSelected(event, editor);
22492
22890
  },
22493
22891
  handleEvent: function (event, editor) {
22892
+ var _a, _b, _c;
22494
22893
  var shift = event.rawEvent.shiftKey;
22495
22894
  var td = cacheGetTableCell(event, editor);
22895
+ if (!td) {
22896
+ return;
22897
+ }
22496
22898
  var vtable = cacheVTable(event, td);
22497
- for (var step = shift ? -1 : 1, row = vtable.row, col = vtable.col + step;; col += step) {
22498
- if (col < 0 || col >= vtable.cells[row].length) {
22899
+ for (var step = shift ? -1 : 1, row = (_a = vtable.row) !== null && _a !== void 0 ? _a : 0, col = ((_b = vtable.col) !== null && _b !== void 0 ? _b : 0) + step;; col += step) {
22900
+ var tableCells = (_c = vtable.cells) !== null && _c !== void 0 ? _c : [];
22901
+ if (col < 0 || col >= tableCells[row].length) {
22499
22902
  row += step;
22500
22903
  if (row < 0) {
22501
22904
  editor.select(vtable.table, -2 /* Before */);
22502
22905
  break;
22503
22906
  }
22504
- else if (row >= vtable.cells.length) {
22907
+ else if (row >= tableCells.length) {
22505
22908
  (0, roosterjs_editor_api_1.editTable)(editor, 1 /* InsertBelow */);
22506
22909
  break;
22507
22910
  }
22508
- col = shift ? vtable.cells[row].length - 1 : 0;
22911
+ col = shift ? tableCells[row].length - 1 : 0;
22509
22912
  }
22510
22913
  var cell = vtable.getCell(row, col);
22511
22914
  if (cell.td) {
@@ -22531,6 +22934,9 @@ var IndentTableOnTab = {
22531
22934
  var shift = event.rawEvent.shiftKey;
22532
22935
  var selection = editor.getSelectionRangeEx();
22533
22936
  var td = cacheGetTableCell(event, editor);
22937
+ if (!td) {
22938
+ return;
22939
+ }
22534
22940
  var vtable = cacheVTable(event, td);
22535
22941
  if (shift && editor.getElementAtCursor('blockquote', vtable.table, event)) {
22536
22942
  (0, roosterjs_editor_api_1.setIndentation)(editor, 1 /* Decrease */);
@@ -22538,7 +22944,9 @@ var IndentTableOnTab = {
22538
22944
  else if (!shift) {
22539
22945
  (0, roosterjs_editor_api_1.setIndentation)(editor, 0 /* Increase */);
22540
22946
  }
22541
- editor.select(selection.table, selection.coordinates);
22947
+ if (selection.coordinates) {
22948
+ editor.select(selection.table, selection.coordinates);
22949
+ }
22542
22950
  });
22543
22951
  },
22544
22952
  };
@@ -22552,8 +22960,11 @@ var UpDownInTable = {
22552
22960
  return cacheGetTableCell(event, editor) && !cacheIsWholeTableSelected(event, editor);
22553
22961
  },
22554
22962
  handleEvent: function (event, editor) {
22555
- var _a;
22963
+ var _a, _b, _c;
22556
22964
  var td = cacheGetTableCell(event, editor);
22965
+ if (!td) {
22966
+ return;
22967
+ }
22557
22968
  var vtable = new roosterjs_editor_dom_1.VTable(td);
22558
22969
  var isUp = event.rawEvent.which == 38 /* UP */;
22559
22970
  var step = isUp ? -1 : 1;
@@ -22562,8 +22973,8 @@ var UpDownInTable = {
22562
22973
  var targetTd = null;
22563
22974
  if (selection) {
22564
22975
  var anchorNode_1 = selection.anchorNode, anchorOffset_1 = selection.anchorOffset;
22565
- for (var row = vtable.row; row >= 0 && row < vtable.cells.length; row += step) {
22566
- var cell = vtable.getCell(row, vtable.col);
22976
+ for (var row = (_b = vtable.row) !== null && _b !== void 0 ? _b : 0; row >= 0 && vtable.cells && row < vtable.cells.length; row += step) {
22977
+ var cell = vtable.getCell(row, (_c = vtable.col) !== null && _c !== void 0 ? _c : 0);
22567
22978
  if (cell.td && cell.td != td) {
22568
22979
  targetTd = cell.td;
22569
22980
  break;
@@ -22584,7 +22995,9 @@ var UpDownInTable = {
22584
22995
  ? new roosterjs_editor_dom_1.Position(newPos.node, newPos.isAtEnd ? -3 /* After */ : -2 /* Before */)
22585
22996
  : newPos;
22586
22997
  var selection_1 = (_a = editor.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
22587
- selection_1 === null || selection_1 === void 0 ? void 0 : selection_1.setBaseAndExtent(anchorNode_1, anchorOffset_1, newPos.node, newPos.offset);
22998
+ if (anchorNode_1) {
22999
+ selection_1 === null || selection_1 === void 0 ? void 0 : selection_1.setBaseAndExtent(anchorNode_1, anchorOffset_1, newPos.node, newPos.offset);
23000
+ }
22588
23001
  }
22589
23002
  else {
22590
23003
  editor.select(newPos.normalize());
@@ -22607,6 +23020,9 @@ var DeleteTableWithBackspace = {
22607
23020
  },
22608
23021
  handleEvent: function (event, editor) {
22609
23022
  var td = cacheGetTableCell(event, editor);
23023
+ if (!td) {
23024
+ return;
23025
+ }
22610
23026
  var vtable = new roosterjs_editor_dom_1.VTable(td);
22611
23027
  vtable.edit(4 /* DeleteTable */);
22612
23028
  vtable.writeBack();
@@ -22622,9 +23038,13 @@ function cacheGetTableCell(event, editor) {
22622
23038
  function cacheIsWholeTableSelected(event, editor) {
22623
23039
  return (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'WHOLE_TABLE_SELECTED_FOR_FEATURES', function () {
22624
23040
  var td = cacheGetTableCell(event, editor);
23041
+ if (!td) {
23042
+ return false;
23043
+ }
22625
23044
  var vtable = cacheVTable(event, td);
22626
23045
  var selection = editor.getSelectionRangeEx();
22627
23046
  return (selection.type == 1 /* TableSelection */ &&
23047
+ selection.coordinates &&
22628
23048
  (0, roosterjs_editor_dom_1.isWholeTableSelected)(vtable, selection.coordinates));
22629
23049
  });
22630
23050
  }
@@ -22674,7 +23094,7 @@ var IndentWhenTabText = {
22674
23094
  if (editor.isFeatureEnabled("TabKeyTextFeatures" /* TabKeyTextFeatures */) &&
22675
23095
  !event.rawEvent.shiftKey) {
22676
23096
  var activeElement = editor.getDocument().activeElement;
22677
- var listOrTable = editor.getElementAtCursor('LI,TABLE', null /*startFrom*/, event);
23097
+ var listOrTable = editor.getElementAtCursor('LI,TABLE', undefined /*startFrom*/, event);
22678
23098
  var entity = editor.getElementAtCursor((0, roosterjs_editor_dom_1.getEntitySelector)(), undefined /*startFrom*/, event);
22679
23099
  return (!listOrTable &&
22680
23100
  (entity ? entity.isContentEditable : activeElement.isContentEditable));
@@ -22718,8 +23138,8 @@ var OutdentWhenTabText = {
22718
23138
  var selection = editor.getSelectionRangeEx();
22719
23139
  return (selection.type == 0 /* Normal */ &&
22720
23140
  !selection.areAllCollapsed &&
22721
- editor.getElementAtCursor('blockquote', null, event) &&
22722
- !editor.getElementAtCursor('LI,TABLE', null /*startFrom*/, event) &&
23141
+ editor.getElementAtCursor('blockquote', undefined, event) &&
23142
+ !editor.getElementAtCursor('LI,TABLE', undefined /*startFrom*/, event) &&
22723
23143
  shouldSetIndentation(editor, selection.ranges[0]));
22724
23144
  }
22725
23145
  return false;
@@ -22783,9 +23203,12 @@ function isRangeEmpty(range) {
22783
23203
  function insertTab(editor, event) {
22784
23204
  var span = editor.getDocument().createElement('span');
22785
23205
  var searcher = editor.getContentSearcherOfCursor(event);
23206
+ if (!searcher) {
23207
+ return;
23208
+ }
22786
23209
  var charsBefore = searcher.getSubStringBefore(Number.MAX_SAFE_INTEGER);
22787
23210
  var numberOfChars = TAB_SPACES - (charsBefore.length % TAB_SPACES);
22788
- var span2;
23211
+ var span2 = null;
22789
23212
  var textContent = '';
22790
23213
  for (var index = 0; index < numberOfChars; index++) {
22791
23214
  textContent += '&ensp;';
@@ -22842,7 +23265,8 @@ var shortcutFeatures_1 = __webpack_require__(/*! ./features/shortcutFeatures */
22842
23265
  var structuredNodeFeatures_1 = __webpack_require__(/*! ./features/structuredNodeFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/structuredNodeFeatures.ts");
22843
23266
  var tableFeatures_1 = __webpack_require__(/*! ./features/tableFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/tableFeatures.ts");
22844
23267
  var textFeatures_1 = __webpack_require__(/*! ./features/textFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/textFeatures.ts");
22845
- var allFeatures = __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, listFeatures_1.ListFeatures), quoteFeatures_1.QuoteFeatures), tableFeatures_1.TableFeatures), structuredNodeFeatures_1.StructuredNodeFeatures), autoLinkFeatures_1.AutoLinkFeatures), shortcutFeatures_1.ShortcutFeatures), cursorFeatures_1.CursorFeatures), markdownFeatures_1.MarkdownFeatures), entityFeatures_1.EntityFeatures), textFeatures_1.TextFeatures);
23268
+ var codeFeatures_1 = __webpack_require__(/*! ./features/codeFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/codeFeatures.ts");
23269
+ var allFeatures = __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, listFeatures_1.ListFeatures), quoteFeatures_1.QuoteFeatures), tableFeatures_1.TableFeatures), structuredNodeFeatures_1.StructuredNodeFeatures), autoLinkFeatures_1.AutoLinkFeatures), shortcutFeatures_1.ShortcutFeatures), cursorFeatures_1.CursorFeatures), markdownFeatures_1.MarkdownFeatures), entityFeatures_1.EntityFeatures), textFeatures_1.TextFeatures), codeFeatures_1.CodeFeatures);
22846
23270
  /**
22847
23271
  * Get all content edit features provided by roosterjs
22848
23272
  */
@@ -22978,7 +23402,8 @@ var identifyNumberingType = function (text, previousListStyle) {
22978
23402
  return 1 /* Decimal */;
22979
23403
  }
22980
23404
  else if (/[a-z]+/g.test(text)) {
22981
- if ((lowerRomanTypes.indexOf(previousListStyle) > -1 &&
23405
+ if ((previousListStyle != undefined &&
23406
+ lowerRomanTypes.indexOf(previousListStyle) > -1 &&
22982
23407
  lowerRomanNumbers.indexOf(text[0]) > -1) ||
22983
23408
  (!previousListStyle && text === 'i')) {
22984
23409
  return 4 /* LowerRoman */;
@@ -22988,7 +23413,8 @@ var identifyNumberingType = function (text, previousListStyle) {
22988
23413
  }
22989
23414
  }
22990
23415
  else if (/[A-Z]+/g.test(text)) {
22991
- if ((upperRomanTypes.indexOf(previousListStyle) > -1 &&
23416
+ if ((previousListStyle != undefined &&
23417
+ upperRomanTypes.indexOf(previousListStyle) > -1 &&
22992
23418
  upperRomanNumbers.indexOf(text[0]) > -1) ||
22993
23419
  (!previousListStyle && text === 'I')) {
22994
23420
  return 5 /* UpperRoman */;
@@ -23902,7 +24328,7 @@ var ImageEdit = /** @class */ (function () {
23902
24328
  }
23903
24329
  var viewport = (_b = _this.editor) === null || _b === void 0 ? void 0 : _b.getVisibleViewport();
23904
24330
  if (rotateHandle && rotateCenter && viewport) {
23905
- (0, Rotator_1.updateRotateHandlePosition)(_this.editInfo, viewport, marginVertical, rotateCenter, rotateHandle);
24331
+ (0, Rotator_1.updateRotateHandlePosition)(viewport, rotateCenter, rotateHandle);
23906
24332
  }
23907
24333
  updateHandleCursor(resizeHandles, angleRad);
23908
24334
  }
@@ -24045,6 +24471,54 @@ var ImageEdit = /** @class */ (function () {
24045
24471
  this.editor.select(this.image);
24046
24472
  }
24047
24473
  };
24474
+ /**
24475
+ * Flip the image.
24476
+ * @param image The image to be flipped
24477
+ * @param direction
24478
+ */
24479
+ ImageEdit.prototype.flipImage = function (image, direction) {
24480
+ var _a;
24481
+ this.image = image;
24482
+ this.editInfo = (0, editInfo_1.getEditInfoFromImage)(image);
24483
+ var angleRad = this.editInfo.angleRad;
24484
+ var isInVerticalPostion = (angleRad >= Math.PI / 2 && angleRad < (3 * Math.PI) / 4) ||
24485
+ (angleRad <= -Math.PI / 2 && angleRad > (-3 * Math.PI) / 4);
24486
+ if (isInVerticalPostion) {
24487
+ if (direction === 'horizontal') {
24488
+ this.editInfo.flippedVertical = !this.editInfo.flippedVertical;
24489
+ }
24490
+ else {
24491
+ this.editInfo.flippedHorizontal = !this.editInfo.flippedHorizontal;
24492
+ }
24493
+ }
24494
+ else {
24495
+ if (direction === 'vertical') {
24496
+ this.editInfo.flippedVertical = !this.editInfo.flippedVertical;
24497
+ }
24498
+ else {
24499
+ this.editInfo.flippedHorizontal = !this.editInfo.flippedHorizontal;
24500
+ }
24501
+ }
24502
+ this.createWrapper(4 /* Rotate */);
24503
+ this.updateWrapper();
24504
+ this.setEditingImage(null);
24505
+ (_a = this.editor) === null || _a === void 0 ? void 0 : _a.select(image);
24506
+ };
24507
+ /**
24508
+ * Rotate the image in radian angle.
24509
+ * @param image The image to be rotated
24510
+ * @param angleRad The angle in radian that the image must be rotated.
24511
+ */
24512
+ ImageEdit.prototype.rotateImage = function (image, angleRad) {
24513
+ var _a;
24514
+ this.image = image;
24515
+ this.editInfo = (0, editInfo_1.getEditInfoFromImage)(image);
24516
+ this.editInfo.angleRad = this.editInfo.angleRad + angleRad;
24517
+ this.createWrapper(4 /* Rotate */);
24518
+ this.updateWrapper();
24519
+ this.setEditingImage(null);
24520
+ (_a = this.editor) === null || _a === void 0 ? void 0 : _a.select(image);
24521
+ };
24048
24522
  /**
24049
24523
  * Create editing wrapper for the image
24050
24524
  */
@@ -24055,6 +24529,7 @@ var ImageEdit = /** @class */ (function () {
24055
24529
  //Clone the image and insert the clone in a entity
24056
24530
  this.clonedImage = this.image.cloneNode(true);
24057
24531
  this.clonedImage.removeAttribute('id');
24532
+ this.clonedImage.style.removeProperty('max-width');
24058
24533
  this.wrapper = (0, roosterjs_editor_dom_1.createElement)(6 /* ImageEditWrapper */, this.image.ownerDocument);
24059
24534
  (_b = (_a = this.wrapper) === null || _a === void 0 ? void 0 : _a.firstChild) === null || _b === void 0 ? void 0 : _b.appendChild(this.clonedImage);
24060
24535
  this.wrapper.style.display = roosterjs_editor_dom_1.Browser.isSafari ? 'inline-block' : 'inline-flex';
@@ -24063,6 +24538,7 @@ var ImageEdit = /** @class */ (function () {
24063
24538
  // Set image src to original src to help show editing UI, also it will be used when regenerate image dataURL after editing
24064
24539
  if (this.clonedImage) {
24065
24540
  this.clonedImage.src = this.editInfo.src;
24541
+ setFlipped(this.clonedImage, this.editInfo.flippedHorizontal, this.editInfo.flippedVertical);
24066
24542
  this.clonedImage.style.position = 'absolute';
24067
24543
  }
24068
24544
  // Get HTML for all edit elements (resize handle, rotate handle, crop handle and overlay, ...) and create HTML element
@@ -24220,6 +24696,9 @@ function getColorString(color, isDarkMode) {
24220
24696
  }
24221
24697
  return isDarkMode ? color.darkModeColor.trim() : color.lightModeColor.trim();
24222
24698
  }
24699
+ function setFlipped(element, flipppedHorizontally, flipppedVertically) {
24700
+ element.style.transform = "scale(" + (flipppedHorizontally ? '-1' : '1') + ", " + (flipppedVertically ? '-1' : '1') + ")";
24701
+ }
24223
24702
 
24224
24703
 
24225
24704
  /***/ }),
@@ -24362,6 +24841,7 @@ function resizeByPercentage(editor, image, percentage, minWidth, minHeight) {
24362
24841
  editor.addUndoSnapshot(function () {
24363
24842
  (0, applyChange_1.default)(editor, image, editInfo, lastSrc_1 || '', true /*wasResized*/);
24364
24843
  }, "ImageResize" /* ImageResize */);
24844
+ editor.select(image);
24365
24845
  }
24366
24846
  });
24367
24847
  }
@@ -24506,13 +24986,18 @@ function checkEditInfoState(editInfo, compareTo) {
24506
24986
  if (!editInfo || !editInfo.src || ALL_KEYS.some(function (key) { return !isNumber(editInfo[key]); })) {
24507
24987
  return 0 /* Invalid */;
24508
24988
  }
24509
- else if (ROTATE_CROP_KEYS.every(function (key) { return areSameNumber(editInfo[key], 0); })) {
24989
+ else if (ROTATE_CROP_KEYS.every(function (key) { return areSameNumber(editInfo[key], 0); }) &&
24990
+ !editInfo.flippedHorizontal &&
24991
+ !editInfo.flippedVertical &&
24992
+ (!compareTo || (compareTo && editInfo.angleRad === compareTo.angleRad))) {
24510
24993
  return 1 /* ResizeOnly */;
24511
24994
  }
24512
24995
  else if (compareTo &&
24513
24996
  ROTATE_KEYS.every(function (key) { return areSameNumber(editInfo[key], 0); }) &&
24514
24997
  ROTATE_KEYS.every(function (key) { return areSameNumber(compareTo[key], 0); }) &&
24515
- CROP_KEYS.every(function (key) { return areSameNumber(editInfo[key], compareTo[key]); })) {
24998
+ CROP_KEYS.every(function (key) { return areSameNumber(editInfo[key], compareTo[key]); }) &&
24999
+ compareTo.flippedHorizontal === editInfo.flippedHorizontal &&
25000
+ compareTo.flippedVertical === editInfo.flippedVertical) {
24516
25001
  return 2 /* SameWithLast */;
24517
25002
  }
24518
25003
  else {
@@ -24633,6 +25118,7 @@ function generateDataURL(image, editInfo) {
24633
25118
  if (context) {
24634
25119
  context.translate(targetWidth / 2, targetHeight / 2);
24635
25120
  context.rotate(angle);
25121
+ context.scale(editInfo.flippedHorizontal ? -1 : 1, editInfo.flippedVertical ? -1 : 1);
24636
25122
  context.drawImage(image, naturalWidth * left, naturalHeight * top, imageWidth, imageHeight, -width / 2, -height / 2, width, height);
24637
25123
  }
24638
25124
  return canvas.toDataURL('image/png', 1.0);
@@ -25138,15 +25624,26 @@ exports.Rotator = {
25138
25624
  * Move rotate handle. When image is very close to the border of editor, rotate handle may not be visible.
25139
25625
  * Fix it by reduce the distance from image to rotate handle
25140
25626
  */
25141
- function updateRotateHandlePosition(editInfo, editorRect, marginVertical, rotateCenter, rotateHandle) {
25627
+ function updateRotateHandlePosition(editorRect, rotateCenter, rotateHandle) {
25142
25628
  var rotateHandleRect = rotateHandle.getBoundingClientRect();
25143
25629
  if (rotateHandleRect) {
25144
25630
  var top_1 = rotateHandleRect.top - editorRect.top;
25145
- var angleRad = editInfo.angleRad, heightPx = editInfo.heightPx;
25146
- var cosAngle = Math.cos(angleRad);
25147
- var adjustedDistance = cosAngle <= 0
25148
- ? Number.MAX_SAFE_INTEGER
25149
- : (top_1 + heightPx / 2 + marginVertical) / cosAngle - heightPx / 2;
25631
+ var left = rotateHandleRect.left - editorRect.left;
25632
+ var right = rotateHandleRect.right - editorRect.right;
25633
+ var bottom = rotateHandleRect.bottom - editorRect.bottom;
25634
+ var adjustedDistance = Number.MAX_SAFE_INTEGER;
25635
+ if (top_1 <= 0) {
25636
+ adjustedDistance = top_1;
25637
+ }
25638
+ else if (left <= 0) {
25639
+ adjustedDistance = left;
25640
+ }
25641
+ else if (right >= 0) {
25642
+ adjustedDistance = right;
25643
+ }
25644
+ else if (bottom >= 0) {
25645
+ adjustedDistance = bottom;
25646
+ }
25150
25647
  var rotateGap = Math.max(Math.min(ROTATE_GAP, adjustedDistance), 0);
25151
25648
  var rotateTop = Math.max(Math.min(ROTATE_SIZE, adjustedDistance - rotateGap), 0);
25152
25649
  rotateCenter.style.top = -rotateGap + 'px';
@@ -25366,6 +25863,7 @@ var Paste = /** @class */ (function () {
25366
25863
  if (convertSingleImageBody === void 0) { convertSingleImageBody = false; }
25367
25864
  this.unknownTagReplacement = unknownTagReplacement;
25368
25865
  this.convertSingleImageBody = convertSingleImageBody;
25866
+ this.editor = null;
25369
25867
  }
25370
25868
  /**
25371
25869
  * Get a friendly name of this plugin
@@ -25391,7 +25889,7 @@ var Paste = /** @class */ (function () {
25391
25889
  * @param event PluginEvent object
25392
25890
  */
25393
25891
  Paste.prototype.onPluginEvent = function (event) {
25394
- if (event.eventType == 10 /* BeforePaste */) {
25892
+ if (this.editor && event.eventType == 10 /* BeforePaste */) {
25395
25893
  var fragment = event.fragment, sanitizingOption = event.sanitizingOption;
25396
25894
  var trustedHTMLHandler = this.editor.getTrustedHTMLHandler();
25397
25895
  switch ((0, getPasteSource_1.default)(event, this.convertSingleImageBody)) {
@@ -25400,22 +25898,23 @@ var Paste = /** @class */ (function () {
25400
25898
  (0, convertPastedContentFromWord_1.default)(event);
25401
25899
  break;
25402
25900
  case 1 /* ExcelDesktop */:
25901
+ case 2 /* ExcelOnline */:
25403
25902
  // Handle HTML copied from Excel
25404
25903
  (0, convertPastedContentFromExcel_1.default)(event, trustedHTMLHandler);
25405
25904
  break;
25406
- case 2 /* PowerPointDesktop */:
25905
+ case 3 /* PowerPointDesktop */:
25407
25906
  (0, convertPastedContentFromPowerPoint_1.default)(event, trustedHTMLHandler);
25408
25907
  break;
25409
- case 4 /* WacComponents */:
25908
+ case 5 /* WacComponents */:
25410
25909
  (0, convertPastedContentFromOfficeOnline_1.default)(fragment);
25411
25910
  break;
25412
- case 3 /* GoogleSheets */:
25911
+ case 4 /* GoogleSheets */:
25413
25912
  sanitizingOption.additionalTagReplacements[constants_1.GOOGLE_SHEET_NODE_NAME] = '*';
25414
25913
  break;
25415
- case 6 /* SingleImage */:
25914
+ case 7 /* SingleImage */:
25416
25915
  (0, convertPasteContentForSingleImage_1.default)(event, trustedHTMLHandler);
25417
25916
  break;
25418
- case 5 /* Default */:
25917
+ case 6 /* Default */:
25419
25918
  (0, convertPastedContentForLI_1.default)(fragment);
25420
25919
  (0, handleLineMerge_1.default)(fragment);
25421
25920
  break;
@@ -25510,12 +26009,28 @@ var DEFAULT_BORDER_STYLE = 'solid 1px #d4d4d4';
25510
26009
  * @param event The BeforePaste event
25511
26010
  */
25512
26011
  function convertPastedContentFromExcel(event, trustedHTMLHandler) {
26012
+ var _a, _b;
25513
26013
  var fragment = event.fragment, sanitizingOption = event.sanitizingOption, htmlBefore = event.htmlBefore, clipboardData = event.clipboardData;
25514
- var html = excelHandler(clipboardData.html, htmlBefore);
25515
- if (clipboardData.html != html) {
26014
+ var fragmentHTML = (_b = (_a = fragment.firstElementChild) === null || _a === void 0 ? void 0 : _a.outerHTML) !== null && _b !== void 0 ? _b : clipboardData.html;
26015
+ var html = fragmentHTML ? excelHandler(fragmentHTML, htmlBefore) : undefined;
26016
+ if (html && fragmentHTML != html) {
25516
26017
  var doc = new DOMParser().parseFromString(trustedHTMLHandler(html), 'text/html');
25517
26018
  (0, roosterjs_editor_dom_1.moveChildNodes)(fragment, doc === null || doc === void 0 ? void 0 : doc.body);
25518
26019
  }
26020
+ // For Excel Online
26021
+ var firstChild = fragment.firstChild;
26022
+ if (firstChild && firstChild.childNodes.length > 0 && (0, roosterjs_editor_dom_1.getTagOfNode)(firstChild) == 'DIV') {
26023
+ var tableFound = Array.from(firstChild.childNodes).every(function (child) {
26024
+ // Tables pasted from Excel Online should be of the format: 0 to N META tags and 1 TABLE tag
26025
+ return (0, roosterjs_editor_dom_1.getTagOfNode)(child) == 'META'
26026
+ ? true
26027
+ : (0, roosterjs_editor_dom_1.getTagOfNode)(child) == 'TABLE' && child == firstChild.lastChild;
26028
+ });
26029
+ // Extract Table from Div
26030
+ if (tableFound && firstChild.lastChild) {
26031
+ event.fragment.replaceChildren(firstChild.lastChild);
26032
+ }
26033
+ }
25519
26034
  (0, roosterjs_editor_dom_1.chainSanitizerCallback)(sanitizingOption.elementCallbacks, 'TD', function (element) {
25520
26035
  if (element.style.borderStyle == 'none') {
25521
26036
  element.style.border = DEFAULT_BORDER_STYLE;
@@ -25629,21 +26144,23 @@ function handleLineMerge(root) {
25629
26144
  }
25630
26145
  exports.default = handleLineMerge;
25631
26146
  function processBlock(block) {
25632
- var _a, _b;
26147
+ var _a, _b, _c;
25633
26148
  var start = block.start, end = block.end;
25634
26149
  if (start == end && (0, roosterjs_editor_dom_1.getTagOfNode)(start) == 'DIV') {
25635
26150
  var node = (0, roosterjs_editor_dom_1.changeElementTag)(start, 'SPAN');
25636
26151
  block.start = node;
25637
26152
  block.end = node;
25638
- if ((0, roosterjs_editor_dom_1.getTagOfNode)(node.lastChild) == 'BR') {
26153
+ if (node && node.lastChild && (0, roosterjs_editor_dom_1.getTagOfNode)(node.lastChild) == 'BR') {
25639
26154
  node.removeChild(node.lastChild);
25640
26155
  }
25641
26156
  }
25642
26157
  else if ((0, roosterjs_editor_dom_1.getTagOfNode)(end) == 'BR') {
25643
- var node = end.ownerDocument.createTextNode('');
25644
- (_a = end.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(node, end);
25645
- block.end = node;
25646
- (_b = end.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(end);
26158
+ var node = (_a = end.ownerDocument) === null || _a === void 0 ? void 0 : _a.createTextNode('');
26159
+ if (node) {
26160
+ (_b = end.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(node, end);
26161
+ block.end = node;
26162
+ (_c = end.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(end);
26163
+ }
25647
26164
  }
25648
26165
  }
25649
26166
  function checkAndAddBr(root, block, isFirst, firstBlock) {
@@ -25668,7 +26185,8 @@ function checkAndAddBr(root, block, isFirst, firstBlock) {
25668
26185
  // If the first block and the last block are Siblings, add a BR before so the only two
25669
26186
  // lines that are being pasted are not merged.
25670
26187
  var previousSibling = (0, roosterjs_editor_dom_1.getPreviousLeafSibling)(root, block.start);
25671
- if (firstBlock.end.contains(previousSibling)) {
26188
+ if (firstBlock.end.contains(previousSibling) &&
26189
+ !(0, roosterjs_editor_dom_1.findClosestElementAncestor)(block.start, root, 'li')) {
25672
26190
  var br = (_c = block.start.ownerDocument) === null || _c === void 0 ? void 0 : _c.createElement('br');
25673
26191
  if (br) {
25674
26192
  (_d = block.start.parentNode) === null || _d === void 0 ? void 0 : _d.insertBefore(br, block.start);
@@ -25730,8 +26248,9 @@ var convertPastedContentFromWordOnline_1 = __webpack_require__(/*! ./convertPast
25730
26248
  */
25731
26249
  function convertPastedContentFromOfficeOnline(fragment) {
25732
26250
  fragment.querySelectorAll(constants_1.WAC_IDENTIFY_SELECTOR).forEach(function (el) {
25733
- el.style.display = null;
25734
- el.style.margin = null;
26251
+ var element = el;
26252
+ element.style.removeProperty('display');
26253
+ element.style.removeProperty('margin');
25735
26254
  });
25736
26255
  // call conversion function if the pasted content is from word online and
25737
26256
  // has list element in the pasted content.
@@ -25811,6 +26330,7 @@ function convertPastedContentFromWordOnline(fragment) {
25811
26330
  sanitizeListItemContainer(fragment);
25812
26331
  var listItemBlocks = getListItemBlocks(fragment);
25813
26332
  listItemBlocks.forEach(function (itemBlock) {
26333
+ var _a, _b, _c;
25814
26334
  // There are cases where consecutive List Elements are separated into different nodes:
25815
26335
  // <div>
25816
26336
  // <div>
@@ -25840,37 +26360,47 @@ function convertPastedContentFromWordOnline(fragment) {
25840
26360
  // Then we are start processing.
25841
26361
  flattenListBlock(fragment, itemBlock);
25842
26362
  // Find the node to insertBefore, which is next sibling node of the end of a listItemBlock.
25843
- itemBlock.insertPositionNode = itemBlock.endElement.nextSibling;
25844
- var convertedListElement;
26363
+ itemBlock.insertPositionNode = (_b = (_a = itemBlock.endElement) === null || _a === void 0 ? void 0 : _a.nextSibling) !== null && _b !== void 0 ? _b : null;
26364
+ var convertedListElement = undefined;
25845
26365
  var doc = fragment.ownerDocument;
25846
26366
  itemBlock.listItemContainers.forEach(function (listItemContainer) {
25847
26367
  var listType = getContainerListType(listItemContainer); // list type that is contained by iterator.
25848
- // Initialize processed element with proper listType if this is the first element
25849
- if (!convertedListElement) {
25850
- convertedListElement = createNewList(listItemContainer, doc, listType);
25851
- }
25852
- // Get all list items(<li>) in the current iterator element.
25853
- var currentListItems = (0, roosterjs_editor_dom_1.toArray)(listItemContainer.querySelectorAll('li'));
25854
- currentListItems.forEach(function (item) {
25855
- // If item is in root level and the type of list changes then
25856
- // insert the current list into body and then reinitialize the convertedListElement
25857
- // Word Online is using data-aria-level to determine the the depth of the list item.
25858
- var itemLevel = parseInt(item.getAttribute('data-aria-level'));
25859
- // In first level list, there are cases where a consecutive list item DIV may have different list type
25860
- // When that happens we need to insert the processed elements into the document, then change the list type
25861
- // and keep the processing going.
25862
- if ((0, roosterjs_editor_dom_1.getTagOfNode)(convertedListElement) != listType && itemLevel == 1) {
25863
- insertConvertedListToDoc(convertedListElement, fragment, itemBlock);
26368
+ if (listType) {
26369
+ // Initialize processed element with proper listType if this is the first element
26370
+ if (!convertedListElement) {
25864
26371
  convertedListElement = createNewList(listItemContainer, doc, listType);
25865
26372
  }
25866
- insertListItem(convertedListElement, item, listType, doc);
25867
- });
26373
+ // Get all list items(<li>) in the current iterator element.
26374
+ var currentListItems = (0, roosterjs_editor_dom_1.toArray)(listItemContainer.querySelectorAll('li'));
26375
+ currentListItems.forEach(function (item) {
26376
+ var _a;
26377
+ // If item is in root level and the type of list changes then
26378
+ // insert the current list into body and then reinitialize the convertedListElement
26379
+ // Word Online is using data-aria-level to determine the the depth of the list item.
26380
+ var itemLevel = parseInt((_a = item.getAttribute('data-aria-level')) !== null && _a !== void 0 ? _a : '');
26381
+ // In first level list, there are cases where a consecutive list item DIV may have different list type
26382
+ // When that happens we need to insert the processed elements into the document, then change the list type
26383
+ // and keep the processing going.
26384
+ if (convertedListElement &&
26385
+ (0, roosterjs_editor_dom_1.getTagOfNode)(convertedListElement) != listType &&
26386
+ itemLevel == 1 &&
26387
+ listType) {
26388
+ insertConvertedListToDoc(convertedListElement, fragment, itemBlock);
26389
+ convertedListElement = createNewList(listItemContainer, doc, listType);
26390
+ }
26391
+ if (convertedListElement && listType) {
26392
+ insertListItem(convertedListElement, item, listType, doc);
26393
+ }
26394
+ });
26395
+ }
25868
26396
  });
25869
- insertConvertedListToDoc(convertedListElement, fragment, itemBlock);
26397
+ if (convertedListElement) {
26398
+ insertConvertedListToDoc(convertedListElement, fragment, itemBlock);
26399
+ }
25870
26400
  // Once we finish the process the list items and put them into a list.
25871
26401
  // After inserting the processed element,
25872
26402
  // we need to remove all the non processed node from the parent node.
25873
- var parentContainer = itemBlock.startElement.parentNode;
26403
+ var parentContainer = (_c = itemBlock.startElement) === null || _c === void 0 ? void 0 : _c.parentNode;
25874
26404
  if (parentContainer) {
25875
26405
  itemBlock.listItemContainers.forEach(function (listItemContainer) {
25876
26406
  parentContainer.removeChild(listItemContainer);
@@ -25890,8 +26420,9 @@ function convertPastedContentFromWordOnline(fragment) {
25890
26420
  // Removing the nodes that are not img will resolve the additional space
25891
26421
  if ((0, roosterjs_editor_dom_1.safeInstanceOf)(node, 'HTMLSpanElement')) {
25892
26422
  node.childNodes.forEach(function (childNode) {
26423
+ var _a;
25893
26424
  if ((0, roosterjs_editor_dom_1.getTagOfNode)(childNode) != 'IMG') {
25894
- childNode.parentElement.removeChild(childNode);
26425
+ (_a = childNode.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(childNode);
25895
26426
  }
25896
26427
  });
25897
26428
  }
@@ -25933,7 +26464,7 @@ function sanitizeListItemContainer(fragment) {
25933
26464
  function getListItemBlocks(fragment) {
25934
26465
  var listElements = fragment.querySelectorAll('.' + LIST_CONTAINER_ELEMENT_CLASS_NAME);
25935
26466
  var result = [];
25936
- var curListItemBlock;
26467
+ var curListItemBlock = null;
25937
26468
  for (var i = 0; i < listElements.length; i++) {
25938
26469
  var curItem = listElements[i];
25939
26470
  if (!curListItemBlock) {
@@ -25943,8 +26474,9 @@ function getListItemBlocks(fragment) {
25943
26474
  var listItemContainers = curListItemBlock.listItemContainers;
25944
26475
  var lastItemInCurBlock = listItemContainers[listItemContainers.length - 1];
25945
26476
  if (curItem == lastItemInCurBlock.nextSibling ||
25946
- (0, roosterjs_editor_dom_1.getFirstLeafNode)(curItem) ==
25947
- (0, roosterjs_editor_dom_1.getNextLeafSibling)(lastItemInCurBlock.parentNode, lastItemInCurBlock)) {
26477
+ (lastItemInCurBlock.parentNode &&
26478
+ (0, roosterjs_editor_dom_1.getFirstLeafNode)(curItem) ==
26479
+ (0, roosterjs_editor_dom_1.getNextLeafSibling)(lastItemInCurBlock.parentNode, lastItemInCurBlock))) {
25948
26480
  listItemContainers.push(curItem);
25949
26481
  curListItemBlock.endElement = curItem;
25950
26482
  }
@@ -25955,7 +26487,7 @@ function getListItemBlocks(fragment) {
25955
26487
  }
25956
26488
  }
25957
26489
  }
25958
- if ((curListItemBlock === null || curListItemBlock === void 0 ? void 0 : curListItemBlock.listItemContainers.length) > 0) {
26490
+ if (curListItemBlock && curListItemBlock.listItemContainers.length > 0) {
25959
26491
  result.push(curListItemBlock);
25960
26492
  }
25961
26493
  return result;
@@ -25966,12 +26498,14 @@ function getListItemBlocks(fragment) {
25966
26498
  * @param listItemBlock The list item block needed to be flattened.
25967
26499
  */
25968
26500
  function flattenListBlock(fragment, listItemBlock) {
25969
- var collapsedListItemSections = (0, roosterjs_editor_dom_1.collapseNodes)(fragment, listItemBlock.startElement, listItemBlock.endElement, true);
25970
- collapsedListItemSections.forEach(function (section) {
25971
- if ((0, roosterjs_editor_dom_1.getTagOfNode)(section.firstChild) == 'DIV') {
25972
- (0, roosterjs_editor_dom_1.unwrap)(section);
25973
- }
25974
- });
26501
+ if (listItemBlock.startElement && listItemBlock.endElement) {
26502
+ var collapsedListItemSections = (0, roosterjs_editor_dom_1.collapseNodes)(fragment, listItemBlock.startElement, listItemBlock.endElement, true);
26503
+ collapsedListItemSections.forEach(function (section) {
26504
+ if ((0, roosterjs_editor_dom_1.getTagOfNode)(section.firstChild) == 'DIV') {
26505
+ (0, roosterjs_editor_dom_1.unwrap)(section);
26506
+ }
26507
+ });
26508
+ }
25975
26509
  }
25976
26510
  /**
25977
26511
  * Get the list type that the container contains. If there is no list in the container
@@ -26009,14 +26543,16 @@ function insertListItem(listRootElement, itemToInsert, listType, doc) {
26009
26543
  // If the current level is empty, create empty list within the current level
26010
26544
  // then move the level iterator into the next level.
26011
26545
  curListLevel.appendChild(doc.createElement(listType));
26012
- curListLevel = curListLevel.firstElementChild;
26546
+ if (curListLevel.firstElementChild) {
26547
+ curListLevel = curListLevel.firstElementChild;
26548
+ }
26013
26549
  }
26014
26550
  else {
26015
26551
  // If the current level is not empty, the last item in the needs to be a UL or OL
26016
26552
  // and the level iterator should move to the UL/OL at the last position.
26017
26553
  var lastChild = curListLevel.lastElementChild;
26018
26554
  var lastChildTag = (0, roosterjs_editor_dom_1.getTagOfNode)(lastChild);
26019
- if (lastChildTag == 'UL' || lastChildTag == 'OL') {
26555
+ if (lastChild && (lastChildTag == 'UL' || lastChildTag == 'OL')) {
26020
26556
  // If the last child is a list(UL/OL), then move the level iterator to last child.
26021
26557
  curListLevel = lastChild;
26022
26558
  }
@@ -26024,7 +26560,9 @@ function insertListItem(listRootElement, itemToInsert, listType, doc) {
26024
26560
  // If the last child is not a list, then append a new list to the level
26025
26561
  // and move the level iterator to the new level.
26026
26562
  curListLevel.appendChild(doc.createElement(listType));
26027
- curListLevel = curListLevel.lastElementChild;
26563
+ if (curListLevel.lastElementChild) {
26564
+ curListLevel = curListLevel.lastElementChild;
26565
+ }
26028
26566
  }
26029
26567
  }
26030
26568
  itemLevel--;
@@ -26039,6 +26577,7 @@ function insertListItem(listRootElement, itemToInsert, listType, doc) {
26039
26577
  * @param listItemBlock List item block that was converted.
26040
26578
  */
26041
26579
  function insertConvertedListToDoc(convertedListElement, fragment, listItemBlock) {
26580
+ var _a;
26042
26581
  if (!convertedListElement) {
26043
26582
  return;
26044
26583
  }
@@ -26050,7 +26589,7 @@ function insertConvertedListToDoc(convertedListElement, fragment, listItemBlock)
26050
26589
  }
26051
26590
  }
26052
26591
  else {
26053
- var parentNode = listItemBlock.startElement.parentNode;
26592
+ var parentNode = (_a = listItemBlock.startElement) === null || _a === void 0 ? void 0 : _a.parentNode;
26054
26593
  if (parentNode) {
26055
26594
  parentNode.appendChild(convertedListElement);
26056
26595
  }
@@ -26221,7 +26760,7 @@ function validateLink(link, htmlElement) {
26221
26760
  "use strict";
26222
26761
 
26223
26762
  Object.defineProperty(exports, "__esModule", { value: true });
26224
- exports.WAC_IDENTIFY_SELECTOR = exports.PROG_ID_NAME = exports.GOOGLE_SHEET_NODE_NAME = void 0;
26763
+ exports.EXCEL_DESKTOP_ATTRIBUTE_NAME = exports.WAC_IDENTIFY_SELECTOR = exports.PROG_ID_NAME = exports.GOOGLE_SHEET_NODE_NAME = void 0;
26225
26764
  /**
26226
26765
  * @internal
26227
26766
  * Node attribute used to identify if the content is from Google Sheets.
@@ -26237,6 +26776,11 @@ exports.PROG_ID_NAME = 'ProgId';
26237
26776
  * Selector used to identify Wac Elements
26238
26777
  */
26239
26778
  exports.WAC_IDENTIFY_SELECTOR = 'ul[class^="BulletListStyle"]>.OutlineElement,ol[class^="NumberListStyle"]>.OutlineElement,span.WACImageContainer';
26779
+ /**
26780
+ * @internal
26781
+ * Name of the HTMLMeta Property that identifies pated content as from Excel Desktop
26782
+ */
26783
+ exports.EXCEL_DESKTOP_ATTRIBUTE_NAME = 'xmlns:x';
26240
26784
 
26241
26785
 
26242
26786
  /***/ }),
@@ -26279,6 +26823,7 @@ exports.default = documentContainWacElements;
26279
26823
  Object.defineProperty(exports, "__esModule", { value: true });
26280
26824
  var documentContainWacElements_1 = __webpack_require__(/*! ./documentContainWacElements */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/documentContainWacElements.ts");
26281
26825
  var isExcelDesktopDocument_1 = __webpack_require__(/*! ./isExcelDesktopDocument */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isExcelDesktopDocument.ts");
26826
+ var isExcelOnlineDocument_1 = __webpack_require__(/*! ./isExcelOnlineDocument */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isExcelOnlineDocument.ts");
26282
26827
  var isGoogleSheetDocument_1 = __webpack_require__(/*! ./isGoogleSheetDocument */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isGoogleSheetDocument.ts");
26283
26828
  var isPowerPointDesktopDocument_1 = __webpack_require__(/*! ./isPowerPointDesktopDocument */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isPowerPointDesktopDocument.ts");
26284
26829
  var isWordDesktopDocument_1 = __webpack_require__(/*! ./isWordDesktopDocument */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isWordDesktopDocument.ts");
@@ -26286,10 +26831,11 @@ var shouldConvertToSingleImage_1 = __webpack_require__(/*! ./shouldConvertToSing
26286
26831
  var getSourceFunctions = new Map([
26287
26832
  [0 /* WordDesktop */, isWordDesktopDocument_1.default],
26288
26833
  [1 /* ExcelDesktop */, isExcelDesktopDocument_1.default],
26289
- [2 /* PowerPointDesktop */, isPowerPointDesktopDocument_1.default],
26290
- [4 /* WacComponents */, documentContainWacElements_1.default],
26291
- [3 /* GoogleSheets */, isGoogleSheetDocument_1.default],
26292
- [6 /* SingleImage */, shouldConvertToSingleImage_1.default],
26834
+ [2 /* ExcelOnline */, isExcelOnlineDocument_1.default],
26835
+ [3 /* PowerPointDesktop */, isPowerPointDesktopDocument_1.default],
26836
+ [5 /* WacComponents */, documentContainWacElements_1.default],
26837
+ [4 /* GoogleSheets */, isGoogleSheetDocument_1.default],
26838
+ [7 /* SingleImage */, shouldConvertToSingleImage_1.default],
26293
26839
  ]);
26294
26840
  /**
26295
26841
  * @internal
@@ -26312,7 +26858,7 @@ function getPasteSource(event, shouldConvertSingleImage) {
26312
26858
  result = key;
26313
26859
  }
26314
26860
  });
26315
- return result !== null && result !== void 0 ? result : 5 /* Default */;
26861
+ return result !== null && result !== void 0 ? result : 6 /* Default */;
26316
26862
  }
26317
26863
  exports.default = getPasteSource;
26318
26864
 
@@ -26330,9 +26876,7 @@ exports.default = getPasteSource;
26330
26876
 
26331
26877
  Object.defineProperty(exports, "__esModule", { value: true });
26332
26878
  var constants_1 = __webpack_require__(/*! ./constants */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/constants.ts");
26333
- var EXCEL_ATTRIBUTE_NAME = 'xmlns:x';
26334
26879
  var EXCEL_ATTRIBUTE_VALUE = 'urn:schemas-microsoft-com:office:excel';
26335
- var EXCEL_ONLINE_ATTRIBUTE_VALUE = 'Excel.Sheet';
26336
26880
  /**
26337
26881
  * @internal
26338
26882
  * Checks whether the Array provided contains strings that identify Excel Desktop documents
@@ -26341,12 +26885,42 @@ var EXCEL_ONLINE_ATTRIBUTE_VALUE = 'Excel.Sheet';
26341
26885
  */
26342
26886
  var isExcelDesktopDocument = function (props) {
26343
26887
  var htmlAttributes = props.htmlAttributes;
26344
- return (htmlAttributes[EXCEL_ATTRIBUTE_NAME] == EXCEL_ATTRIBUTE_VALUE ||
26345
- htmlAttributes[constants_1.PROG_ID_NAME] == EXCEL_ONLINE_ATTRIBUTE_VALUE);
26888
+ // The presence of this attribute confirms its origin from Excel Desktop
26889
+ return htmlAttributes[constants_1.EXCEL_DESKTOP_ATTRIBUTE_NAME] == EXCEL_ATTRIBUTE_VALUE;
26346
26890
  };
26347
26891
  exports.default = isExcelDesktopDocument;
26348
26892
 
26349
26893
 
26894
+ /***/ }),
26895
+
26896
+ /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isExcelOnlineDocument.ts":
26897
+ /*!********************************************************************************************************!*\
26898
+ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isExcelOnlineDocument.ts ***!
26899
+ \********************************************************************************************************/
26900
+ /*! no static exports found */
26901
+ /***/ (function(module, exports, __webpack_require__) {
26902
+
26903
+ "use strict";
26904
+
26905
+ Object.defineProperty(exports, "__esModule", { value: true });
26906
+ var constants_1 = __webpack_require__(/*! ./constants */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/constants.ts");
26907
+ // Excel Desktop also has this attribute
26908
+ var EXCEL_ONLINE_ATTRIBUTE_VALUE = 'Excel.Sheet';
26909
+ /**
26910
+ * @internal
26911
+ * Checks whether the Array provided contains strings that identify Excel Online documents
26912
+ * @param props Properties related to the PasteEvent
26913
+ * @returns
26914
+ */
26915
+ var isExcelOnlineDocument = function (props) {
26916
+ var htmlAttributes = props.htmlAttributes;
26917
+ // The presence of Excel.Sheet confirms its origin from Excel, the absence of EXCEL_DESKTOP_ATTRIBUTE_NAME confirms it is from the Online version
26918
+ return (htmlAttributes[constants_1.PROG_ID_NAME] == EXCEL_ONLINE_ATTRIBUTE_VALUE &&
26919
+ htmlAttributes[constants_1.EXCEL_DESKTOP_ATTRIBUTE_NAME] == undefined);
26920
+ };
26921
+ exports.default = isExcelOnlineDocument;
26922
+
26923
+
26350
26924
  /***/ }),
26351
26925
 
26352
26926
  /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isGoogleSheetDocument.ts":
@@ -26786,7 +27360,11 @@ var LINE_BREAKS = /[\n|\r]/gi;
26786
27360
  * for numbered headers, and we don't want to convert those, because the numbering would be completely wrong.
26787
27361
  */
26788
27362
  function processNodesDiscovery(wordConverter) {
27363
+ var _a;
26789
27364
  var args = wordConverter.wordConverterArgs;
27365
+ if (!args) {
27366
+ return false;
27367
+ }
26790
27368
  while (args.currentIndex < args.nodes.length) {
26791
27369
  var node = args.nodes.item(args.currentIndex);
26792
27370
  // Try to get the list metadata for the specified node
@@ -26875,7 +27453,7 @@ function processNodesDiscovery(wordConverter) {
26875
27453
  last.appendChild(last.ownerDocument.createElement('br'));
26876
27454
  (0, roosterjs_editor_dom_1.moveChildNodes)(last, node, true /*keepExistingChildren*/);
26877
27455
  // Remove the item that we don't need anymore
26878
- node.parentNode.removeChild(node);
27456
+ (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node);
26879
27457
  }
26880
27458
  }
26881
27459
  // Move to the next element are return true if more elements need to be processed
@@ -26891,44 +27469,47 @@ exports.processNodesDiscovery = processNodesDiscovery;
26891
27469
  * conversion needed
26892
27470
  */
26893
27471
  function processNodeConvert(wordConverter) {
27472
+ var _a;
26894
27473
  var args = wordConverter.wordConverterArgs;
26895
- args.currentIndex = 0;
26896
- while (args.currentIndex < args.listItems.length) {
26897
- var metadata = args.listItems[args.currentIndex];
26898
- var node = metadata.originalNode;
26899
- var listMetadata = args.lists[metadata.uniqueListId.toString()];
26900
- if (!listMetadata.ignore) {
26901
- // We have a list item that we need to convert, get or create the list
26902
- // that hold this item out
26903
- var list = getOrCreateListForNode(wordConverter, node, metadata, listMetadata);
26904
- if (list) {
26905
- // Clean the element out.. this call gets rid of the fake bullet and unneeded nodes
26906
- cleanupListIgnore(node, LOOKUP_DEPTH);
26907
- // Create a new list item and transfer the children
26908
- var li = node.ownerDocument.createElement('LI');
26909
- if ((0, roosterjs_editor_dom_1.getTagOfNode)(node).startsWith('H')) {
26910
- var clone = node.cloneNode(true /* deep */);
26911
- clone.style.textIndent = '';
26912
- clone.style.marginLeft = '';
26913
- clone.style.marginRight = '';
26914
- li.appendChild(clone);
26915
- }
26916
- else {
26917
- (0, roosterjs_editor_dom_1.moveChildNodes)(li, node);
26918
- }
26919
- // Append the list item into the list
26920
- list.appendChild(li);
26921
- // Remove the node we just converted
26922
- node.parentNode.removeChild(node);
26923
- if (listMetadata.tagName == 'UL') {
26924
- wordConverter.numBulletsConverted++;
26925
- }
26926
- else {
26927
- wordConverter.numNumberedConverted++;
27474
+ if (args) {
27475
+ args.currentIndex = 0;
27476
+ while (args.currentIndex < args.listItems.length) {
27477
+ var metadata = args.listItems[args.currentIndex];
27478
+ var node = metadata.originalNode;
27479
+ var listMetadata = args.lists[metadata.uniqueListId.toString()];
27480
+ if (!listMetadata.ignore) {
27481
+ // We have a list item that we need to convert, get or create the list
27482
+ // that hold this item out
27483
+ var list = getOrCreateListForNode(wordConverter, node, metadata, listMetadata);
27484
+ if (list) {
27485
+ // Clean the element out.. this call gets rid of the fake bullet and unneeded nodes
27486
+ cleanupListIgnore(node, LOOKUP_DEPTH);
27487
+ // Create a new list item and transfer the children
27488
+ var li = node.ownerDocument.createElement('LI');
27489
+ if ((0, roosterjs_editor_dom_1.getTagOfNode)(node).startsWith('H')) {
27490
+ var clone = node.cloneNode(true /* deep */);
27491
+ clone.style.textIndent = '';
27492
+ clone.style.marginLeft = '';
27493
+ clone.style.marginRight = '';
27494
+ li.appendChild(clone);
27495
+ }
27496
+ else {
27497
+ (0, roosterjs_editor_dom_1.moveChildNodes)(li, node);
27498
+ }
27499
+ // Append the list item into the list
27500
+ list.appendChild(li);
27501
+ // Remove the node we just converted
27502
+ (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node);
27503
+ if (listMetadata.tagName == 'UL') {
27504
+ wordConverter.numBulletsConverted++;
27505
+ }
27506
+ else {
27507
+ wordConverter.numNumberedConverted++;
27508
+ }
26928
27509
  }
26929
27510
  }
27511
+ args.currentIndex++;
26930
27512
  }
26931
- args.currentIndex++;
26932
27513
  }
26933
27514
  return wordConverter.numBulletsConverted > 0 || wordConverter.numNumberedConverted > 0;
26934
27515
  }
@@ -26938,6 +27519,7 @@ exports.processNodeConvert = processNodeConvert;
26938
27519
  * items content and the specified metadata
26939
27520
  */
26940
27521
  function getOrCreateListForNode(wordConverter, node, metadata, listMetadata) {
27522
+ var _a;
26941
27523
  // First get the last list next to this node under the specified level. This code
26942
27524
  // path will return the list or will create lists if needed
26943
27525
  var list = recurringGetOrCreateListAtNode(node, metadata.level, listMetadata);
@@ -26949,7 +27531,7 @@ function getOrCreateListForNode(wordConverter, node, metadata, listMetadata) {
26949
27531
  // is a completely new list, so we'll append a new list for that
26950
27532
  if ((listId && listId != metadata.uniqueListId) || (!listId && list.firstChild)) {
26951
27533
  var newList = node.ownerDocument.createElement(listMetadata.tagName);
26952
- list.parentNode.insertBefore(newList, list.nextSibling);
27534
+ (_a = list.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(newList, list.nextSibling);
26953
27535
  list = newList;
26954
27536
  }
26955
27537
  // Set the list id into the custom data
@@ -26964,15 +27546,18 @@ function getOrCreateListForNode(wordConverter, node, metadata, listMetadata) {
26964
27546
  * information already stored in the list itself
26965
27547
  */
26966
27548
  function convertListIfNeeded(wordConverter, list, listMetadata) {
27549
+ var _a, _b, _c;
26967
27550
  // Check if we need to convert the list out
26968
27551
  if (listMetadata.tagName != (0, roosterjs_editor_dom_1.getTagOfNode)(list)) {
26969
27552
  // We have the wrong list type.. convert it, set the id again and transfer all the children
26970
- var newList = list.ownerDocument.createElement(listMetadata.tagName);
26971
- (0, WordCustomData_1.setObject)(wordConverter.wordCustomData, newList, UNIQUE_LIST_ID_CUSTOM_DATA, (0, WordCustomData_1.getObject)(wordConverter.wordCustomData, list, UNIQUE_LIST_ID_CUSTOM_DATA));
26972
- (0, roosterjs_editor_dom_1.moveChildNodes)(newList, list);
26973
- list.parentNode.insertBefore(newList, list);
26974
- list.parentNode.removeChild(list);
26975
- list = newList;
27553
+ var newList = (_a = list.ownerDocument) === null || _a === void 0 ? void 0 : _a.createElement(listMetadata.tagName);
27554
+ if (newList) {
27555
+ (0, WordCustomData_1.setObject)(wordConverter.wordCustomData, newList, UNIQUE_LIST_ID_CUSTOM_DATA, (0, WordCustomData_1.getObject)(wordConverter.wordCustomData, list, UNIQUE_LIST_ID_CUSTOM_DATA));
27556
+ (0, roosterjs_editor_dom_1.moveChildNodes)(newList, list);
27557
+ (_b = list.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(newList, list);
27558
+ (_c = list.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(list);
27559
+ list = newList;
27560
+ }
26976
27561
  }
26977
27562
  return list;
26978
27563
  }
@@ -26980,8 +27565,9 @@ function convertListIfNeeded(wordConverter, list, listMetadata) {
26980
27565
  * Gets or creates the specified list
26981
27566
  */
26982
27567
  function recurringGetOrCreateListAtNode(node, level, listMetadata) {
27568
+ var _a, _b;
26983
27569
  var parent = null;
26984
- var possibleList;
27570
+ var possibleList = null;
26985
27571
  if (level == 1) {
26986
27572
  // Root case, we'll check if the list is the previous sibling of the node
26987
27573
  possibleList = getRealPreviousSibling(node);
@@ -26990,7 +27576,9 @@ function recurringGetOrCreateListAtNode(node, level, listMetadata) {
26990
27576
  // If we get here, we are looking for level 2 or deeper... get the upper list
26991
27577
  // and check if the last element is a list
26992
27578
  parent = recurringGetOrCreateListAtNode(node, level - 1, null);
26993
- possibleList = parent.lastChild;
27579
+ if (parent.lastChild) {
27580
+ possibleList = parent.lastChild;
27581
+ }
26994
27582
  }
26995
27583
  // Check the element that we got and verify that it is a list
26996
27584
  if (possibleList && possibleList.nodeType == 1 /* Element */) {
@@ -27002,15 +27590,15 @@ function recurringGetOrCreateListAtNode(node, level, listMetadata) {
27002
27590
  }
27003
27591
  // If we get here, it means we don't have a list and we need to create one
27004
27592
  // this code path will always create new lists as UL lists
27005
- var newList = node.ownerDocument.createElement(listMetadata ? listMetadata.tagName : 'UL');
27593
+ var newList = (_a = node.ownerDocument) === null || _a === void 0 ? void 0 : _a.createElement(listMetadata ? listMetadata.tagName : 'UL');
27006
27594
  if (level == 1) {
27007
27595
  // For level 1, we'll insert the list before the node
27008
- node.parentNode.insertBefore(newList, node);
27596
+ (_b = node.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(newList, node);
27009
27597
  }
27010
27598
  else {
27011
27599
  // Any level 2 or above, we insert the list as the last
27012
27600
  // child of the upper level list
27013
- parent.appendChild(newList);
27601
+ parent === null || parent === void 0 ? void 0 : parent.appendChild(newList);
27014
27602
  }
27015
27603
  return newList;
27016
27604
  }
@@ -27022,15 +27610,17 @@ function recurringGetOrCreateListAtNode(node, level, listMetadata) {
27022
27610
  function cleanupListIgnore(node, levels) {
27023
27611
  var nodesToRemove = [];
27024
27612
  for (var child = node.firstChild; child; child = child.nextSibling) {
27025
- // Clean up the item internally first if we need to based on the number of levels
27026
- if (child.nodeType == 1 /* Element */ && levels > 1) {
27027
- cleanupListIgnore(child, levels - 1);
27028
- }
27029
- // Try to convert word comments into ignore elements if we haven't done so for this element
27030
- child = fixWordListComments(child, true /*removeComments*/);
27031
- // Check if we can remove this item out
27032
- if (isEmptySpan(child) || isIgnoreNode(child)) {
27033
- nodesToRemove.push(child);
27613
+ if (child) {
27614
+ // Clean up the item internally first if we need to based on the number of levels
27615
+ if (child && child.nodeType == 1 /* Element */ && levels > 1) {
27616
+ cleanupListIgnore(child, levels - 1);
27617
+ }
27618
+ // Try to convert word comments into ignore elements if we haven't done so for this element
27619
+ child = fixWordListComments(child, true /*removeComments*/);
27620
+ // Check if we can remove this item out
27621
+ if (isEmptySpan(child) || isIgnoreNode(child)) {
27622
+ nodesToRemove.push(child);
27623
+ }
27034
27624
  }
27035
27625
  }
27036
27626
  nodesToRemove.forEach(function (child) { return node.removeChild(child); });
@@ -27079,6 +27669,7 @@ function getFakeBulletTagName(fakeBullet) {
27079
27669
  * a bullet string. If not found, it returns null...
27080
27670
  */
27081
27671
  function getFakeBulletText(node, levels) {
27672
+ var _a, _b;
27082
27673
  // Word uses the following format for their bullets:
27083
27674
  // &lt;p style="mso-list:l1 level1 lfo2"&gt;
27084
27675
  // &lt;span style="..."&gt;
@@ -27089,7 +27680,7 @@ function getFakeBulletText(node, levels) {
27089
27680
  //
27090
27681
  // Basically, we need to locate the mso-list:Ignore SPAN, which holds either one text or image node. That
27091
27682
  // text or image node will be the fake bullet we are looking for
27092
- var result = null;
27683
+ var result = '';
27093
27684
  var child = node.firstChild;
27094
27685
  while (!result && child) {
27095
27686
  // First, check if we need to convert the Word list comments into real elements
@@ -27097,7 +27688,7 @@ function getFakeBulletText(node, levels) {
27097
27688
  // Check if this is the node that holds the fake bullets (mso-list: Ignore)
27098
27689
  if (isIgnoreNode(child)) {
27099
27690
  // Yes... this is the node that holds either the text or image data
27100
- result = child.textContent.trim();
27691
+ result = (_b = (_a = child.textContent) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : '';
27101
27692
  // This is the case for image case
27102
27693
  if (result.length == 0) {
27103
27694
  result = 'o';
@@ -27121,6 +27712,7 @@ function getFakeBulletText(node, levels) {
27121
27712
  * styles of the span, but we'll use these comments to recreate them out
27122
27713
  */
27123
27714
  function fixWordListComments(child, removeComments) {
27715
+ var _a, _b, _c, _d;
27124
27716
  if (child.nodeType == 8 /* Comment */) {
27125
27717
  var value = child.data;
27126
27718
  if (value && value.trim().toLowerCase() == '[if !supportlists]') {
@@ -27143,22 +27735,28 @@ function fixWordListComments(child, removeComments) {
27143
27735
  }
27144
27736
  // if we found the end node, wrap everything out
27145
27737
  if (endComment) {
27146
- var newSpan = child.ownerDocument.createElement('span');
27147
- newSpan.setAttribute('style', 'mso-list: ignore');
27738
+ var newSpan = (_a = child.ownerDocument) === null || _a === void 0 ? void 0 : _a.createElement('span');
27739
+ newSpan === null || newSpan === void 0 ? void 0 : newSpan.setAttribute('style', 'mso-list: ignore');
27148
27740
  nextElement = getRealNextSibling(child);
27149
27741
  while (nextElement != endComment) {
27150
- nextElement = nextElement.nextSibling;
27151
- newSpan.appendChild(nextElement.previousSibling);
27742
+ nextElement = nextElement === null || nextElement === void 0 ? void 0 : nextElement.nextSibling;
27743
+ if (nextElement.previousSibling) {
27744
+ newSpan === null || newSpan === void 0 ? void 0 : newSpan.appendChild(nextElement.previousSibling);
27745
+ }
27152
27746
  }
27153
27747
  // Insert the element out and use that one as the current child
27154
- endComment.parentNode.insertBefore(newSpan, endComment);
27748
+ if (newSpan) {
27749
+ (_b = endComment.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(newSpan, endComment);
27750
+ }
27155
27751
  // Remove the comments out if the call specified it out
27156
27752
  if (removeComments) {
27157
- child.parentNode.removeChild(child);
27158
- endComment.parentNode.removeChild(endComment);
27753
+ (_c = child.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(child);
27754
+ (_d = endComment.parentNode) === null || _d === void 0 ? void 0 : _d.removeChild(endComment);
27159
27755
  }
27160
27756
  // Last, make sure we return the new element out instead of the comment
27161
- child = newSpan;
27757
+ if (newSpan) {
27758
+ child = newSpan;
27759
+ }
27162
27760
  }
27163
27761
  }
27164
27762
  }
@@ -27210,6 +27808,7 @@ function getStyleValue(node, styleName) {
27210
27808
  }
27211
27809
  /** Checks if the node is an empty text node that can be ignored */
27212
27810
  function isEmptyTextNode(node) {
27811
+ var _a;
27213
27812
  // No node is empty
27214
27813
  if (!node) {
27215
27814
  return true;
@@ -27217,12 +27816,14 @@ function isEmptyTextNode(node) {
27217
27816
  // Empty text node is empty
27218
27817
  if (node.nodeType == 3 /* Text */) {
27219
27818
  var value = node.nodeValue;
27220
- value = value.replace(LINE_BREAKS, '');
27221
- return value.trim().length == 0;
27819
+ value = (_a = value === null || value === void 0 ? void 0 : value.replace(LINE_BREAKS, '')) !== null && _a !== void 0 ? _a : '';
27820
+ return (value === null || value === void 0 ? void 0 : value.trim().length) == 0;
27222
27821
  }
27223
27822
  // Span or Font with an empty child node is empty
27224
27823
  var tagName = (0, roosterjs_editor_dom_1.getTagOfNode)(node);
27225
- if (node.firstChild == node.lastChild && (tagName == 'SPAN' || tagName == 'FONT')) {
27824
+ if (node.firstChild &&
27825
+ node.firstChild == node.lastChild &&
27826
+ (tagName == 'SPAN' || tagName == 'FONT')) {
27226
27827
  return isEmptyTextNode(node.firstChild);
27227
27828
  }
27228
27829
  // If not found, then this is not empty
@@ -29145,7 +29746,7 @@ var TableInsertHandler = /** @class */ (function () {
29145
29746
  }());
29146
29747
  function getInsertElementData(isHorizontal, isDark, isRTL, backgroundColor) {
29147
29748
  var inserterColor = isDark ? INSERTER_COLOR_DARK_MODE : INSERTER_COLOR;
29148
- var outerDivStyle = "position: fixed; width: " + INSERTER_SIDE_LENGTH + "px; height: " + INSERTER_SIDE_LENGTH + "px; font-size: 16px; color: " + inserterColor + "; line-height: 10px; vertical-align: middle; text-align: center; cursor: pointer; border: solid " + INSERTER_BORDER_SIZE + "px " + inserterColor + "; border-radius: 50%; background-color: " + backgroundColor;
29749
+ var outerDivStyle = "position: fixed; width: " + INSERTER_SIDE_LENGTH + "px; height: " + INSERTER_SIDE_LENGTH + "px; font-size: 16px; color: " + inserterColor + "; line-height: 8px; vertical-align: middle; text-align: center; cursor: pointer; border: solid " + INSERTER_BORDER_SIZE + "px " + inserterColor + "; border-radius: 50%; background-color: " + backgroundColor;
29149
29750
  var leftOrRight = isRTL ? 'right' : 'left';
29150
29751
  var childBaseStyles = "position: absolute; box-sizing: border-box; background-color: " + backgroundColor + ";";
29151
29752
  var childInfo = {
@@ -29744,6 +30345,11 @@ var CompatibleChangeSource;
29744
30345
  * List chain reorganized numbers of lists
29745
30346
  */
29746
30347
  CompatibleChangeSource["ListChain"] = "ListChain";
30348
+ /**
30349
+ * Keyboard event, used by Content Model.
30350
+ * Data of this event will be the key code number
30351
+ */
30352
+ CompatibleChangeSource["Keyboard"] = "Keyboard";
29747
30353
  })(CompatibleChangeSource = exports.CompatibleChangeSource || (exports.CompatibleChangeSource = {}));
29748
30354
 
29749
30355