roosterjs 9.1.0 → 9.2.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
@@ -2095,7 +2095,7 @@ exports["default"] = getDarkColor;
2095
2095
 
2096
2096
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2097
2097
  exports.formatTextSegmentBeforeSelectionMarker = exports.formatSegmentWithContentModel = exports.formatParagraphWithContentModel = exports.formatImageWithContentModel = exports.formatTableWithContentModel = exports.clearSelectedCells = exports.insertTableColumn = exports.insertTableRow = exports.insertEntity = exports.toggleCode = exports.setParagraphMargin = exports.adjustImageSelection = exports.setImageAltText = exports.adjustLinkSelection = exports.removeLink = exports.insertLink = exports.clearFormat = exports.getFormatState = exports.changeImage = exports.setImageBoxShadow = exports.setImageBorder = exports.setSpacing = exports.toggleBlockQuote = exports.setHeadingLevel = exports.setDirection = exports.setAlignment = exports.setIndentation = exports.setListStartNumber = exports.setListStyle = exports.insertImage = exports.changeCapitalization = exports.applySegmentFormat = exports.changeFontSize = exports.setTextColor = exports.setFontSize = exports.setFontName = exports.setBackgroundColor = exports.toggleSuperscript = exports.toggleSubscript = exports.toggleStrikethrough = exports.toggleUnderline = exports.toggleItalic = exports.toggleBold = exports.toggleNumbering = exports.toggleBullet = exports.applyTableBorderFormat = exports.editTable = exports.setTableCellShade = exports.formatTable = exports.insertTable = void 0;
2098
- exports.matchLink = exports.setModelIndentation = exports.findListItemsInSameThread = exports.setModelListStartNumber = exports.setModelListStyle = exports.setListType = void 0;
2098
+ exports.getListAnnounceData = exports.matchLink = exports.setModelIndentation = exports.findListItemsInSameThread = exports.setModelListStartNumber = exports.setModelListStyle = exports.setListType = void 0;
2099
2099
  var insertTable_1 = __webpack_require__(/*! ./publicApi/table/insertTable */ "./packages/roosterjs-content-model-api/lib/publicApi/table/insertTable.ts");
2100
2100
  Object.defineProperty(exports, "insertTable", ({ enumerable: true, get: function () { return insertTable_1.insertTable; } }));
2101
2101
  var formatTable_1 = __webpack_require__(/*! ./publicApi/table/formatTable */ "./packages/roosterjs-content-model-api/lib/publicApi/table/formatTable.ts");
@@ -2208,6 +2208,8 @@ var setModelIndentation_1 = __webpack_require__(/*! ./modelApi/block/setModelInd
2208
2208
  Object.defineProperty(exports, "setModelIndentation", ({ enumerable: true, get: function () { return setModelIndentation_1.setModelIndentation; } }));
2209
2209
  var matchLink_1 = __webpack_require__(/*! ./modelApi/link/matchLink */ "./packages/roosterjs-content-model-api/lib/modelApi/link/matchLink.ts");
2210
2210
  Object.defineProperty(exports, "matchLink", ({ enumerable: true, get: function () { return matchLink_1.matchLink; } }));
2211
+ var getListAnnounceData_1 = __webpack_require__(/*! ./modelApi/list/getListAnnounceData */ "./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts");
2212
+ Object.defineProperty(exports, "getListAnnounceData", ({ enumerable: true, get: function () { return getListAnnounceData_1.getListAnnounceData; } }));
2211
2213
 
2212
2214
 
2213
2215
  /***/ }),
@@ -2374,7 +2376,9 @@ function setProperty(format, key, value) {
2374
2376
 
2375
2377
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2376
2378
  exports.setModelIndentation = void 0;
2379
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
2377
2380
  var findListItemsInSameThread_1 = __webpack_require__(/*! ../list/findListItemsInSameThread */ "./packages/roosterjs-content-model-api/lib/modelApi/list/findListItemsInSameThread.ts");
2381
+ var getListAnnounceData_1 = __webpack_require__(/*! ../list/getListAnnounceData */ "./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts");
2378
2382
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
2379
2383
  var IndentStepInPixel = 40;
2380
2384
  /**
@@ -2383,7 +2387,7 @@ var IndentStepInPixel = 40;
2383
2387
  * @param length The length of indentation in pixel, default value is 40
2384
2388
  * Set indentation for selected list items or paragraphs
2385
2389
  */
2386
- function setModelIndentation(model, indentation, length) {
2390
+ function setModelIndentation(model, indentation, length, context) {
2387
2391
  if (length === void 0) { length = IndentStepInPixel; }
2388
2392
  var paragraphOrListItem = (0, roosterjs_content_model_dom_1.getOperationalBlocks)(model, ['ListItem'], ['TableCell']);
2389
2393
  var isIndent = indentation == 'indent';
@@ -2430,6 +2434,9 @@ function setModelIndentation(model, indentation, length) {
2430
2434
  else {
2431
2435
  block.levels.pop();
2432
2436
  }
2437
+ if (block.levels.length > 0 && context) {
2438
+ context.announceData = (0, getListAnnounceData_1.getListAnnounceData)((0, tslib_1.__spreadArray)([block], (0, tslib_1.__read)(path), false));
2439
+ }
2433
2440
  }
2434
2441
  }
2435
2442
  else if (block) {
@@ -3130,9 +3137,9 @@ exports.findListItemsInSameThread = void 0;
3130
3137
  * @param currentItem The current list item
3131
3138
  * Search for all list items in the same thread as the current list item
3132
3139
  */
3133
- function findListItemsInSameThread(model, currentItem) {
3140
+ function findListItemsInSameThread(group, currentItem) {
3134
3141
  var items = [];
3135
- findListItems(model, items);
3142
+ findListItems(group, items);
3136
3143
  return filterListItems(items, currentItem);
3137
3144
  }
3138
3145
  exports.findListItemsInSameThread = findListItemsInSameThread;
@@ -3200,7 +3207,9 @@ function filterListItems(items, currentItem) {
3200
3207
  break;
3201
3208
  }
3202
3209
  }
3203
- else if (!isOrderedList || startNumberOverride) {
3210
+ else if (!isOrderedList ||
3211
+ startNumberOverride ||
3212
+ item.levels.length < currentItem.levels.length) {
3204
3213
  break;
3205
3214
  }
3206
3215
  }
@@ -3218,7 +3227,9 @@ function filterListItems(items, currentItem) {
3218
3227
  if (areListTypesCompatible(items, currentIndex, i) && !startNumberOverride) {
3219
3228
  result.push(item);
3220
3229
  }
3221
- else if (!isOrderedList || startNumberOverride) {
3230
+ else if (!isOrderedList ||
3231
+ startNumberOverride ||
3232
+ item.levels.length < currentItem.levels.length) {
3222
3233
  break;
3223
3234
  }
3224
3235
  }
@@ -3238,6 +3249,85 @@ function hasStartNumberOverride(item, levelLength) {
3238
3249
  }
3239
3250
 
3240
3251
 
3252
+ /***/ }),
3253
+
3254
+ /***/ "./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts":
3255
+ /*!***************************************************************************************!*\
3256
+ !*** ./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts ***!
3257
+ \***************************************************************************************/
3258
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
3259
+
3260
+ "use strict";
3261
+
3262
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
3263
+ exports.getListAnnounceData = void 0;
3264
+ var findListItemsInSameThread_1 = __webpack_require__(/*! ./findListItemsInSameThread */ "./packages/roosterjs-content-model-api/lib/modelApi/list/findListItemsInSameThread.ts");
3265
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
3266
+ /**
3267
+ * Get announce data for list item
3268
+ * @param path Content model path that include the list item
3269
+ * @returns Announce data of current list item if any, or null
3270
+ */
3271
+ function getListAnnounceData(path) {
3272
+ var index = (0, roosterjs_content_model_dom_1.getClosestAncestorBlockGroupIndex)(path, ['ListItem'], ['TableCell']);
3273
+ if (index >= 0) {
3274
+ var listItem = path[index];
3275
+ var level = listItem.levels[listItem.levels.length - 1];
3276
+ if (level.format.displayForDummyItem) {
3277
+ return null;
3278
+ }
3279
+ else if (level.listType == 'OL') {
3280
+ var listNumber = getListNumber(path, listItem);
3281
+ var metadata = (0, roosterjs_content_model_dom_1.updateListMetadata)(level);
3282
+ var listStyle = (0, roosterjs_content_model_dom_1.getAutoListStyleType)('OL', metadata !== null && metadata !== void 0 ? metadata : {}, listItem.levels.length - 1, level.format.listStyleType);
3283
+ return listStyle === undefined
3284
+ ? null
3285
+ : {
3286
+ defaultStrings: 'announceListItemNumbering',
3287
+ formatStrings: [(0, roosterjs_content_model_dom_1.getOrderedListNumberStr)(listStyle, listNumber)],
3288
+ };
3289
+ }
3290
+ else {
3291
+ return {
3292
+ defaultStrings: 'announceListItemBullet',
3293
+ };
3294
+ }
3295
+ }
3296
+ else {
3297
+ return null;
3298
+ }
3299
+ }
3300
+ exports.getListAnnounceData = getListAnnounceData;
3301
+ function getListNumber(path, listItem) {
3302
+ var _a, _b;
3303
+ var items = (0, findListItemsInSameThread_1.findListItemsInSameThread)(path[path.length - 1], listItem);
3304
+ var listNumber = 0;
3305
+ for (var i = 0; i < items.length; i++) {
3306
+ var item = items[i];
3307
+ if (listNumber == 0 && item.levels.length == listItem.levels.length) {
3308
+ listNumber = (_b = (_a = item.levels[item.levels.length - 1]) === null || _a === void 0 ? void 0 : _a.format.startNumberOverride) !== null && _b !== void 0 ? _b : 1;
3309
+ }
3310
+ if (item == listItem) {
3311
+ // Found current item, so break and return
3312
+ break;
3313
+ }
3314
+ else if (item.levels.length < listItem.levels.length) {
3315
+ // Found upper level item, reset list number
3316
+ listNumber = 0;
3317
+ }
3318
+ else if (item.levels.length > listItem.levels.length) {
3319
+ // Found deeper level item, skip
3320
+ continue;
3321
+ }
3322
+ else if (!item.levels[item.levels.length - 1].format.displayForDummyItem) {
3323
+ // Save level, and is not dummy, number plus one
3324
+ listNumber++;
3325
+ }
3326
+ }
3327
+ return listNumber;
3328
+ }
3329
+
3330
+
3241
3331
  /***/ }),
3242
3332
 
3243
3333
  /***/ "./packages/roosterjs-content-model-api/lib/modelApi/list/setListType.ts":
@@ -4992,6 +5082,8 @@ function insertImageWithSrc(editor, src) {
4992
5082
  (0, roosterjs_content_model_dom_1.mergeModel)(model, doc, context, {
4993
5083
  mergeFormat: 'mergeAll',
4994
5084
  });
5085
+ image.isSelected = true;
5086
+ (0, roosterjs_content_model_dom_1.setSelection)(model, image);
4995
5087
  return true;
4996
5088
  }, {
4997
5089
  apiName: 'insertImage',
@@ -6304,6 +6396,7 @@ var alignTableCell_1 = __webpack_require__(/*! ../../modelApi/table/alignTableCe
6304
6396
  */
6305
6397
  function editTable(editor, operation) {
6306
6398
  editor.focus();
6399
+ fixUpSafariSelection(editor);
6307
6400
  (0, formatTableWithContentModel_1.formatTableWithContentModel)(editor, 'editTable', function (tableModel) {
6308
6401
  switch (operation) {
6309
6402
  case 'alignCellLeft':
@@ -6359,6 +6452,22 @@ function editTable(editor, operation) {
6359
6452
  });
6360
6453
  }
6361
6454
  exports.editTable = editTable;
6455
+ // In safari, when open context menu under a table, it may expand the range selection to the beginning of next table cell.
6456
+ // So we make a workaround here to collapse the selection when need, to avoid unexpected table editing behavior
6457
+ // (e.g. insert two columns but actually need one only)
6458
+ function fixUpSafariSelection(editor) {
6459
+ if (editor.getEnvironment().isSafari) {
6460
+ var selection = editor.getDOMSelection();
6461
+ if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'range' && !selection.range.collapsed) {
6462
+ selection.range.collapse(true /*toStart*/);
6463
+ editor.setDOMSelection({
6464
+ type: 'range',
6465
+ range: selection.range,
6466
+ isReverted: false,
6467
+ });
6468
+ }
6469
+ }
6470
+ }
6362
6471
 
6363
6472
 
6364
6473
  /***/ }),
@@ -6740,7 +6849,8 @@ function formatSegmentWithContentModel(editor, apiName, toggleStyleCallback, seg
6740
6849
  segmentAndParagraphs[0][0].segmentType == 'SelectionMarker';
6741
6850
  if (isCollapsedSelection) {
6742
6851
  var para_1 = segmentAndParagraphs[0][1];
6743
- segmentAndParagraphs = (0, adjustWordSelection_1.adjustWordSelection)(model, segmentAndParagraphs[0][0]).map(function (x) { return [x, para_1]; });
6852
+ var path_1 = segmentAndParagraphs[0][2];
6853
+ segmentAndParagraphs = (0, adjustWordSelection_1.adjustWordSelection)(model, segmentAndParagraphs[0][0]).map(function (x) { return [x, para_1, path_1]; });
6744
6854
  if (segmentAndParagraphs.length > 1) {
6745
6855
  isCollapsedSelection = false;
6746
6856
  }
@@ -6842,8 +6952,10 @@ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-mo
6842
6952
  * Invoke a callback to format the text segment before the selection marker using Content Model
6843
6953
  * @param editor The editor object
6844
6954
  * @param callback The callback to format the text segment.
6955
+ * @returns True if the segment before cursor is found and callback is called, otherwise false
6845
6956
  */
6846
- function formatTextSegmentBeforeSelectionMarker(editor, callback) {
6957
+ function formatTextSegmentBeforeSelectionMarker(editor, callback, options) {
6958
+ var result = false;
6847
6959
  editor.formatContentModel(function (model, context) {
6848
6960
  var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /*includeFormatHolder*/);
6849
6961
  if (selectedSegmentsAndParagraphs.length > 0 && selectedSegmentsAndParagraphs[0][1]) {
@@ -6853,12 +6965,14 @@ function formatTextSegmentBeforeSelectionMarker(editor, callback) {
6853
6965
  if (marker.segmentType === 'SelectionMarker' && markerIndex > 0) {
6854
6966
  var previousSegment = paragraph.segments[markerIndex - 1];
6855
6967
  if (previousSegment && previousSegment.segmentType === 'Text') {
6968
+ result = true;
6856
6969
  return callback(model, previousSegment, paragraph, marker.format, context);
6857
6970
  }
6858
6971
  }
6859
6972
  }
6860
6973
  return false;
6861
- });
6974
+ }, options);
6975
+ return result;
6862
6976
  }
6863
6977
  exports.formatTextSegmentBeforeSelectionMarker = formatTextSegmentBeforeSelectionMarker;
6864
6978
 
@@ -8127,6 +8241,69 @@ function getPath(node, offset, rootNode) {
8127
8241
  exports.getPath = getPath;
8128
8242
 
8129
8243
 
8244
+ /***/ }),
8245
+
8246
+ /***/ "./packages/roosterjs-content-model-core/lib/coreApi/announce/announce.ts":
8247
+ /*!********************************************************************************!*\
8248
+ !*** ./packages/roosterjs-content-model-core/lib/coreApi/announce/announce.ts ***!
8249
+ \********************************************************************************/
8250
+ /***/ ((__unused_webpack_module, exports) => {
8251
+
8252
+ "use strict";
8253
+
8254
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
8255
+ exports.announce = void 0;
8256
+ /**
8257
+ * @internal
8258
+ * Announce the given data
8259
+ * @param core The EditorCore object
8260
+ * @param announceData Data to announce
8261
+ */
8262
+ var announce = function (core, announceData) {
8263
+ var _a;
8264
+ var text = announceData.text, defaultStrings = announceData.defaultStrings, _b = announceData.formatStrings, formatStrings = _b === void 0 ? [] : _b;
8265
+ var announcerStringGetter = core.lifecycle.announcerStringGetter;
8266
+ var template = defaultStrings && (announcerStringGetter === null || announcerStringGetter === void 0 ? void 0 : announcerStringGetter(defaultStrings));
8267
+ var textToAnnounce = formatString(template || text, formatStrings);
8268
+ if (textToAnnounce) {
8269
+ var announceContainer = core.lifecycle.announceContainer;
8270
+ if (!announceContainer || textToAnnounce == announceContainer.textContent) {
8271
+ (_a = announceContainer === null || announceContainer === void 0 ? void 0 : announceContainer.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(announceContainer);
8272
+ announceContainer = createAriaLiveElement(core.physicalRoot.ownerDocument);
8273
+ core.lifecycle.announceContainer = announceContainer;
8274
+ }
8275
+ if (announceContainer) {
8276
+ announceContainer.textContent = textToAnnounce;
8277
+ }
8278
+ }
8279
+ };
8280
+ exports.announce = announce;
8281
+ function formatString(text, formatStrings) {
8282
+ if (text == undefined) {
8283
+ return text;
8284
+ }
8285
+ text = text.replace(/\{(\d+)\}/g, function (_, sub) {
8286
+ var index = parseInt(sub);
8287
+ var replace = formatStrings[index];
8288
+ return replace !== null && replace !== void 0 ? replace : '';
8289
+ });
8290
+ return text;
8291
+ }
8292
+ function createAriaLiveElement(document) {
8293
+ var div = document.createElement('div');
8294
+ div.style.clip = 'rect(0px, 0px, 0px, 0px)';
8295
+ div.style.clipPath = 'inset(100%)';
8296
+ div.style.height = '1px';
8297
+ div.style.overflow = 'hidden';
8298
+ div.style.position = 'absolute';
8299
+ div.style.whiteSpace = 'nowrap';
8300
+ div.style.width = '1px';
8301
+ div.ariaLive = 'assertive';
8302
+ document.body.appendChild(div);
8303
+ return div;
8304
+ }
8305
+
8306
+
8130
8307
  /***/ }),
8131
8308
 
8132
8309
  /***/ "./packages/roosterjs-content-model-core/lib/coreApi/attachDomEvent/attachDomEvent.ts":
@@ -8186,6 +8363,7 @@ exports.attachDomEvent = attachDomEvent;
8186
8363
  Object.defineProperty(exports, "__esModule", ({ value: true }));
8187
8364
  exports.coreApiMap = void 0;
8188
8365
  var addUndoSnapshot_1 = __webpack_require__(/*! ./addUndoSnapshot/addUndoSnapshot */ "./packages/roosterjs-content-model-core/lib/coreApi/addUndoSnapshot/addUndoSnapshot.ts");
8366
+ var announce_1 = __webpack_require__(/*! ./announce/announce */ "./packages/roosterjs-content-model-core/lib/coreApi/announce/announce.ts");
8189
8367
  var attachDomEvent_1 = __webpack_require__(/*! ./attachDomEvent/attachDomEvent */ "./packages/roosterjs-content-model-core/lib/coreApi/attachDomEvent/attachDomEvent.ts");
8190
8368
  var createContentModel_1 = __webpack_require__(/*! ./createContentModel/createContentModel */ "./packages/roosterjs-content-model-core/lib/coreApi/createContentModel/createContentModel.ts");
8191
8369
  var createEditorContext_1 = __webpack_require__(/*! ./createEditorContext/createEditorContext */ "./packages/roosterjs-content-model-core/lib/coreApi/createEditorContext/createEditorContext.ts");
@@ -8220,6 +8398,7 @@ exports.coreApiMap = {
8220
8398
  switchShadowEdit: switchShadowEdit_1.switchShadowEdit,
8221
8399
  getVisibleViewport: getVisibleViewport_1.getVisibleViewport,
8222
8400
  setEditorStyle: setEditorStyle_1.setEditorStyle,
8401
+ announce: announce_1.announce,
8223
8402
  };
8224
8403
 
8225
8404
 
@@ -8303,17 +8482,12 @@ var createEditorContext = function (core, saveIndex) {
8303
8482
  var lifecycle = core.lifecycle, format = core.format, darkColorHandler = core.darkColorHandler, logicalRoot = core.logicalRoot, cache = core.cache, domHelper = core.domHelper;
8304
8483
  saveIndex = saveIndex && !core.lifecycle.shadowEditFragment;
8305
8484
  var context = (0, tslib_1.__assign)({ isDarkMode: lifecycle.isDarkMode, defaultFormat: format.defaultFormat, pendingFormat: (_a = format.pendingFormat) !== null && _a !== void 0 ? _a : undefined, darkColorHandler: darkColorHandler, addDelimiterForEntity: true, allowCacheElement: true, domIndexer: saveIndex ? cache.domIndexer : undefined, zoomScale: domHelper.calculateZoomScale() }, (0, getRootComputedStyleForContext_1.getRootComputedStyleForContext)(logicalRoot.ownerDocument));
8306
- checkRootRtl(logicalRoot, context);
8485
+ if (core.domHelper.isRightToLeft()) {
8486
+ context.isRootRtl = true;
8487
+ }
8307
8488
  return context;
8308
8489
  };
8309
8490
  exports.createEditorContext = createEditorContext;
8310
- function checkRootRtl(element, context) {
8311
- var _a;
8312
- var style = (_a = element === null || element === void 0 ? void 0 : element.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(element);
8313
- if ((style === null || style === void 0 ? void 0 : style.direction) == 'rtl') {
8314
- context.isRootRtl = true;
8315
- }
8316
- }
8317
8491
 
8318
8492
 
8319
8493
  /***/ }),
@@ -8461,19 +8635,19 @@ var formatContentModel = function (core, formatter, options, domToModelOptions)
8461
8635
  }
8462
8636
  handlePendingFormat(core, context, core.api.getDOMSelection(core));
8463
8637
  }
8638
+ if (context.announceData) {
8639
+ core.api.announce(core, context.announceData);
8640
+ }
8464
8641
  };
8465
8642
  exports.formatContentModel = formatContentModel;
8466
8643
  function handleImages(core, context) {
8467
8644
  if (context.newImages.length > 0) {
8468
- var viewport = core.api.getVisibleViewport(core);
8469
- if (viewport) {
8470
- var left = viewport.left, right = viewport.right;
8471
- var minMaxImageSize = 10;
8472
- var maxWidth_1 = Math.max(right - left, minMaxImageSize);
8473
- context.newImages.forEach(function (image) {
8474
- image.format.maxWidth = maxWidth_1 + "px";
8475
- });
8476
- }
8645
+ var width = core.domHelper.getClientWidth();
8646
+ var minMaxImageSize = 10;
8647
+ var maxWidth_1 = Math.max(width, minMaxImageSize);
8648
+ context.newImages.forEach(function (image) {
8649
+ image.format.maxWidth = maxWidth_1 + "px";
8650
+ });
8477
8651
  }
8478
8652
  }
8479
8653
  function handlePendingFormat(core, context, selection) {
@@ -8693,7 +8867,6 @@ exports.restoreSnapshotColors = restoreSnapshotColors;
8693
8867
  Object.defineProperty(exports, "__esModule", ({ value: true }));
8694
8868
  exports.restoreSnapshotHTML = void 0;
8695
8869
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
8696
- var BlockEntityContainer = '_E_EBlockEntityContainer';
8697
8870
  /**
8698
8871
  * @internal
8699
8872
  */
@@ -8745,22 +8918,19 @@ function tryGetEntityElement(entityMap, node) {
8745
8918
  var format = (0, roosterjs_content_model_dom_1.parseEntityFormat)(node);
8746
8919
  result = getEntityWrapperForReuse(entityMap, format.id);
8747
8920
  }
8748
- else if (isBlockEntityContainer(node)) {
8921
+ else if ((0, roosterjs_content_model_dom_1.isBlockEntityContainer)(node)) {
8749
8922
  result = tryGetEntityFromContainer(node, entityMap);
8750
8923
  }
8751
8924
  }
8752
8925
  return result;
8753
8926
  }
8754
- function isBlockEntityContainer(node) {
8755
- return node.classList.contains(BlockEntityContainer);
8756
- }
8757
8927
  function tryGetEntityFromContainer(element, entityMap) {
8758
8928
  var _a;
8759
8929
  for (var node = element.firstChild; node; node = node.nextSibling) {
8760
8930
  if ((0, roosterjs_content_model_dom_1.isEntityElement)(node) && (0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'ELEMENT_NODE')) {
8761
8931
  var format = (0, roosterjs_content_model_dom_1.parseEntityFormat)(node);
8762
8932
  var parent_1 = (_a = getEntityWrapperForReuse(entityMap, format.id)) === null || _a === void 0 ? void 0 : _a.parentElement;
8763
- return (0, roosterjs_content_model_dom_1.isNodeOfType)(parent_1, 'ELEMENT_NODE') && isBlockEntityContainer(parent_1)
8933
+ return (0, roosterjs_content_model_dom_1.isNodeOfType)(parent_1, 'ELEMENT_NODE') && (0, roosterjs_content_model_dom_1.isBlockEntityContainer)(parent_1)
8764
8934
  ? parent_1
8765
8935
  : null;
8766
8936
  }
@@ -9812,11 +9982,15 @@ function reconcileSelection(model, newSelection, oldSelection) {
9812
9982
  var newRange = newSelection.range;
9813
9983
  if (newRange) {
9814
9984
  var startContainer = newRange.startContainer, startOffset = newRange.startOffset, endContainer = newRange.endContainer, endOffset = newRange.endOffset, collapsed = newRange.collapsed;
9985
+ delete model.hasRevertedRangeSelection;
9815
9986
  if (collapsed) {
9816
9987
  return !!reconcileNodeSelection(startContainer, startOffset);
9817
9988
  }
9818
9989
  else if (startContainer == endContainer &&
9819
9990
  (0, roosterjs_content_model_dom_1.isNodeOfType)(startContainer, 'TEXT_NODE')) {
9991
+ if (newSelection.isReverted) {
9992
+ model.hasRevertedRangeSelection = true;
9993
+ }
9820
9994
  return (isIndexedSegment(startContainer) &&
9821
9995
  !!reconcileTextSelection(startContainer, startOffset, endOffset));
9822
9996
  }
@@ -9824,6 +9998,9 @@ function reconcileSelection(model, newSelection, oldSelection) {
9824
9998
  var marker1 = reconcileNodeSelection(startContainer, startOffset);
9825
9999
  var marker2 = reconcileNodeSelection(endContainer, endOffset);
9826
10000
  if (marker1 && marker2) {
10001
+ if (newSelection.isReverted) {
10002
+ model.hasRevertedRangeSelection = true;
10003
+ }
9827
10004
  (0, roosterjs_content_model_dom_1.setSelection)(model, marker1, marker2);
9828
10005
  return true;
9829
10006
  }
@@ -10287,8 +10464,8 @@ var CopyPastePlugin = /** @class */ (function () {
10287
10464
  return;
10288
10465
  }
10289
10466
  cleanUpAndRestoreSelection(tempDiv_1);
10290
- _this.editor.focus();
10291
10467
  _this.editor.setDOMSelection(selection);
10468
+ _this.editor.focus();
10292
10469
  if (isCut) {
10293
10470
  _this.editor.formatContentModel(function (model, context) {
10294
10471
  if ((0, roosterjs_content_model_dom_1.deleteSelection)(model, [deleteEmptyList_1.deleteEmptyList], context)
@@ -10955,6 +11132,123 @@ function createEntityPlugin() {
10955
11132
  exports.createEntityPlugin = createEntityPlugin;
10956
11133
 
10957
11134
 
11135
+ /***/ }),
11136
+
11137
+ /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/entity/adjustSelectionAroundEntity.ts":
11138
+ /*!****************************************************************************************************!*\
11139
+ !*** ./packages/roosterjs-content-model-core/lib/corePlugin/entity/adjustSelectionAroundEntity.ts ***!
11140
+ \****************************************************************************************************/
11141
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
11142
+
11143
+ "use strict";
11144
+
11145
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
11146
+ exports.adjustSelectionAroundEntity = void 0;
11147
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
11148
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
11149
+ /**
11150
+ * @internal
11151
+ */
11152
+ function adjustSelectionAroundEntity(editor, key, shiftKey) {
11153
+ var _a;
11154
+ var selection = editor.isDisposed() ? null : editor.getDOMSelection();
11155
+ if (!selection || selection.type != 'range') {
11156
+ return;
11157
+ }
11158
+ var range = selection.range, isReverted = selection.isReverted;
11159
+ var anchorNode = isReverted ? range.startContainer : range.endContainer;
11160
+ var offset = isReverted ? range.startOffset : range.endOffset;
11161
+ var delimiter = (0, roosterjs_content_model_dom_1.isNodeOfType)(anchorNode, 'ELEMENT_NODE')
11162
+ ? anchorNode
11163
+ : anchorNode.parentElement;
11164
+ var isRtl = delimiter &&
11165
+ ((_a = editor.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(delimiter).direction) == 'rtl';
11166
+ var movingBefore = (key == 'ArrowLeft') != !!isRtl;
11167
+ if (delimiter &&
11168
+ (((0, roosterjs_content_model_dom_1.isEntityDelimiter)(delimiter, !movingBefore) &&
11169
+ ((movingBefore && offset == 0) || (!movingBefore && offset == 1))) ||
11170
+ (0, roosterjs_content_model_dom_1.isBlockEntityContainer)(delimiter))) {
11171
+ editor.formatContentModel(function (model) {
11172
+ var _a, _b;
11173
+ var allSel = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /*includingFormatHolder*/, true /*includingEntity*/);
11174
+ var sel = allSel[isReverted ? 0 : allSel.length - 1];
11175
+ var index = (_b = (_a = sel === null || sel === void 0 ? void 0 : sel[1]) === null || _a === void 0 ? void 0 : _a.segments.indexOf(sel[0])) !== null && _b !== void 0 ? _b : -1;
11176
+ if (sel && sel[1] && index >= 0) {
11177
+ var _c = (0, tslib_1.__read)(sel, 3), segment = _c[0], paragraph = _c[1], path = _c[2];
11178
+ var isShrinking = shiftKey && !range.collapsed && movingBefore != !!isReverted;
11179
+ var entitySegment = isShrinking
11180
+ ? segment
11181
+ : paragraph.segments[movingBefore ? index - 1 : index + 1];
11182
+ var pairedDelimiter = findPairedDelimiter(entitySegment, path, paragraph, movingBefore);
11183
+ if (pairedDelimiter) {
11184
+ var newRange = getNewRange(range, isShrinking, movingBefore, pairedDelimiter, shiftKey);
11185
+ editor.setDOMSelection({
11186
+ type: 'range',
11187
+ range: newRange,
11188
+ isReverted: newRange.collapsed ? false : isReverted,
11189
+ });
11190
+ }
11191
+ }
11192
+ return false;
11193
+ });
11194
+ }
11195
+ }
11196
+ exports.adjustSelectionAroundEntity = adjustSelectionAroundEntity;
11197
+ function getNewRange(originalRange, isShrinking, movingBefore, pairedDelimiter, shiftKey) {
11198
+ var newRange = originalRange.cloneRange();
11199
+ if (isShrinking) {
11200
+ if (movingBefore) {
11201
+ newRange.setEndBefore(pairedDelimiter);
11202
+ }
11203
+ else {
11204
+ newRange.setStartAfter(pairedDelimiter);
11205
+ }
11206
+ }
11207
+ else {
11208
+ if (movingBefore) {
11209
+ newRange.setStartBefore(pairedDelimiter);
11210
+ }
11211
+ else {
11212
+ newRange.setEndAfter(pairedDelimiter);
11213
+ }
11214
+ if (!shiftKey) {
11215
+ if (movingBefore) {
11216
+ newRange.setEndBefore(pairedDelimiter);
11217
+ }
11218
+ else {
11219
+ newRange.setStartAfter(pairedDelimiter);
11220
+ }
11221
+ }
11222
+ }
11223
+ return newRange;
11224
+ }
11225
+ function findPairedDelimiter(entitySegment, path, paragraph, movingBefore) {
11226
+ var entity = null;
11227
+ if ((entitySegment === null || entitySegment === void 0 ? void 0 : entitySegment.segmentType) == 'Entity') {
11228
+ // Inline entity
11229
+ entity = entitySegment;
11230
+ }
11231
+ else {
11232
+ // Block entity
11233
+ var blocks = path[0].blocks;
11234
+ var paraIndex = blocks.indexOf(paragraph);
11235
+ var entityBlock = paraIndex >= 0 ? blocks[movingBefore ? paraIndex - 1 : paraIndex + 1] : null;
11236
+ if ((entityBlock === null || entityBlock === void 0 ? void 0 : entityBlock.blockType) == 'Entity') {
11237
+ entity = entityBlock;
11238
+ }
11239
+ }
11240
+ var pairedDelimiter = entity
11241
+ ? movingBefore
11242
+ ? entity.wrapper.previousElementSibling
11243
+ : entity.wrapper.nextElementSibling
11244
+ : null;
11245
+ return (0, roosterjs_content_model_dom_1.isNodeOfType)(pairedDelimiter, 'ELEMENT_NODE') &&
11246
+ (0, roosterjs_content_model_dom_1.isEntityDelimiter)(pairedDelimiter, movingBefore)
11247
+ ? pairedDelimiter
11248
+ : null;
11249
+ }
11250
+
11251
+
10958
11252
  /***/ }),
10959
11253
 
10960
11254
  /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/entity/entityDelimiterUtils.ts":
@@ -10968,6 +11262,7 @@ exports.createEntityPlugin = createEntityPlugin;
10968
11262
  Object.defineProperty(exports, "__esModule", ({ value: true }));
10969
11263
  exports.handleEnterInlineEntity = exports.handleKeyDownInBlockDelimiter = exports.handleDelimiterKeyDownEvent = exports.handleCompositionEndEvent = exports.handleDelimiterContentChangedEvent = exports.preventTypeInDelimiter = void 0;
10970
11264
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
11265
+ var adjustSelectionAroundEntity_1 = __webpack_require__(/*! ./adjustSelectionAroundEntity */ "./packages/roosterjs-content-model-core/lib/corePlugin/entity/adjustSelectionAroundEntity.ts");
10971
11266
  var normalizePos_1 = __webpack_require__(/*! ../selection/normalizePos */ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/normalizePos.ts");
10972
11267
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
10973
11268
  var DelimiterBefore = 'entityDelimiterBefore';
@@ -10976,8 +11271,6 @@ var DelimiterSelector = '.' + DelimiterAfter + ',.' + DelimiterBefore;
10976
11271
  var ZeroWidthSpace = '\u200B';
10977
11272
  var EntityInfoName = '_Entity';
10978
11273
  var InlineEntitySelector = 'span.' + EntityInfoName;
10979
- var BlockEntityContainer = '_E_EBlockEntityContainer';
10980
- var BlockEntityContainerSelector = '.' + BlockEntityContainer;
10981
11274
  /**
10982
11275
  * @internal exported only for unit test
10983
11276
  */
@@ -11119,61 +11412,86 @@ exports.handleCompositionEndEvent = handleCompositionEndEvent;
11119
11412
  function handleDelimiterKeyDownEvent(editor, event) {
11120
11413
  var _a;
11121
11414
  var selection = editor.getDOMSelection();
11122
- var rawEvent = event.rawEvent;
11123
11415
  if (!selection || selection.type != 'range') {
11124
11416
  return;
11125
11417
  }
11126
- var isEnter = rawEvent.key === 'Enter';
11127
- var helper = editor.getDOMHelper();
11128
- if (selection.range.collapsed && ((0, roosterjs_content_model_dom_1.isCharacterValue)(rawEvent) || isEnter)) {
11129
- var helper_1 = editor.getDOMHelper();
11130
- var node_1 = getFocusedElement(selection);
11131
- if (node_1 && (0, roosterjs_content_model_dom_1.isEntityDelimiter)(node_1) && helper_1.isNodeInEditor(node_1)) {
11132
- var blockEntityContainer = node_1.closest(BlockEntityContainerSelector);
11133
- if (blockEntityContainer && helper_1.isNodeInEditor(blockEntityContainer)) {
11134
- var isAfter = node_1.classList.contains(DelimiterAfter);
11135
- if (isAfter) {
11136
- selection.range.setStartAfter(blockEntityContainer);
11137
- }
11138
- else {
11139
- selection.range.setStartBefore(blockEntityContainer);
11140
- }
11141
- selection.range.collapse(true /* toStart */);
11142
- if (isEnter) {
11143
- event.rawEvent.preventDefault();
11418
+ var rawEvent = event.rawEvent;
11419
+ var range = selection.range;
11420
+ var key = rawEvent.key;
11421
+ switch (key) {
11422
+ case 'Enter':
11423
+ if (range.collapsed) {
11424
+ handleInputOnDelimiter(editor, range, getFocusedElement(selection), rawEvent);
11425
+ }
11426
+ else {
11427
+ var helper = editor.getDOMHelper();
11428
+ var entity = (0, roosterjs_content_model_dom_1.findClosestEntityWrapper)(range.startContainer, helper);
11429
+ if (entity &&
11430
+ (0, roosterjs_content_model_dom_1.isNodeOfType)(entity, 'ELEMENT_NODE') &&
11431
+ helper.isNodeInEditor(entity)) {
11432
+ triggerEntityEventOnEnter(editor, entity, rawEvent);
11144
11433
  }
11145
- editor.formatContentModel(exports.handleKeyDownInBlockDelimiter, {
11146
- selectionOverride: {
11147
- type: 'range',
11148
- isReverted: false,
11149
- range: selection.range,
11150
- },
11434
+ }
11435
+ break;
11436
+ case 'ArrowLeft':
11437
+ case 'ArrowRight':
11438
+ if (!rawEvent.altKey && !rawEvent.ctrlKey && !rawEvent.metaKey) {
11439
+ // Handle in async so focus is already moved, this makes us easier to check if we should adjust the selection
11440
+ (_a = editor.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.requestAnimationFrame(function () {
11441
+ (0, adjustSelectionAroundEntity_1.adjustSelectionAroundEntity)(editor, key, rawEvent.shiftKey);
11151
11442
  });
11152
11443
  }
11444
+ break;
11445
+ default:
11446
+ if ((0, roosterjs_content_model_dom_1.isCharacterValue)(rawEvent) && range.collapsed) {
11447
+ handleInputOnDelimiter(editor, range, getFocusedElement(selection), rawEvent);
11448
+ }
11449
+ break;
11450
+ }
11451
+ }
11452
+ exports.handleDelimiterKeyDownEvent = handleDelimiterKeyDownEvent;
11453
+ function handleInputOnDelimiter(editor, range, focusedNode, rawEvent) {
11454
+ var _a;
11455
+ var helper = editor.getDOMHelper();
11456
+ if (focusedNode && (0, roosterjs_content_model_dom_1.isEntityDelimiter)(focusedNode) && helper.isNodeInEditor(focusedNode)) {
11457
+ var blockEntityContainer = (0, roosterjs_content_model_dom_1.findClosestBlockEntityContainer)(focusedNode, helper);
11458
+ var isEnter = rawEvent.key === 'Enter';
11459
+ if (blockEntityContainer && helper.isNodeInEditor(blockEntityContainer)) {
11460
+ var isAfter = focusedNode.classList.contains(DelimiterAfter);
11461
+ if (isAfter) {
11462
+ range.setStartAfter(blockEntityContainer);
11463
+ }
11153
11464
  else {
11154
- if (isEnter) {
11155
- event.rawEvent.preventDefault();
11156
- editor.formatContentModel(exports.handleEnterInlineEntity);
11157
- }
11158
- else {
11159
- editor.takeSnapshot();
11160
- (_a = editor
11161
- .getDocument()
11162
- .defaultView) === null || _a === void 0 ? void 0 : _a.requestAnimationFrame(function () {
11163
- return preventTypeInDelimiter(node_1, editor);
11164
- });
11165
- }
11465
+ range.setStartBefore(blockEntityContainer);
11466
+ }
11467
+ range.collapse(true /* toStart */);
11468
+ if (isEnter) {
11469
+ rawEvent.preventDefault();
11166
11470
  }
11471
+ editor.formatContentModel(exports.handleKeyDownInBlockDelimiter, {
11472
+ selectionOverride: {
11473
+ type: 'range',
11474
+ isReverted: false,
11475
+ range: range,
11476
+ },
11477
+ });
11167
11478
  }
11168
- }
11169
- else if (isEnter) {
11170
- var entity = (0, roosterjs_content_model_dom_1.findClosestEntityWrapper)(selection.range.startContainer, helper);
11171
- if (entity && (0, roosterjs_content_model_dom_1.isNodeOfType)(entity, 'ELEMENT_NODE') && helper.isNodeInEditor(entity)) {
11172
- triggerEntityEventOnEnter(editor, entity, rawEvent);
11479
+ else {
11480
+ if (isEnter) {
11481
+ rawEvent.preventDefault();
11482
+ editor.formatContentModel(exports.handleEnterInlineEntity);
11483
+ }
11484
+ else {
11485
+ editor.takeSnapshot();
11486
+ (_a = editor
11487
+ .getDocument()
11488
+ .defaultView) === null || _a === void 0 ? void 0 : _a.requestAnimationFrame(function () {
11489
+ return preventTypeInDelimiter(focusedNode, editor);
11490
+ });
11491
+ }
11173
11492
  }
11174
11493
  }
11175
11494
  }
11176
- exports.handleDelimiterKeyDownEvent = handleDelimiterKeyDownEvent;
11177
11495
  /**
11178
11496
  * @internal Exported Only for unit test
11179
11497
  * @returns
@@ -11668,6 +11986,7 @@ var LifecyclePlugin = /** @class */ (function () {
11668
11986
  isDarkMode: !!options.inDarkMode,
11669
11987
  shadowEditFragment: null,
11670
11988
  styleElements: {},
11989
+ announcerStringGetter: options.announcerStringGetter,
11671
11990
  };
11672
11991
  }
11673
11992
  /**
@@ -11695,7 +12014,7 @@ var LifecyclePlugin = /** @class */ (function () {
11695
12014
  */
11696
12015
  LifecyclePlugin.prototype.dispose = function () {
11697
12016
  var _this = this;
11698
- var _a;
12017
+ var _a, _b;
11699
12018
  (_a = this.editor) === null || _a === void 0 ? void 0 : _a.triggerEvent('beforeDispose', {}, true /*broadcast*/);
11700
12019
  (0, roosterjs_content_model_dom_1.getObjectKeys)(this.state.styleElements).forEach(function (key) {
11701
12020
  var _a;
@@ -11703,6 +12022,11 @@ var LifecyclePlugin = /** @class */ (function () {
11703
12022
  (_a = element.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(element);
11704
12023
  delete _this.state.styleElements[key];
11705
12024
  });
12025
+ var announceContainer = this.state.announceContainer;
12026
+ if (announceContainer) {
12027
+ (_b = announceContainer.parentElement) === null || _b === void 0 ? void 0 : _b.removeChild(announceContainer);
12028
+ delete this.state.announceContainer;
12029
+ }
11706
12030
  if (this.disposer) {
11707
12031
  this.disposer();
11708
12032
  this.disposer = null;
@@ -12086,14 +12410,14 @@ var SelectionPlugin = /** @class */ (function () {
12086
12410
  return rawEvent.shiftKey ? 'TabLeft' : 'TabRight';
12087
12411
  };
12088
12412
  SelectionPlugin.prototype.handleSelectionInTable = function (key) {
12089
- var _a, _b, _c, _d;
12413
+ var _a, _b, _c, _d, _e, _f;
12090
12414
  if (!this.editor || !this.state.tableSelection) {
12091
12415
  return;
12092
12416
  }
12093
12417
  var selection = this.editor.getDOMSelection();
12094
12418
  var domHelper = this.editor.getDOMHelper();
12095
12419
  if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'range') {
12096
- var _e = selection.range, collapsed = _e.collapsed, startContainer = _e.startContainer, endContainer = _e.endContainer, commonAncestorContainer = _e.commonAncestorContainer, isReverted = selection.isReverted;
12420
+ var _g = selection.range, collapsed = _g.collapsed, startContainer = _g.startContainer, endContainer = _g.endContainer, commonAncestorContainer = _g.commonAncestorContainer, isReverted = selection.isReverted;
12097
12421
  var start = isReverted ? endContainer : startContainer;
12098
12422
  var end = isReverted ? startContainer : endContainer;
12099
12423
  var tableSel = this.parseTableSelection(commonAncestorContainer, start, domHelper);
@@ -12101,7 +12425,7 @@ var SelectionPlugin = /** @class */ (function () {
12101
12425
  return;
12102
12426
  }
12103
12427
  var lastCo = (0, findCoordinate_1.findCoordinate)(tableSel === null || tableSel === void 0 ? void 0 : tableSel.parsedTable, end, domHelper);
12104
- var _f = this.state.tableSelection, parsedTable = _f.parsedTable, oldCo = _f.firstCo, table = _f.table;
12428
+ var _h = this.state.tableSelection, parsedTable = _h.parsedTable, oldCo = _h.firstCo, table = _h.table;
12105
12429
  if (lastCo && tableSel.table == table) {
12106
12430
  if (lastCo.col != oldCo.col && (key == Up || key == Down)) {
12107
12431
  var change = key == Up ? -1 : 1;
@@ -12139,6 +12463,8 @@ var SelectionPlugin = /** @class */ (function () {
12139
12463
  var cell = parsedTable[row][col];
12140
12464
  if (typeof cell != 'string') {
12141
12465
  this.setRangeSelectionInTable(cell, 0, this.editor);
12466
+ lastCo.row = row;
12467
+ lastCo.col = col;
12142
12468
  break;
12143
12469
  }
12144
12470
  }
@@ -12146,6 +12472,13 @@ var SelectionPlugin = /** @class */ (function () {
12146
12472
  else {
12147
12473
  this.state.tableSelection = null;
12148
12474
  }
12475
+ if (collapsed &&
12476
+ (lastCo.col != oldCo.col || lastCo.row != oldCo.row) &&
12477
+ lastCo.row >= 0 &&
12478
+ lastCo.row == parsedTable.length - 1 &&
12479
+ lastCo.col == ((_e = parsedTable[lastCo.row]) === null || _e === void 0 ? void 0 : _e.length) - 1) {
12480
+ (_f = this.editor) === null || _f === void 0 ? void 0 : _f.announce({ defaultStrings: 'announceOnFocusLastCell' });
12481
+ }
12149
12482
  }
12150
12483
  if (!collapsed && lastCo) {
12151
12484
  this.state.tableSelection = tableSel;
@@ -13098,6 +13431,14 @@ var Editor = /** @class */ (function () {
13098
13431
  var core = this.getCore();
13099
13432
  core.api.setEditorStyle(core, key, cssRule, subSelectors);
13100
13433
  };
13434
+ /**
13435
+ * Announce the given data
13436
+ * @param announceData Data to announce
13437
+ */
13438
+ Editor.prototype.announce = function (announceData) {
13439
+ var core = this.getCore();
13440
+ core.api.announce(core, announceData);
13441
+ };
13101
13442
  /**
13102
13443
  * @returns the current EditorCore object
13103
13444
  * @throws a standard Error if there's no core object
@@ -13178,6 +13519,26 @@ var DOMHelperImpl = /** @class */ (function () {
13178
13519
  var activeElement = this.contentDiv.ownerDocument.activeElement;
13179
13520
  return !!(activeElement && this.contentDiv.contains(activeElement));
13180
13521
  };
13522
+ /**
13523
+ * Check if the root element is in RTL mode
13524
+ */
13525
+ DOMHelperImpl.prototype.isRightToLeft = function () {
13526
+ var _a;
13527
+ var contentDiv = this.contentDiv;
13528
+ var style = (_a = contentDiv.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(contentDiv);
13529
+ return (style === null || style === void 0 ? void 0 : style.direction) == 'rtl';
13530
+ };
13531
+ /**
13532
+ * Get the width of the editable area of the editor content div
13533
+ */
13534
+ DOMHelperImpl.prototype.getClientWidth = function () {
13535
+ var _a;
13536
+ var contentDiv = this.contentDiv;
13537
+ var style = (_a = contentDiv.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(contentDiv);
13538
+ var paddingLeft = (0, roosterjs_content_model_dom_1.parseValueWithUnit)(style === null || style === void 0 ? void 0 : style.paddingLeft);
13539
+ var paddingRight = (0, roosterjs_content_model_dom_1.parseValueWithUnit)(style === null || style === void 0 ? void 0 : style.paddingRight);
13540
+ return this.contentDiv.clientWidth - (paddingLeft + paddingRight);
13541
+ };
13181
13542
  return DOMHelperImpl;
13182
13543
  }());
13183
13544
  /**
@@ -13468,95 +13829,24 @@ exports.containerSizeFormatParser = containerSizeFormatParser;
13468
13829
 
13469
13830
  Object.defineProperty(exports, "__esModule", ({ value: true }));
13470
13831
  exports.listLevelMetadataApplier = exports.listItemMetadataApplier = void 0;
13471
- var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
13472
13832
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
13473
- var DefaultOrderedListStyles = ['decimal', 'lower-alpha', 'lower-roman'];
13474
- var DefaultUnorderedListStyles = ['disc', 'circle', 'square'];
13475
13833
  var OrderedMapPlaceholderRegex = /\$\{(\w+)\}/;
13476
- var CharCodeOfA = 65;
13477
- var RomanValues = {
13478
- M: 1000,
13479
- CM: 900,
13480
- D: 500,
13481
- CD: 400,
13482
- C: 100,
13483
- XC: 90,
13484
- L: 50,
13485
- XL: 40,
13486
- X: 10,
13487
- IX: 9,
13488
- V: 5,
13489
- IV: 4,
13490
- I: 1,
13491
- };
13492
- function getOrderedListStyleValue(template, listNumber) {
13493
- return template
13494
- ? template.replace(OrderedMapPlaceholderRegex, function (_, subStr) {
13495
- switch (subStr) {
13496
- case 'Number':
13497
- return listNumber + '';
13498
- case 'LowerAlpha':
13499
- return convertDecimalsToAlpha(listNumber, true /*isLowerCase*/);
13500
- case 'UpperAlpha':
13501
- return convertDecimalsToAlpha(listNumber, false /*isLowerCase*/);
13502
- case 'LowerRoman':
13503
- return convertDecimalsToRoman(listNumber, true /*isLowerCase*/);
13504
- case 'UpperRoman':
13505
- return convertDecimalsToRoman(listNumber, false /*isLowerCase*/);
13506
- }
13507
- return '';
13508
- })
13509
- : undefined;
13510
- }
13511
- function convertDecimalsToAlpha(decimal, isLowerCase) {
13512
- var alpha = '';
13513
- decimal--;
13514
- while (decimal >= 0) {
13515
- alpha = String.fromCharCode((decimal % 26) + CharCodeOfA) + alpha;
13516
- decimal = Math.floor(decimal / 26) - 1;
13517
- }
13518
- return isLowerCase ? alpha.toLowerCase() : alpha;
13519
- }
13520
- function convertDecimalsToRoman(decimal, isLowerCase) {
13521
- var e_1, _a;
13522
- var romanValue = '';
13523
- try {
13524
- for (var _b = (0, tslib_1.__values)((0, roosterjs_content_model_dom_1.getObjectKeys)(RomanValues)), _c = _b.next(); !_c.done; _c = _b.next()) {
13525
- var i = _c.value;
13526
- var timesRomanCharAppear = Math.floor(decimal / RomanValues[i]);
13527
- decimal = decimal - timesRomanCharAppear * RomanValues[i];
13528
- romanValue = romanValue + i.repeat(timesRomanCharAppear);
13529
- }
13530
- }
13531
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
13532
- finally {
13533
- try {
13534
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
13535
- }
13536
- finally { if (e_1) throw e_1.error; }
13537
- }
13538
- return isLowerCase ? romanValue.toLocaleLowerCase() : romanValue;
13539
- }
13540
- function shouldApplyToItem(listStyleType) {
13541
- return listStyleType.indexOf('"') >= 0;
13542
- }
13543
- function getRawListStyleType(listType, metadata, depth) {
13544
- var orderedStyleType = metadata.orderedStyleType, unorderedStyleType = metadata.unorderedStyleType, applyListStyleFromLevel = metadata.applyListStyleFromLevel;
13834
+ function getListStyleValue(listType, listStyleType, listNumber) {
13545
13835
  if (listType == 'OL') {
13546
- return typeof orderedStyleType == 'number'
13547
- ? roosterjs_content_model_dom_1.OrderedListStyleMap[orderedStyleType]
13548
- : applyListStyleFromLevel
13549
- ? DefaultOrderedListStyles[depth % DefaultOrderedListStyles.length]
13550
- : undefined;
13836
+ var numberStr = (0, roosterjs_content_model_dom_1.getOrderedListNumberStr)(listStyleType, listNumber !== null && listNumber !== void 0 ? listNumber : 1);
13837
+ var template = roosterjs_content_model_dom_1.OrderedListStyleMap[listStyleType];
13838
+ return template ? template.replace(OrderedMapPlaceholderRegex, numberStr) : undefined;
13551
13839
  }
13552
13840
  else {
13553
- return typeof unorderedStyleType == 'number'
13554
- ? roosterjs_content_model_dom_1.UnorderedListStyleMap[unorderedStyleType]
13555
- : applyListStyleFromLevel
13556
- ? DefaultUnorderedListStyles[depth % DefaultUnorderedListStyles.length]
13557
- : undefined;
13841
+ return roosterjs_content_model_dom_1.UnorderedListStyleMap[listStyleType];
13558
13842
  }
13559
13843
  }
13844
+ function shouldApplyToItem(listStyleType, listType) {
13845
+ var style = listType == 'OL'
13846
+ ? roosterjs_content_model_dom_1.OrderedListStyleMap[listStyleType]
13847
+ : roosterjs_content_model_dom_1.UnorderedListStyleMap[listStyleType];
13848
+ return (style === null || style === void 0 ? void 0 : style.indexOf('"')) >= 0;
13849
+ }
13560
13850
  /**
13561
13851
  * @internal
13562
13852
  */
@@ -13567,13 +13857,10 @@ exports.listItemMetadataApplier = {
13567
13857
  var depth = context.listFormat.nodeStack.length - 2; // Minus two for the parent element and convert length to index
13568
13858
  if (depth >= 0) {
13569
13859
  var listType = (_a = context.listFormat.nodeStack[depth + 1].listType) !== null && _a !== void 0 ? _a : 'OL';
13570
- var listStyleType = getRawListStyleType(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13571
- if (listStyleType) {
13572
- if (shouldApplyToItem(listStyleType)) {
13573
- format.listStyleType =
13574
- listType == 'OL'
13575
- ? getOrderedListStyleValue(listStyleType, context.listFormat.threadItemCounts[depth])
13576
- : listStyleType;
13860
+ var listStyleType = (0, roosterjs_content_model_dom_1.getAutoListStyleType)(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13861
+ if (listStyleType !== undefined) {
13862
+ if (shouldApplyToItem(listStyleType, listType)) {
13863
+ format.listStyleType = getListStyleValue(listType, listStyleType, context.listFormat.threadItemCounts[depth]);
13577
13864
  }
13578
13865
  else {
13579
13866
  delete format.listStyleType;
@@ -13592,10 +13879,13 @@ exports.listLevelMetadataApplier = {
13592
13879
  var depth = context.listFormat.nodeStack.length - 2; // Minus two for the parent element and convert length to index
13593
13880
  if (depth >= 0) {
13594
13881
  var listType = (_a = context.listFormat.nodeStack[depth + 1].listType) !== null && _a !== void 0 ? _a : 'OL';
13595
- var listStyleType = getRawListStyleType(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13596
- if (listStyleType) {
13597
- if (!shouldApplyToItem(listStyleType)) {
13598
- format.listStyleType = listStyleType;
13882
+ var listStyleType = (0, roosterjs_content_model_dom_1.getAutoListStyleType)(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13883
+ if (listStyleType !== undefined) {
13884
+ if (!shouldApplyToItem(listStyleType, listType)) {
13885
+ var listStyleTypeFormat = getListStyleValue(listType, listStyleType, context.listFormat.threadItemCounts[depth]);
13886
+ if (listStyleTypeFormat) {
13887
+ format.listStyleType = listStyleTypeFormat;
13888
+ }
13599
13889
  }
13600
13890
  else {
13601
13891
  delete format.listStyleType;
@@ -14161,7 +14451,11 @@ exports.ChangeSource = {
14161
14451
  * Data of this event will be the key code number
14162
14452
  */
14163
14453
  Keyboard: 'Keyboard',
14164
- };
14454
+ /**
14455
+ * Content changed by auto format
14456
+ */
14457
+ AutoFormat: 'AutoFormat',
14458
+ };
14165
14459
 
14166
14460
 
14167
14461
  /***/ }),
@@ -14651,7 +14945,11 @@ var normalizeContentModel_1 = __webpack_require__(/*! ../modelApi/common/normali
14651
14945
  * @returns A ContentModelDocument object that contains all the models created from the give root element
14652
14946
  */
14653
14947
  function domToContentModel(root, context) {
14948
+ var _a;
14654
14949
  var model = (0, createContentModelDocument_1.createContentModelDocument)(context.defaultFormat);
14950
+ if (((_a = context.selection) === null || _a === void 0 ? void 0 : _a.type) == 'range' && context.selection.isReverted) {
14951
+ model.hasRevertedRangeSelection = true;
14952
+ }
14655
14953
  context.elementProcessors.child(model, root, context);
14656
14954
  (0, normalizeContentModel_1.normalizeContentModel)(model);
14657
14955
  return model;
@@ -16249,19 +16547,22 @@ function stackFormatInternal(format, processType) {
16249
16547
  "use strict";
16250
16548
 
16251
16549
  Object.defineProperty(exports, "__esModule", ({ value: true }));
16252
- exports.addDelimiters = exports.isEntityDelimiter = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestEntityWrapper = exports.isEntityElement = void 0;
16550
+ exports.addDelimiters = exports.isBlockEntityContainer = exports.isEntityDelimiter = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestBlockEntityContainer = exports.findClosestEntityWrapper = exports.isEntityElement = void 0;
16253
16551
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
16254
16552
  var applyFormat_1 = __webpack_require__(/*! ../modelToDom/utils/applyFormat */ "./packages/roosterjs-content-model-dom/lib/modelToDom/utils/applyFormat.ts");
16255
16553
  var isElementOfType_1 = __webpack_require__(/*! ./isElementOfType */ "./packages/roosterjs-content-model-dom/lib/domUtils/isElementOfType.ts");
16256
16554
  var isNodeOfType_1 = __webpack_require__(/*! ./isNodeOfType */ "./packages/roosterjs-content-model-dom/lib/domUtils/isNodeOfType.ts");
16257
16555
  var toArray_1 = __webpack_require__(/*! ./toArray */ "./packages/roosterjs-content-model-dom/lib/domUtils/toArray.ts");
16258
16556
  var ENTITY_INFO_NAME = '_Entity';
16557
+ var ENTITY_INFO_SELECTOR = '.' + ENTITY_INFO_NAME;
16259
16558
  var ENTITY_TYPE_PREFIX = '_EType_';
16260
16559
  var ENTITY_ID_PREFIX = '_EId_';
16261
16560
  var ENTITY_READONLY_PREFIX = '_EReadonly_';
16262
16561
  var ZERO_WIDTH_SPACE = '\u200B';
16263
16562
  var DELIMITER_BEFORE = 'entityDelimiterBefore';
16264
16563
  var DELIMITER_AFTER = 'entityDelimiterAfter';
16564
+ var BLOCK_ENTITY_CONTAINER = '_E_EBlockEntityContainer';
16565
+ var BLOCK_ENTITY_CONTAINER_SELECTOR = '.' + BLOCK_ENTITY_CONTAINER;
16265
16566
  /**
16266
16567
  * Check if the given DOM Node is an entity wrapper element
16267
16568
  */
@@ -16275,9 +16576,19 @@ exports.isEntityElement = isEntityElement;
16275
16576
  * @param domHelper The DOM helper to use
16276
16577
  */
16277
16578
  function findClosestEntityWrapper(startNode, domHelper) {
16278
- return domHelper.findClosestElementAncestor(startNode, "." + ENTITY_INFO_NAME);
16579
+ return domHelper.findClosestElementAncestor(startNode, ENTITY_INFO_SELECTOR);
16279
16580
  }
16280
16581
  exports.findClosestEntityWrapper = findClosestEntityWrapper;
16582
+ /**
16583
+ * Find the closest block entity wrapper element from a given DOM node
16584
+ * @param node The node to start looking for entity container
16585
+ * @param domHelper The DOM helper
16586
+ * @returns
16587
+ */
16588
+ function findClosestBlockEntityContainer(node, domHelper) {
16589
+ return domHelper.findClosestElementAncestor(node, BLOCK_ENTITY_CONTAINER_SELECTOR);
16590
+ }
16591
+ exports.findClosestBlockEntityContainer = findClosestBlockEntityContainer;
16281
16592
  /**
16282
16593
  * Get all entity wrapper elements under the given root element
16283
16594
  * @param root The root element to query from
@@ -16339,15 +16650,27 @@ exports.generateEntityClassNames = generateEntityClassNames;
16339
16650
  /**
16340
16651
  * Checks whether the node provided is a Entity delimiter
16341
16652
  * @param node the node to check
16653
+ * @param isBefore True to match delimiter before entity only, false to match delimiter after entity, or undefined means match both
16342
16654
  * @return true if it is a delimiter
16343
16655
  */
16344
- function isEntityDelimiter(element) {
16656
+ function isEntityDelimiter(element, isBefore) {
16657
+ var matchBefore = isBefore === undefined || isBefore;
16658
+ var matchAfter = isBefore === undefined || !isBefore;
16345
16659
  return ((0, isElementOfType_1.isElementOfType)(element, 'span') &&
16346
- (element.classList.contains(DELIMITER_AFTER) ||
16347
- element.classList.contains(DELIMITER_BEFORE)) &&
16660
+ ((matchAfter && element.classList.contains(DELIMITER_AFTER)) ||
16661
+ (matchBefore && element.classList.contains(DELIMITER_BEFORE))) &&
16348
16662
  element.textContent === ZERO_WIDTH_SPACE);
16349
16663
  }
16350
16664
  exports.isEntityDelimiter = isEntityDelimiter;
16665
+ /**
16666
+ * Check if the given element is a container element of block entity
16667
+ * @param element The element to check
16668
+ * @returns True if the element is a block entity container, otherwise false
16669
+ */
16670
+ function isBlockEntityContainer(element) {
16671
+ return (0, isElementOfType_1.isElementOfType)(element, 'div') && element.classList.contains(BLOCK_ENTITY_CONTAINER);
16672
+ }
16673
+ exports.isBlockEntityContainer = isBlockEntityContainer;
16351
16674
  /**
16352
16675
  * Adds delimiters to the element provided. If the delimiters already exists, will not be added
16353
16676
  * @param element the node to add the delimiters
@@ -19241,9 +19564,9 @@ exports.shouldSetValue = shouldSetValue;
19241
19564
  "use strict";
19242
19565
 
19243
19566
  Object.defineProperty(exports, "__esModule", ({ value: true }));
19244
- exports.addBlock = exports.createEmptyModel = exports.createListLevel = exports.createDivider = exports.createEntity = exports.createGeneralBlock = exports.createGeneralSegment = exports.createParagraphDecorator = exports.createContentModelDocument = exports.createImage = exports.createText = exports.createTableCell = exports.createTable = exports.createSelectionMarker = exports.createParagraph = exports.createFormatContainer = exports.createListItem = exports.createBr = exports.normalizeRect = exports.isWhiteSpacePreserved = exports.reuseCachedElement = exports.isEntityDelimiter = exports.addDelimiters = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestEntityWrapper = exports.isEntityElement = exports.wrap = exports.wrapAllChildNodes = exports.moveChildNodes = exports.toArray = exports.getObjectKeys = exports.isElementOfType = exports.isNodeOfType = exports.hasMetadata = exports.updateMetadata = exports.buildSelectionMarker = exports.isBlockElement = exports.areSameFormats = exports.parseFormat = exports.getRegularSelectionOffsets = exports.tableProcessor = exports.entityProcessor = exports.processChildNode = exports.handleRegularSelection = exports.childProcessor = exports.contentModelToText = exports.contentModelToDom = exports.domToContentModel = void 0;
19245
- exports.hasSelectionInSegment = exports.hasSelectionInBlock = exports.getSelectedCells = exports.getSelectedSegmentsAndParagraphs = exports.getSelectedSegments = exports.getSelectedParagraphs = exports.getOperationalBlocks = exports.getFirstSelectedTable = exports.getFirstSelectedListItem = exports.iterateSelections = exports.getClosestAncestorBlockGroupIndex = exports.isBlockGroupOfType = exports.cacheGetEventData = exports.extractClipboardItems = exports.transformColor = exports.readFile = exports.parseTableCells = exports.normalizeText = exports.isSpace = exports.isPunctuation = exports.extractBorderValues = exports.combineBorderValue = exports.isCursorMovingKey = exports.isModifierKey = exports.isCharacterValue = exports.getSelectionRootNode = exports.isBold = exports.createModelToDomConfig = exports.createModelToDomContextWithConfig = exports.createModelToDomContext = exports.createDomToModelConfig = exports.createDomToModelContextWithConfig = exports.createDomToModelContext = exports.parseColor = exports.setColor = exports.getColor = exports.DeprecatedColors = exports.BorderKeys = exports.parseValueWithUnit = exports.setParagraphNotImplicit = exports.normalizeSingleSegment = exports.isEmpty = exports.addSegment = exports.unwrapBlock = exports.isGeneralSegment = exports.normalizeContentModel = exports.normalizeParagraph = exports.addTextSegment = exports.addLink = exports.addCode = void 0;
19246
- exports.UnorderedListStyleMap = exports.OrderedListStyleMap = exports.TableBorderFormat = exports.NumberingListType = exports.BulletListType = exports.ChangeSource = exports.ListMetadataDefinition = exports.updateListMetadata = exports.updateTableMetadata = exports.updateTableCellMetadata = exports.updateImageMetadata = exports.getSegmentTextFormat = exports.getListStyleTypeFromString = exports.retrieveModelFormatState = exports.setTableCellBackgroundColor = exports.MIN_ALLOWED_TABLE_CELL_WIDTH = exports.normalizeTable = exports.applyTableFormat = exports.deleteBlock = exports.deleteSegment = exports.deleteSelection = exports.mergeModel = exports.cloneModel = exports.setSelection = exports.hasSelectionInBlockGroup = void 0;
19567
+ exports.createListLevel = exports.createDivider = exports.createEntity = exports.createGeneralBlock = exports.createGeneralSegment = exports.createParagraphDecorator = exports.createContentModelDocument = exports.createImage = exports.createText = exports.createTableCell = exports.createTable = exports.createSelectionMarker = exports.createParagraph = exports.createFormatContainer = exports.createListItem = exports.createBr = exports.normalizeRect = exports.isWhiteSpacePreserved = exports.reuseCachedElement = exports.findClosestBlockEntityContainer = exports.isBlockEntityContainer = exports.isEntityDelimiter = exports.addDelimiters = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestEntityWrapper = exports.isEntityElement = exports.wrap = exports.wrapAllChildNodes = exports.moveChildNodes = exports.toArray = exports.getObjectKeys = exports.isElementOfType = exports.isNodeOfType = exports.hasMetadata = exports.updateMetadata = exports.buildSelectionMarker = exports.isBlockElement = exports.areSameFormats = exports.parseFormat = exports.getRegularSelectionOffsets = exports.tableProcessor = exports.entityProcessor = exports.processChildNode = exports.handleRegularSelection = exports.childProcessor = exports.contentModelToText = exports.contentModelToDom = exports.domToContentModel = void 0;
19568
+ exports.getSelectedSegments = exports.getSelectedParagraphs = exports.getOperationalBlocks = exports.getFirstSelectedTable = exports.getFirstSelectedListItem = exports.iterateSelections = exports.getClosestAncestorBlockGroupIndex = exports.isBlockGroupOfType = exports.cacheGetEventData = exports.extractClipboardItems = exports.transformColor = exports.readFile = exports.parseTableCells = exports.normalizeText = exports.isSpace = exports.isPunctuation = exports.extractBorderValues = exports.combineBorderValue = exports.isCursorMovingKey = exports.isModifierKey = exports.isCharacterValue = exports.getSelectionRootNode = exports.isBold = exports.createModelToDomConfig = exports.createModelToDomContextWithConfig = exports.createModelToDomContext = exports.createDomToModelConfig = exports.createDomToModelContextWithConfig = exports.createDomToModelContext = exports.parseColor = exports.setColor = exports.getColor = exports.DeprecatedColors = exports.BorderKeys = exports.parseValueWithUnit = exports.getAutoListStyleType = exports.getOrderedListNumberStr = exports.setParagraphNotImplicit = exports.normalizeSingleSegment = exports.isEmpty = exports.addSegment = exports.unwrapBlock = exports.isGeneralSegment = exports.normalizeContentModel = exports.normalizeParagraph = exports.addTextSegment = exports.addLink = exports.addCode = exports.addBlock = exports.createEmptyModel = void 0;
19569
+ exports.UnorderedListStyleMap = exports.OrderedListStyleMap = exports.TableBorderFormat = exports.NumberingListType = exports.BulletListType = exports.ChangeSource = exports.ListMetadataDefinition = exports.updateListMetadata = exports.updateTableMetadata = exports.updateTableCellMetadata = exports.updateImageMetadata = exports.getSegmentTextFormat = exports.getListStyleTypeFromString = exports.retrieveModelFormatState = exports.setTableCellBackgroundColor = exports.MIN_ALLOWED_TABLE_CELL_WIDTH = exports.normalizeTable = exports.applyTableFormat = exports.deleteBlock = exports.deleteSegment = exports.deleteSelection = exports.mergeModel = exports.cloneModel = exports.setSelection = exports.hasSelectionInBlockGroup = exports.hasSelectionInSegment = exports.hasSelectionInBlock = exports.getSelectedCells = exports.getSelectedSegmentsAndParagraphs = void 0;
19247
19570
  var domToContentModel_1 = __webpack_require__(/*! ./domToModel/domToContentModel */ "./packages/roosterjs-content-model-dom/lib/domToModel/domToContentModel.ts");
19248
19571
  Object.defineProperty(exports, "domToContentModel", ({ enumerable: true, get: function () { return domToContentModel_1.domToContentModel; } }));
19249
19572
  var contentModelToDom_1 = __webpack_require__(/*! ./modelToDom/contentModelToDom */ "./packages/roosterjs-content-model-dom/lib/modelToDom/contentModelToDom.ts");
@@ -19292,6 +19615,8 @@ Object.defineProperty(exports, "parseEntityFormat", ({ enumerable: true, get: fu
19292
19615
  Object.defineProperty(exports, "generateEntityClassNames", ({ enumerable: true, get: function () { return entityUtils_1.generateEntityClassNames; } }));
19293
19616
  Object.defineProperty(exports, "addDelimiters", ({ enumerable: true, get: function () { return entityUtils_1.addDelimiters; } }));
19294
19617
  Object.defineProperty(exports, "isEntityDelimiter", ({ enumerable: true, get: function () { return entityUtils_1.isEntityDelimiter; } }));
19618
+ Object.defineProperty(exports, "isBlockEntityContainer", ({ enumerable: true, get: function () { return entityUtils_1.isBlockEntityContainer; } }));
19619
+ Object.defineProperty(exports, "findClosestBlockEntityContainer", ({ enumerable: true, get: function () { return entityUtils_1.findClosestBlockEntityContainer; } }));
19295
19620
  var reuseCachedElement_1 = __webpack_require__(/*! ./domUtils/reuseCachedElement */ "./packages/roosterjs-content-model-dom/lib/domUtils/reuseCachedElement.ts");
19296
19621
  Object.defineProperty(exports, "reuseCachedElement", ({ enumerable: true, get: function () { return reuseCachedElement_1.reuseCachedElement; } }));
19297
19622
  var isWhiteSpacePreserved_1 = __webpack_require__(/*! ./domUtils/isWhiteSpacePreserved */ "./packages/roosterjs-content-model-dom/lib/domUtils/isWhiteSpacePreserved.ts");
@@ -19356,6 +19681,10 @@ var normalizeSegment_1 = __webpack_require__(/*! ./modelApi/common/normalizeSegm
19356
19681
  Object.defineProperty(exports, "normalizeSingleSegment", ({ enumerable: true, get: function () { return normalizeSegment_1.normalizeSingleSegment; } }));
19357
19682
  var setParagraphNotImplicit_1 = __webpack_require__(/*! ./modelApi/block/setParagraphNotImplicit */ "./packages/roosterjs-content-model-dom/lib/modelApi/block/setParagraphNotImplicit.ts");
19358
19683
  Object.defineProperty(exports, "setParagraphNotImplicit", ({ enumerable: true, get: function () { return setParagraphNotImplicit_1.setParagraphNotImplicit; } }));
19684
+ var getOrderedListNumberStr_1 = __webpack_require__(/*! ./modelApi/list/getOrderedListNumberStr */ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getOrderedListNumberStr.ts");
19685
+ Object.defineProperty(exports, "getOrderedListNumberStr", ({ enumerable: true, get: function () { return getOrderedListNumberStr_1.getOrderedListNumberStr; } }));
19686
+ var getAutoListStyleType_1 = __webpack_require__(/*! ./modelApi/list/getAutoListStyleType */ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getAutoListStyleType.ts");
19687
+ Object.defineProperty(exports, "getAutoListStyleType", ({ enumerable: true, get: function () { return getAutoListStyleType_1.getAutoListStyleType; } }));
19359
19688
  var parseValueWithUnit_1 = __webpack_require__(/*! ./formatHandlers/utils/parseValueWithUnit */ "./packages/roosterjs-content-model-dom/lib/formatHandlers/utils/parseValueWithUnit.ts");
19360
19689
  Object.defineProperty(exports, "parseValueWithUnit", ({ enumerable: true, get: function () { return parseValueWithUnit_1.parseValueWithUnit; } }));
19361
19690
  var borderFormatHandler_1 = __webpack_require__(/*! ./formatHandlers/common/borderFormatHandler */ "./packages/roosterjs-content-model-dom/lib/formatHandlers/common/borderFormatHandler.ts");
@@ -22372,6 +22701,175 @@ function calculateLightness(color) {
22372
22701
  }
22373
22702
 
22374
22703
 
22704
+ /***/ }),
22705
+
22706
+ /***/ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getAutoListStyleType.ts":
22707
+ /*!****************************************************************************************!*\
22708
+ !*** ./packages/roosterjs-content-model-dom/lib/modelApi/list/getAutoListStyleType.ts ***!
22709
+ \****************************************************************************************/
22710
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
22711
+
22712
+ "use strict";
22713
+
22714
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
22715
+ exports.getAutoListStyleType = void 0;
22716
+ var BulletListType_1 = __webpack_require__(/*! ../../constants/BulletListType */ "./packages/roosterjs-content-model-dom/lib/constants/BulletListType.ts");
22717
+ var NumberingListType_1 = __webpack_require__(/*! ../../constants/NumberingListType */ "./packages/roosterjs-content-model-dom/lib/constants/NumberingListType.ts");
22718
+ var DefaultOrderedListStyles = [
22719
+ NumberingListType_1.NumberingListType.Decimal,
22720
+ NumberingListType_1.NumberingListType.LowerAlpha,
22721
+ NumberingListType_1.NumberingListType.LowerRoman,
22722
+ ];
22723
+ var DefaultUnorderedListStyles = [
22724
+ BulletListType_1.BulletListType.Disc,
22725
+ BulletListType_1.BulletListType.Circle,
22726
+ BulletListType_1.BulletListType.Square,
22727
+ ];
22728
+ var OrderedListStyleRevertMap = {
22729
+ 'lower-alpha': NumberingListType_1.NumberingListType.LowerAlpha,
22730
+ 'lower-latin': NumberingListType_1.NumberingListType.LowerAlpha,
22731
+ 'upper-alpha': NumberingListType_1.NumberingListType.UpperAlpha,
22732
+ 'upper-latin': NumberingListType_1.NumberingListType.UpperAlpha,
22733
+ 'lower-roman': NumberingListType_1.NumberingListType.LowerRoman,
22734
+ 'upper-roman': NumberingListType_1.NumberingListType.UpperRoman,
22735
+ };
22736
+ var UnorderedListStyleRevertMap = {
22737
+ disc: BulletListType_1.BulletListType.Disc,
22738
+ circle: BulletListType_1.BulletListType.Circle,
22739
+ square: BulletListType_1.BulletListType.Square,
22740
+ };
22741
+ /**
22742
+ * Get automatic list style of a list item according to its lis type and metadata.
22743
+ * @param listType The list type, either OL or UL
22744
+ * @param metadata Metadata of this list item from list item model
22745
+ * @param depth Depth of list level, start from 0
22746
+ * @param existingStyleType Existing list style type in format, if any
22747
+ * @returns A number to represent list style type.
22748
+ * This will be the value of either NumberingListType (when listType is OL) or BulletListType (when listType is UL).
22749
+ * When there is a specified list style in its metadata, return this value, otherwise
22750
+ * When specified "applyListStyleFromLevel" in metadata, calculate auto list type from its depth, otherwise
22751
+ * When there is already listStyleType in list level format, find a related style type index, otherwise
22752
+ * return undefined
22753
+ */
22754
+ function getAutoListStyleType(listType, metadata, depth, existingStyleType) {
22755
+ var orderedStyleType = metadata.orderedStyleType, unorderedStyleType = metadata.unorderedStyleType, applyListStyleFromLevel = metadata.applyListStyleFromLevel;
22756
+ if (listType == 'OL') {
22757
+ return typeof orderedStyleType == 'number'
22758
+ ? orderedStyleType
22759
+ : applyListStyleFromLevel
22760
+ ? DefaultOrderedListStyles[depth % DefaultOrderedListStyles.length]
22761
+ : existingStyleType
22762
+ ? OrderedListStyleRevertMap[existingStyleType]
22763
+ : undefined;
22764
+ }
22765
+ else {
22766
+ return typeof unorderedStyleType == 'number'
22767
+ ? unorderedStyleType
22768
+ : applyListStyleFromLevel
22769
+ ? DefaultUnorderedListStyles[depth % DefaultUnorderedListStyles.length]
22770
+ : existingStyleType
22771
+ ? UnorderedListStyleRevertMap[existingStyleType]
22772
+ : undefined;
22773
+ }
22774
+ }
22775
+ exports.getAutoListStyleType = getAutoListStyleType;
22776
+
22777
+
22778
+ /***/ }),
22779
+
22780
+ /***/ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getOrderedListNumberStr.ts":
22781
+ /*!*******************************************************************************************!*\
22782
+ !*** ./packages/roosterjs-content-model-dom/lib/modelApi/list/getOrderedListNumberStr.ts ***!
22783
+ \*******************************************************************************************/
22784
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
22785
+
22786
+ "use strict";
22787
+
22788
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
22789
+ exports.getOrderedListNumberStr = void 0;
22790
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
22791
+ var getObjectKeys_1 = __webpack_require__(/*! ../../domUtils/getObjectKeys */ "./packages/roosterjs-content-model-dom/lib/domUtils/getObjectKeys.ts");
22792
+ var NumberingListType_1 = __webpack_require__(/*! ../../constants/NumberingListType */ "./packages/roosterjs-content-model-dom/lib/constants/NumberingListType.ts");
22793
+ var CharCodeOfA = 65;
22794
+ var RomanValues = {
22795
+ M: 1000,
22796
+ CM: 900,
22797
+ D: 500,
22798
+ CD: 400,
22799
+ C: 100,
22800
+ XC: 90,
22801
+ L: 50,
22802
+ XL: 40,
22803
+ X: 10,
22804
+ IX: 9,
22805
+ V: 5,
22806
+ IV: 4,
22807
+ I: 1,
22808
+ };
22809
+ /**
22810
+ * Get the list number for a list item according to list style type and its index number
22811
+ * @param styleType The list style number, should be a value of NumberingListType type
22812
+ * @param listNumber List number, start from 1
22813
+ * @returns A string for this list item. For example, when pass in NumberingListType.LowerAlpha and 2, it returns "b"
22814
+ */
22815
+ function getOrderedListNumberStr(styleType, listNumber) {
22816
+ switch (styleType) {
22817
+ case NumberingListType_1.NumberingListType.LowerAlpha:
22818
+ case NumberingListType_1.NumberingListType.LowerAlphaDash:
22819
+ case NumberingListType_1.NumberingListType.LowerAlphaDoubleParenthesis:
22820
+ case NumberingListType_1.NumberingListType.LowerAlphaParenthesis:
22821
+ return convertDecimalsToAlpha(listNumber, true /*isLowerCase*/);
22822
+ case NumberingListType_1.NumberingListType.UpperAlpha:
22823
+ case NumberingListType_1.NumberingListType.UpperAlphaDash:
22824
+ case NumberingListType_1.NumberingListType.UpperAlphaDoubleParenthesis:
22825
+ case NumberingListType_1.NumberingListType.UpperAlphaParenthesis:
22826
+ return convertDecimalsToAlpha(listNumber, false /*isLowerCase*/);
22827
+ case NumberingListType_1.NumberingListType.LowerRoman:
22828
+ case NumberingListType_1.NumberingListType.LowerRomanDash:
22829
+ case NumberingListType_1.NumberingListType.LowerRomanDoubleParenthesis:
22830
+ case NumberingListType_1.NumberingListType.LowerRomanParenthesis:
22831
+ return convertDecimalsToRoman(listNumber, true /*isLowerCase*/);
22832
+ case NumberingListType_1.NumberingListType.UpperRoman:
22833
+ case NumberingListType_1.NumberingListType.UpperRomanDash:
22834
+ case NumberingListType_1.NumberingListType.UpperRomanDoubleParenthesis:
22835
+ case NumberingListType_1.NumberingListType.UpperRomanParenthesis:
22836
+ return convertDecimalsToRoman(listNumber, false /*isLowerCase*/);
22837
+ default:
22838
+ return listNumber + '';
22839
+ }
22840
+ }
22841
+ exports.getOrderedListNumberStr = getOrderedListNumberStr;
22842
+ function convertDecimalsToAlpha(decimal, isLowerCase) {
22843
+ var alpha = '';
22844
+ decimal--;
22845
+ while (decimal >= 0) {
22846
+ alpha = String.fromCharCode((decimal % 26) + CharCodeOfA) + alpha;
22847
+ decimal = Math.floor(decimal / 26) - 1;
22848
+ }
22849
+ return isLowerCase ? alpha.toLowerCase() : alpha;
22850
+ }
22851
+ function convertDecimalsToRoman(decimal, isLowerCase) {
22852
+ var e_1, _a;
22853
+ var romanValue = '';
22854
+ try {
22855
+ for (var _b = (0, tslib_1.__values)((0, getObjectKeys_1.getObjectKeys)(RomanValues)), _c = _b.next(); !_c.done; _c = _b.next()) {
22856
+ var i = _c.value;
22857
+ var timesRomanCharAppear = Math.floor(decimal / RomanValues[i]);
22858
+ decimal = decimal - timesRomanCharAppear * RomanValues[i];
22859
+ romanValue = romanValue + i.repeat(timesRomanCharAppear);
22860
+ }
22861
+ }
22862
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
22863
+ finally {
22864
+ try {
22865
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
22866
+ }
22867
+ finally { if (e_1) throw e_1.error; }
22868
+ }
22869
+ return isLowerCase ? romanValue.toLocaleLowerCase() : romanValue;
22870
+ }
22871
+
22872
+
22375
22873
  /***/ }),
22376
22874
 
22377
22875
  /***/ "./packages/roosterjs-content-model-dom/lib/modelApi/metadata/definitionCreators.ts":
@@ -22768,17 +23266,19 @@ var iterateSelections_1 = __webpack_require__(/*! ./iterateSelections */ "./pack
22768
23266
  * @param model The Content Model to get selection from
22769
23267
  * @param includingFormatHolder True means also include format holder as segment from list item, in that case paragraph will be null
22770
23268
  */
22771
- function getSelectedSegmentsAndParagraphs(model, includingFormatHolder) {
23269
+ function getSelectedSegmentsAndParagraphs(model, includingFormatHolder, includingEntity) {
22772
23270
  var selections = collectSelections(model, {
22773
23271
  includeListFormatHolder: includingFormatHolder ? 'allSegments' : 'never',
22774
23272
  });
22775
23273
  var result = [];
22776
23274
  selections.forEach(function (_a) {
22777
- var segments = _a.segments, block = _a.block;
23275
+ var segments = _a.segments, block = _a.block, path = _a.path;
22778
23276
  if (segments && ((includingFormatHolder && !block) || (block === null || block === void 0 ? void 0 : block.blockType) == 'Paragraph')) {
22779
23277
  segments.forEach(function (segment) {
22780
- if (segment.segmentType != 'Entity' || !segment.entityFormat.isReadonly) {
22781
- result.push([segment, (block === null || block === void 0 ? void 0 : block.blockType) == 'Paragraph' ? block : null]);
23278
+ if (includingEntity ||
23279
+ segment.segmentType != 'Entity' ||
23280
+ !segment.entityFormat.isReadonly) {
23281
+ result.push([segment, (block === null || block === void 0 ? void 0 : block.blockType) == 'Paragraph' ? block : null, path]);
22782
23282
  }
22783
23283
  });
22784
23284
  }
@@ -22814,15 +23314,15 @@ function getSelectedParagraphs(model) {
22814
23314
  exports.getSelectedParagraphs = getSelectedParagraphs;
22815
23315
  /**
22816
23316
  * Get an array of block group - block pair that is of the expected block group type from selection
22817
- * @param model The Content Model to get selection from
23317
+ * @param group The root block group to search
22818
23318
  * @param blockGroupTypes The expected block group types
22819
23319
  * @param stopTypes Block group types that will stop searching when hit
22820
23320
  * @param deepFirst True means search in deep first, otherwise wide first
22821
23321
  */
22822
- function getOperationalBlocks(model, blockGroupTypes, stopTypes, deepFirst) {
23322
+ function getOperationalBlocks(group, blockGroupTypes, stopTypes, deepFirst) {
22823
23323
  var result = [];
22824
23324
  var findSequence = deepFirst ? blockGroupTypes.map(function (type) { return [type]; }) : [blockGroupTypes];
22825
- var selections = collectSelections(model, {
23325
+ var selections = collectSelections(group, {
22826
23326
  includeListFormatHolder: 'never',
22827
23327
  contentUnderSelectedTableCell: 'ignoreForTable', // When whole table is selected, we treat the table as a single block
22828
23328
  });
@@ -22900,9 +23400,9 @@ function getFirstSelectedListItem(model) {
22900
23400
  return listItem;
22901
23401
  }
22902
23402
  exports.getFirstSelectedListItem = getFirstSelectedListItem;
22903
- function collectSelections(model, option) {
23403
+ function collectSelections(group, option) {
22904
23404
  var selections = [];
22905
- (0, iterateSelections_1.iterateSelections)(model, function (path, tableContext, block, segments) {
23405
+ (0, iterateSelections_1.iterateSelections)(group, function (path, tableContext, block, segments) {
22906
23406
  selections.push({
22907
23407
  path: path,
22908
23408
  tableContext: tableContext,
@@ -23443,6 +23943,9 @@ var toArray_1 = __webpack_require__(/*! ../domUtils/toArray */ "./packages/roost
23443
23943
  function contentModelToDom(doc, root, model, context) {
23444
23944
  context.modelHandlers.blockGroupChildren(doc, root, model, context);
23445
23945
  var range = extractSelectionRange(doc, context);
23946
+ if (model.hasRevertedRangeSelection && (range === null || range === void 0 ? void 0 : range.type) == 'range') {
23947
+ range.isReverted = true;
23948
+ }
23446
23949
  root.normalize();
23447
23950
  return range;
23448
23951
  }
@@ -24861,11 +25364,14 @@ function contentModelToTextArray(group, textArray) {
24861
25364
 
24862
25365
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24863
25366
  exports.AutoFormatPlugin = void 0;
25367
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
24864
25368
  var createLink_1 = __webpack_require__(/*! ./link/createLink */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLink.ts");
24865
25369
  var createLinkAfterSpace_1 = __webpack_require__(/*! ./link/createLinkAfterSpace */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLinkAfterSpace.ts");
24866
25370
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
24867
25371
  var keyboardListTrigger_1 = __webpack_require__(/*! ./list/keyboardListTrigger */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/list/keyboardListTrigger.ts");
25372
+ var transformFraction_1 = __webpack_require__(/*! ./numbers/transformFraction */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformFraction.ts");
24868
25373
  var transformHyphen_1 = __webpack_require__(/*! ./hyphen/transformHyphen */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/hyphen/transformHyphen.ts");
25374
+ var transformOrdinals_1 = __webpack_require__(/*! ./numbers/transformOrdinals */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformOrdinals.ts");
24869
25375
  var unlink_1 = __webpack_require__(/*! ./link/unlink */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/unlink.ts");
24870
25376
  /**
24871
25377
  * @internal
@@ -24876,6 +25382,8 @@ var DefaultOptions = {
24876
25382
  autoUnlink: false,
24877
25383
  autoLink: false,
24878
25384
  autoHyphen: false,
25385
+ autoFraction: false,
25386
+ autoOrdinals: false,
24879
25387
  };
24880
25388
  /**
24881
25389
  * Auto Format plugin handles auto formatting, such as transforming * characters into a bullet list.
@@ -24889,6 +25397,8 @@ var AutoFormatPlugin = /** @class */ (function () {
24889
25397
  * - autoLink: A boolean that enables or disables automatic hyperlink creation when pasting or typing content. Defaults to false.
24890
25398
  * - autoUnlink: A boolean that enables or disables automatic hyperlink removal when pressing backspace. Defaults to false.
24891
25399
  * - autoHyphen: A boolean that enables or disables automatic hyphen transformation. Defaults to false.
25400
+ * - autoFraction: A boolean that enables or disables automatic fraction transformation. Defaults to false.
25401
+ * - autoOrdinals: A boolean that enables or disables automatic ordinal number transformation. Defaults to false.
24892
25402
  */
24893
25403
  function AutoFormatPlugin(options) {
24894
25404
  if (options === void 0) { options = DefaultOptions; }
@@ -24949,20 +25459,40 @@ var AutoFormatPlugin = /** @class */ (function () {
24949
25459
  selection.range.collapsed) {
24950
25460
  switch (rawEvent.data) {
24951
25461
  case ' ':
25462
+ var formatOptions_1 = {
25463
+ changeSource: '',
25464
+ apiName: '',
25465
+ };
24952
25466
  (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (model, previousSegment, paragraph, _markerFormat, context) {
24953
- var _a = _this.options, autoBullet = _a.autoBullet, autoNumbering = _a.autoNumbering, autoLink = _a.autoLink, autoHyphen = _a.autoHyphen;
25467
+ var _a = _this.options, autoBullet = _a.autoBullet, autoNumbering = _a.autoNumbering, autoLink = _a.autoLink, autoHyphen = _a.autoHyphen, autoFraction = _a.autoFraction, autoOrdinals = _a.autoOrdinals;
24954
25468
  var shouldHyphen = false;
24955
25469
  var shouldLink = false;
25470
+ var shouldList = false;
25471
+ var shouldFraction = false;
25472
+ var shouldOrdinals = false;
25473
+ if (autoBullet || autoNumbering) {
25474
+ shouldList = (0, keyboardListTrigger_1.keyboardListTrigger)(model, paragraph, context, autoBullet, autoNumbering);
25475
+ }
24956
25476
  if (autoLink) {
24957
25477
  shouldLink = (0, createLinkAfterSpace_1.createLinkAfterSpace)(previousSegment, paragraph, context);
24958
25478
  }
24959
25479
  if (autoHyphen) {
24960
25480
  shouldHyphen = (0, transformHyphen_1.transformHyphen)(previousSegment, paragraph, context);
24961
25481
  }
24962
- return ((0, keyboardListTrigger_1.keyboardListTrigger)(model, paragraph, context, autoBullet, autoNumbering) ||
25482
+ if (autoFraction) {
25483
+ shouldFraction = (0, transformFraction_1.transformFraction)(previousSegment, paragraph, context);
25484
+ }
25485
+ if (autoOrdinals) {
25486
+ shouldOrdinals = (0, transformOrdinals_1.transformOrdinals)(previousSegment, paragraph, context);
25487
+ }
25488
+ formatOptions_1.apiName = getApiName(shouldList, shouldHyphen);
25489
+ formatOptions_1.changeSource = getChangeSource(shouldList, shouldHyphen, shouldLink);
25490
+ return (shouldList ||
24963
25491
  shouldHyphen ||
24964
- shouldLink);
24965
- });
25492
+ shouldLink ||
25493
+ shouldFraction ||
25494
+ shouldOrdinals);
25495
+ }, formatOptions_1);
24966
25496
  break;
24967
25497
  }
24968
25498
  }
@@ -24988,6 +25518,16 @@ var AutoFormatPlugin = /** @class */ (function () {
24988
25518
  return AutoFormatPlugin;
24989
25519
  }());
24990
25520
  exports.AutoFormatPlugin = AutoFormatPlugin;
25521
+ var getApiName = function (shouldList, shouldHyphen) {
25522
+ return shouldList ? 'autoToggleList' : shouldHyphen ? 'autoHyphen' : '';
25523
+ };
25524
+ var getChangeSource = function (shouldList, shouldHyphen, shouldLink) {
25525
+ return shouldList || shouldHyphen
25526
+ ? roosterjs_content_model_dom_1.ChangeSource.AutoFormat
25527
+ : shouldLink
25528
+ ? roosterjs_content_model_dom_1.ChangeSource.AutoLink
25529
+ : '';
25530
+ };
24991
25531
 
24992
25532
 
24993
25533
  /***/ }),
@@ -25066,6 +25606,8 @@ function createLink(editor) {
25066
25606
  return true;
25067
25607
  }
25068
25608
  return false;
25609
+ }, {
25610
+ changeSource: roosterjs_content_model_dom_1.ChangeSource.AutoLink,
25069
25611
  });
25070
25612
  }
25071
25613
  exports.createLink = createLink;
@@ -25480,15 +26022,13 @@ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-mo
25480
26022
  function keyboardListTrigger(model, paragraph, context, shouldSearchForBullet, shouldSearchForNumbering) {
25481
26023
  if (shouldSearchForBullet === void 0) { shouldSearchForBullet = true; }
25482
26024
  if (shouldSearchForNumbering === void 0) { shouldSearchForNumbering = true; }
25483
- if (shouldSearchForBullet || shouldSearchForNumbering) {
25484
- var listStyleType = (0, getListTypeStyle_1.getListTypeStyle)(model, shouldSearchForBullet, shouldSearchForNumbering);
25485
- if (listStyleType) {
25486
- paragraph.segments.splice(0, 1);
25487
- var listType = listStyleType.listType, styleType = listStyleType.styleType, index = listStyleType.index;
25488
- triggerList(model, listType, styleType, index);
25489
- context.canUndoByBackspace = true;
25490
- return true;
25491
- }
26025
+ var listStyleType = (0, getListTypeStyle_1.getListTypeStyle)(model, shouldSearchForBullet, shouldSearchForNumbering);
26026
+ if (listStyleType) {
26027
+ paragraph.segments.splice(0, 1);
26028
+ var listType = listStyleType.listType, styleType = listStyleType.styleType, index = listStyleType.index;
26029
+ triggerList(model, listType, styleType, index);
26030
+ context.canUndoByBackspace = true;
26031
+ return true;
25492
26032
  }
25493
26033
  return false;
25494
26034
  }
@@ -25509,6 +26049,85 @@ var triggerList = function (model, listType, styleType, index) {
25509
26049
  };
25510
26050
 
25511
26051
 
26052
+ /***/ }),
26053
+
26054
+ /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformFraction.ts":
26055
+ /*!**********************************************************************************************!*\
26056
+ !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformFraction.ts ***!
26057
+ \**********************************************************************************************/
26058
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26059
+
26060
+ "use strict";
26061
+
26062
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26063
+ exports.transformFraction = void 0;
26064
+ var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26065
+ var FRACTIONS = {
26066
+ '1/2': '½',
26067
+ '1/4': '¼',
26068
+ '3/4': '¾',
26069
+ };
26070
+ /**
26071
+ * @internal
26072
+ */
26073
+ function transformFraction(previousSegment, paragraph, context) {
26074
+ var _a;
26075
+ var fraction = (_a = previousSegment.text.split(' ').pop()) === null || _a === void 0 ? void 0 : _a.trim();
26076
+ if (fraction && FRACTIONS[fraction]) {
26077
+ var textLength = previousSegment.text.length - 1;
26078
+ var textIndex = textLength - fraction.length;
26079
+ var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textLength);
26080
+ textSegment.text = FRACTIONS[fraction];
26081
+ context.canUndoByBackspace = true;
26082
+ return true;
26083
+ }
26084
+ return false;
26085
+ }
26086
+ exports.transformFraction = transformFraction;
26087
+
26088
+
26089
+ /***/ }),
26090
+
26091
+ /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformOrdinals.ts":
26092
+ /*!**********************************************************************************************!*\
26093
+ !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformOrdinals.ts ***!
26094
+ \**********************************************************************************************/
26095
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26096
+
26097
+ "use strict";
26098
+
26099
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26100
+ exports.transformOrdinals = void 0;
26101
+ var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26102
+ var getOrdinal = function (value) {
26103
+ var ORDINALS = {
26104
+ 1: 'st',
26105
+ 2: 'nd',
26106
+ 3: 'rd',
26107
+ };
26108
+ return ORDINALS[value] || 'th';
26109
+ };
26110
+ /**
26111
+ * @internal
26112
+ */
26113
+ function transformOrdinals(previousSegment, paragraph, context) {
26114
+ var _a;
26115
+ var value = (_a = previousSegment.text.split(' ').pop()) === null || _a === void 0 ? void 0 : _a.trim();
26116
+ if (value) {
26117
+ var ordinal = value.substring(value.length - 2);
26118
+ var ordinalValue = parseInt(value);
26119
+ if (ordinalValue && getOrdinal(ordinalValue) === ordinal) {
26120
+ var ordinalSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - 3, previousSegment.text.length - 1);
26121
+ ordinalSegment.format.superOrSubScriptSequence = 'super';
26122
+ context.canUndoByBackspace = true;
26123
+ return true;
26124
+ }
26125
+ }
26126
+ return false;
26127
+ }
26128
+ exports.transformOrdinals = transformOrdinals;
26129
+
26130
+
25512
26131
  /***/ }),
25513
26132
 
25514
26133
  /***/ "./packages/roosterjs-content-model-plugins/lib/contextMenuBase/ContextMenuPluginBase.ts":
@@ -25603,6 +26222,103 @@ var ContextMenuPluginBase = /** @class */ (function () {
25603
26222
  exports.ContextMenuPluginBase = ContextMenuPluginBase;
25604
26223
 
25605
26224
 
26225
+ /***/ }),
26226
+
26227
+ /***/ "./packages/roosterjs-content-model-plugins/lib/customReplace/CustomReplacePlugin.ts":
26228
+ /*!*******************************************************************************************!*\
26229
+ !*** ./packages/roosterjs-content-model-plugins/lib/customReplace/CustomReplacePlugin.ts ***!
26230
+ \*******************************************************************************************/
26231
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26232
+
26233
+ "use strict";
26234
+
26235
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26236
+ exports.CustomReplacePlugin = void 0;
26237
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26238
+ /**
26239
+ * CustomReplacePlugin is a plugin that allows you to replace a string with another string in the editor.
26240
+ */
26241
+ var CustomReplacePlugin = /** @class */ (function () {
26242
+ /**
26243
+ * @param customReplacements Custom replacement rules.
26244
+ * Ex: [{ stringToReplace: ':)', replacementString: '🙂', replacementHandler: replaceEmojis }]
26245
+ */
26246
+ function CustomReplacePlugin(customReplacements) {
26247
+ this.customReplacements = customReplacements;
26248
+ this.editor = null;
26249
+ this.triggerKeys = [];
26250
+ }
26251
+ /**
26252
+ * Get name of this plugin
26253
+ */
26254
+ CustomReplacePlugin.prototype.getName = function () {
26255
+ return 'CustomReplace';
26256
+ };
26257
+ /**
26258
+ * The first method that editor will call to a plugin when editor is initializing.
26259
+ * It will pass in the editor instance, plugin should take this chance to save the
26260
+ * editor reference so that it can call to any editor method or format API later.
26261
+ * @param editor The editor object
26262
+ */
26263
+ CustomReplacePlugin.prototype.initialize = function (editor) {
26264
+ this.editor = editor;
26265
+ this.triggerKeys = this.customReplacements.map(function (replacement) {
26266
+ return replacement.stringToReplace.slice(-1);
26267
+ });
26268
+ };
26269
+ /**
26270
+ * The last method that editor will call to a plugin before it is disposed.
26271
+ * Plugin can take this chance to clear the reference to editor. After this method is
26272
+ * called, plugin should not call to any editor method since it will result in error.
26273
+ */
26274
+ CustomReplacePlugin.prototype.dispose = function () {
26275
+ this.editor = null;
26276
+ };
26277
+ /**
26278
+ * Core method for a plugin. Once an event happens in editor, editor will call this
26279
+ * method of each plugin to handle the event as long as the event is not handled
26280
+ * exclusively by another plugin.
26281
+ * @param event The event to handle:
26282
+ */
26283
+ CustomReplacePlugin.prototype.onPluginEvent = function (event) {
26284
+ if (this.editor) {
26285
+ switch (event.eventType) {
26286
+ case 'input':
26287
+ this.handleEditorInputEvent(this.editor, event);
26288
+ break;
26289
+ }
26290
+ }
26291
+ };
26292
+ CustomReplacePlugin.prototype.handleEditorInputEvent = function (editor, event) {
26293
+ var _this = this;
26294
+ var rawEvent = event.rawEvent;
26295
+ var selection = editor.getDOMSelection();
26296
+ var key = rawEvent.data;
26297
+ if (this.customReplacements.length > 0 &&
26298
+ rawEvent.inputType === 'insertText' &&
26299
+ selection &&
26300
+ selection.type === 'range' &&
26301
+ selection.range.collapsed &&
26302
+ key &&
26303
+ this.triggerKeys.indexOf(key) > -1) {
26304
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (_model, previousSegment, paragraph, _markerFormat, context) {
26305
+ var replaced = _this.customReplacements.some(function (_a) {
26306
+ var stringToReplace = _a.stringToReplace, replacementString = _a.replacementString, replacementHandler = _a.replacementHandler;
26307
+ return replacementHandler(previousSegment, stringToReplace, replacementString, paragraph);
26308
+ });
26309
+ if (replaced) {
26310
+ context.canUndoByBackspace = true;
26311
+ return true;
26312
+ }
26313
+ return false;
26314
+ });
26315
+ }
26316
+ };
26317
+ return CustomReplacePlugin;
26318
+ }());
26319
+ exports.CustomReplacePlugin = CustomReplacePlugin;
26320
+
26321
+
25606
26322
  /***/ }),
25607
26323
 
25608
26324
  /***/ "./packages/roosterjs-content-model-plugins/lib/edit/EditPlugin.ts":
@@ -25687,11 +26403,18 @@ var EditPlugin = /** @class */ (function () {
25687
26403
  if (!rawEvent.defaultPrevented && !event.handledByEditFeature) {
25688
26404
  switch (rawEvent.key) {
25689
26405
  case 'Backspace':
25690
- case 'Delete':
25691
26406
  // Use our API to handle BACKSPACE/DELETE key.
25692
26407
  // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache
25693
26408
  (0, keyboardDelete_1.keyboardDelete)(editor, rawEvent);
25694
26409
  break;
26410
+ case 'Delete':
26411
+ // Use our API to handle BACKSPACE/DELETE key.
26412
+ // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache
26413
+ // And leave it to browser when shift key is pressed so that browser will trigger cut event
26414
+ if (!event.rawEvent.shiftKey) {
26415
+ (0, keyboardDelete_1.keyboardDelete)(editor, rawEvent);
26416
+ }
26417
+ break;
25695
26418
  case 'Tab':
25696
26419
  (0, keyboardTab_1.keyboardTab)(editor, rawEvent);
25697
26420
  break;
@@ -25708,6 +26431,8 @@ var EditPlugin = /** @class */ (function () {
25708
26431
  }
25709
26432
  };
25710
26433
  EditPlugin.prototype.handleBeforeInputEvent = function (editor, rawEvent) {
26434
+ var _this = this;
26435
+ var _a, _b;
25711
26436
  // Some Android IMEs doesn't fire correct keydown event for BACKSPACE/DELETE key
25712
26437
  // Here we translate input event to BACKSPACE/DELETE keydown event to be compatible with existing logic
25713
26438
  if (!this.shouldHandleNextInputEvent ||
@@ -25735,6 +26460,15 @@ var EditPlugin = /** @class */ (function () {
25735
26460
  }
25736
26461
  if (handled) {
25737
26462
  rawEvent.preventDefault();
26463
+ // Restore the selection to avoid the cursor jump issue
26464
+ // See: https://issues.chromium.org/issues/330596261
26465
+ var selection_1 = editor.getDOMSelection();
26466
+ var doc = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDocument();
26467
+ (_b = doc === null || doc === void 0 ? void 0 : doc.defaultView) === null || _b === void 0 ? void 0 : _b.requestAnimationFrame(function () {
26468
+ if (_this.editor) {
26469
+ _this.editor.setDOMSelection(selection_1);
26470
+ }
26471
+ });
25738
26472
  }
25739
26473
  };
25740
26474
  return EditPlugin;
@@ -26266,6 +27000,7 @@ exports.shouldDeleteAllSegmentsBefore = shouldDeleteAllSegmentsBefore;
26266
27000
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26267
27001
  exports.handleEnterOnList = void 0;
26268
27002
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
27003
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26269
27004
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26270
27005
  /**
26271
27006
  * @internal
@@ -26312,7 +27047,12 @@ var handleEnterOnList = function (context) {
26312
27047
  listItem_1.levels.pop();
26313
27048
  }
26314
27049
  else {
26315
- createNewListItem(context, listItem_1, listParent);
27050
+ var newListItem = createNewListItem(context, listItem_1, listParent);
27051
+ if (context.formatContext) {
27052
+ context.formatContext.announceData = (0, roosterjs_content_model_api_1.getListAnnounceData)((0, tslib_1.__spreadArray)([
27053
+ newListItem
27054
+ ], (0, tslib_1.__read)(path.slice(index + 1)), false));
27055
+ }
26316
27056
  }
26317
27057
  }
26318
27058
  rawEvent === null || rawEvent === void 0 ? void 0 : rawEvent.preventDefault();
@@ -26338,6 +27078,7 @@ var createNewListItem = function (context, listItem, listParent) {
26338
27078
  insertPoint.paragraph = newParagraph;
26339
27079
  context.lastParagraph = newParagraph;
26340
27080
  listParent.blocks.splice(listIndex + 1, 0, newListItem);
27081
+ return newListItem;
26341
27082
  };
26342
27083
  var createNewListLevel = function (listItem) {
26343
27084
  return listItem.levels.map(function (level) {
@@ -26543,8 +27284,8 @@ function keyboardTab(editor, rawEvent) {
26543
27284
  var selection = editor.getDOMSelection();
26544
27285
  switch (selection === null || selection === void 0 ? void 0 : selection.type) {
26545
27286
  case 'range':
26546
- editor.formatContentModel(function (model) {
26547
- return handleTab(model, rawEvent);
27287
+ editor.formatContentModel(function (model, context) {
27288
+ return handleTab(model, rawEvent, context);
26548
27289
  }, {
26549
27290
  apiName: 'handleTabKey',
26550
27291
  });
@@ -26566,7 +27307,7 @@ exports.keyboardTab = keyboardTab;
26566
27307
  * - If it is a paragraph, call handleTabOnParagraph to handle the tab key.
26567
27308
  * - If it is a list item, call handleTabOnList to handle the tab key.
26568
27309
  */
26569
- function handleTab(model, rawEvent) {
27310
+ function handleTab(model, rawEvent, context) {
26570
27311
  var blocks = (0, roosterjs_content_model_dom_1.getOperationalBlocks)(model, ['ListItem', 'TableCell'], []);
26571
27312
  var block = blocks.length > 0 ? blocks[0].block : undefined;
26572
27313
  if (blocks.length > 1) {
@@ -26578,10 +27319,10 @@ function handleTab(model, rawEvent) {
26578
27319
  return (0, handleTabOnTableCell_1.handleTabOnTableCell)(model, block, rawEvent);
26579
27320
  }
26580
27321
  else if ((block === null || block === void 0 ? void 0 : block.blockType) === 'Paragraph') {
26581
- return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, block, rawEvent);
27322
+ return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, block, rawEvent, context);
26582
27323
  }
26583
27324
  else if ((0, roosterjs_content_model_dom_1.isBlockGroupOfType)(block, 'ListItem')) {
26584
- return (0, handleTabOnList_1.handleTabOnList)(model, block, rawEvent);
27325
+ return (0, handleTabOnList_1.handleTabOnList)(model, block, rawEvent, context);
26585
27326
  }
26586
27327
  return false;
26587
27328
  }
@@ -26606,15 +27347,15 @@ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-mo
26606
27347
  * 2. Otherwise call handleTabOnParagraph.
26607
27348
  * @internal
26608
27349
  */
26609
- function handleTabOnList(model, listItem, rawEvent) {
27350
+ function handleTabOnList(model, listItem, rawEvent, context) {
26610
27351
  var selectedParagraph = findSelectedParagraph(listItem);
26611
27352
  if (!isMarkerAtStartOfBlock(listItem) &&
26612
27353
  selectedParagraph.length == 1 &&
26613
27354
  selectedParagraph[0].blockType === 'Paragraph') {
26614
- return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, selectedParagraph[0], rawEvent);
27355
+ return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, selectedParagraph[0], rawEvent, context);
26615
27356
  }
26616
27357
  else {
26617
- (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
27358
+ (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent', undefined /*length*/, context);
26618
27359
  rawEvent.preventDefault();
26619
27360
  return true;
26620
27361
  }
@@ -26662,7 +27403,7 @@ var space = ' ';
26662
27403
  * 4. When the selection is not collapsed, replace the selected range with a 4 space.
26663
27404
  * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to outdent the whole paragraph
26664
27405
  */
26665
- function handleTabOnParagraph(model, paragraph, rawEvent) {
27406
+ function handleTabOnParagraph(model, paragraph, rawEvent, context) {
26666
27407
  var selectedSegments = paragraph.segments.filter(function (segment) { return segment.isSelected; });
26667
27408
  var isCollapsed = selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';
26668
27409
  var isAllSelected = paragraph.segments.every(function (segment) { return segment.isSelected; });
@@ -26674,7 +27415,7 @@ function handleTabOnParagraph(model, paragraph, rawEvent) {
26674
27415
  (isRtl && (!marginRight || marginRight == '0px')))) {
26675
27416
  return false;
26676
27417
  }
26677
- (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
27418
+ (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent', undefined /*length*/, context);
26678
27419
  }
26679
27420
  else {
26680
27421
  if (!isCollapsed) {
@@ -27062,7 +27803,7 @@ exports.HyperlinkPlugin = HyperlinkPlugin;
27062
27803
  "use strict";
27063
27804
 
27064
27805
  Object.defineProperty(exports, "__esModule", ({ value: true }));
27065
- exports.HyperlinkPlugin = exports.MarkdownPlugin = exports.WatermarkPlugin = exports.ContextMenuPluginBase = exports.ShortcutPlugin = exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoMacOS = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = exports.AutoFormatPlugin = exports.EditPlugin = exports.PastePlugin = exports.TableEditPlugin = void 0;
27806
+ exports.getDOMInsertPointRect = exports.CustomReplacePlugin = exports.PickerPlugin = exports.HyperlinkPlugin = exports.MarkdownPlugin = exports.WatermarkPlugin = exports.ContextMenuPluginBase = exports.ShortcutPlugin = exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoMacOS = exports.ShortcutRedoAlt = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = exports.AutoFormatPlugin = exports.EditPlugin = exports.PastePlugin = exports.TableEditPlugin = void 0;
27066
27807
  var TableEditPlugin_1 = __webpack_require__(/*! ./tableEdit/TableEditPlugin */ "./packages/roosterjs-content-model-plugins/lib/tableEdit/TableEditPlugin.ts");
27067
27808
  Object.defineProperty(exports, "TableEditPlugin", ({ enumerable: true, get: function () { return TableEditPlugin_1.TableEditPlugin; } }));
27068
27809
  var PastePlugin_1 = __webpack_require__(/*! ./paste/PastePlugin */ "./packages/roosterjs-content-model-plugins/lib/paste/PastePlugin.ts");
@@ -27079,6 +27820,7 @@ Object.defineProperty(exports, "ShortcutClearFormat", ({ enumerable: true, get:
27079
27820
  Object.defineProperty(exports, "ShortcutUndo", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutUndo; } }));
27080
27821
  Object.defineProperty(exports, "ShortcutUndo2", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutUndo2; } }));
27081
27822
  Object.defineProperty(exports, "ShortcutRedo", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutRedo; } }));
27823
+ Object.defineProperty(exports, "ShortcutRedoAlt", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutRedoAlt; } }));
27082
27824
  Object.defineProperty(exports, "ShortcutRedoMacOS", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutRedoMacOS; } }));
27083
27825
  Object.defineProperty(exports, "ShortcutBullet", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutBullet; } }));
27084
27826
  Object.defineProperty(exports, "ShortcutNumbering", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutNumbering; } }));
@@ -27096,6 +27838,12 @@ var MarkdownPlugin_1 = __webpack_require__(/*! ./markdown/MarkdownPlugin */ "./p
27096
27838
  Object.defineProperty(exports, "MarkdownPlugin", ({ enumerable: true, get: function () { return MarkdownPlugin_1.MarkdownPlugin; } }));
27097
27839
  var HyperlinkPlugin_1 = __webpack_require__(/*! ./hyperlink/HyperlinkPlugin */ "./packages/roosterjs-content-model-plugins/lib/hyperlink/HyperlinkPlugin.ts");
27098
27840
  Object.defineProperty(exports, "HyperlinkPlugin", ({ enumerable: true, get: function () { return HyperlinkPlugin_1.HyperlinkPlugin; } }));
27841
+ var PickerPlugin_1 = __webpack_require__(/*! ./picker/PickerPlugin */ "./packages/roosterjs-content-model-plugins/lib/picker/PickerPlugin.ts");
27842
+ Object.defineProperty(exports, "PickerPlugin", ({ enumerable: true, get: function () { return PickerPlugin_1.PickerPlugin; } }));
27843
+ var CustomReplacePlugin_1 = __webpack_require__(/*! ./customReplace/CustomReplacePlugin */ "./packages/roosterjs-content-model-plugins/lib/customReplace/CustomReplacePlugin.ts");
27844
+ Object.defineProperty(exports, "CustomReplacePlugin", ({ enumerable: true, get: function () { return CustomReplacePlugin_1.CustomReplacePlugin; } }));
27845
+ var getDOMInsertPointRect_1 = __webpack_require__(/*! ./pluginUtils/Rect/getDOMInsertPointRect */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getDOMInsertPointRect.ts");
27846
+ Object.defineProperty(exports, "getDOMInsertPointRect", ({ enumerable: true, get: function () { return getDOMInsertPointRect_1.getDOMInsertPointRect; } }));
27099
27847
 
27100
27848
 
27101
27849
  /***/ }),
@@ -27332,16 +28080,18 @@ function setFormat(editor, character, format, codeFormat) {
27332
28080
  var firstCharIndex = previousSegment.text
27333
28081
  .substring(0, lastCharIndex - 1)
27334
28082
  .lastIndexOf(character);
27335
- var formattedText = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, firstCharIndex, lastCharIndex);
27336
- formattedText.text = formattedText.text.replace(character, '').slice(0, -1);
27337
- formattedText.format = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, formattedText.format), format);
27338
- if (codeFormat) {
27339
- formattedText.code = {
27340
- format: codeFormat,
27341
- };
28083
+ if (lastCharIndex - firstCharIndex > 2) {
28084
+ var formattedText = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, firstCharIndex, lastCharIndex);
28085
+ formattedText.text = formattedText.text.replace(character, '').slice(0, -1);
28086
+ formattedText.format = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, formattedText.format), format);
28087
+ if (codeFormat) {
28088
+ formattedText.code = {
28089
+ format: codeFormat,
28090
+ };
28091
+ }
28092
+ context.canUndoByBackspace = true;
28093
+ return true;
27342
28094
  }
27343
- context.canUndoByBackspace = true;
27344
- return true;
27345
28095
  }
27346
28096
  }
27347
28097
  return false;
@@ -28718,6 +29468,343 @@ function setProcessor(domToModelOption, entry, processorOverride) {
28718
29468
  exports.setProcessor = setProcessor;
28719
29469
 
28720
29470
 
29471
+ /***/ }),
29472
+
29473
+ /***/ "./packages/roosterjs-content-model-plugins/lib/picker/PickerHelperImpl.ts":
29474
+ /*!*********************************************************************************!*\
29475
+ !*** ./packages/roosterjs-content-model-plugins/lib/picker/PickerHelperImpl.ts ***!
29476
+ \*********************************************************************************/
29477
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
29478
+
29479
+ "use strict";
29480
+
29481
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
29482
+ exports.PickerHelperImpl = void 0;
29483
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
29484
+ var getQueryString_1 = __webpack_require__(/*! ./getQueryString */ "./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts");
29485
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
29486
+ /**
29487
+ * @internal
29488
+ */
29489
+ var PickerHelperImpl = /** @class */ (function () {
29490
+ function PickerHelperImpl(editor, handler, triggerCharacter) {
29491
+ this.editor = editor;
29492
+ this.handler = handler;
29493
+ this.triggerCharacter = triggerCharacter;
29494
+ this.direction = null;
29495
+ }
29496
+ /**
29497
+ * Replace the query string with a given Content Model.
29498
+ * This is used for commit a change from picker and insert the committed content into editor.
29499
+ * @param model The Content Model to insert
29500
+ * @param options Options for formatting content model
29501
+ * @param canUndoByBackspace Whether this change can be undone using Backspace key
29502
+ */
29503
+ PickerHelperImpl.prototype.replaceQueryString = function (model, options, canUndoByBackspace) {
29504
+ var _this = this;
29505
+ this.editor.focus();
29506
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(this.editor, function (target, previousSegment, paragraph, _, context) {
29507
+ var potentialSegments = [];
29508
+ var queryString = (0, getQueryString_1.getQueryString)(_this.triggerCharacter, paragraph, previousSegment, potentialSegments);
29509
+ if (queryString) {
29510
+ potentialSegments.forEach(function (x) { return (x.isSelected = true); });
29511
+ (0, roosterjs_content_model_dom_1.mergeModel)(target, model, context);
29512
+ context.canUndoByBackspace = canUndoByBackspace;
29513
+ return true;
29514
+ }
29515
+ else {
29516
+ return false;
29517
+ }
29518
+ }, options);
29519
+ };
29520
+ /**
29521
+ * Notify Picker Plugin that picker is closed from the handler code, so picker plugin can quit the suggesting state
29522
+ */
29523
+ PickerHelperImpl.prototype.closePicker = function () {
29524
+ var _a, _b;
29525
+ if (this.direction) {
29526
+ this.direction = null;
29527
+ (_b = (_a = this.handler).onClosePicker) === null || _b === void 0 ? void 0 : _b.call(_a);
29528
+ }
29529
+ };
29530
+ return PickerHelperImpl;
29531
+ }());
29532
+ exports.PickerHelperImpl = PickerHelperImpl;
29533
+
29534
+
29535
+ /***/ }),
29536
+
29537
+ /***/ "./packages/roosterjs-content-model-plugins/lib/picker/PickerPlugin.ts":
29538
+ /*!*****************************************************************************!*\
29539
+ !*** ./packages/roosterjs-content-model-plugins/lib/picker/PickerPlugin.ts ***!
29540
+ \*****************************************************************************/
29541
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
29542
+
29543
+ "use strict";
29544
+
29545
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
29546
+ exports.PickerPlugin = void 0;
29547
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
29548
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
29549
+ var getQueryString_1 = __webpack_require__(/*! ./getQueryString */ "./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts");
29550
+ var PickerHelperImpl_1 = __webpack_require__(/*! ./PickerHelperImpl */ "./packages/roosterjs-content-model-plugins/lib/picker/PickerHelperImpl.ts");
29551
+ /**
29552
+ * PickerPlugin represents a plugin of editor which can handle picker related behaviors, including
29553
+ * - Show picker when special trigger key is pressed
29554
+ * - Hide picker
29555
+ * - Change selection in picker by Up/Down/Left/Right
29556
+ * - Apply selected item in picker
29557
+ *
29558
+ * PickerPlugin doesn't provide any UI, it just wraps related DOM events and invoke callback functions.
29559
+ */
29560
+ var PickerPlugin = /** @class */ (function () {
29561
+ /**
29562
+ * Construct a new instance of PickerPlugin class
29563
+ * @param triggerCharacter The character to trigger a picker to be shown
29564
+ * @param handler Picker handler for receiving picker state change events
29565
+ */
29566
+ function PickerPlugin(triggerCharacter, handler) {
29567
+ this.triggerCharacter = triggerCharacter;
29568
+ this.handler = handler;
29569
+ this.isMac = false;
29570
+ this.lastQueryString = '';
29571
+ this.helper = null;
29572
+ }
29573
+ /**
29574
+ * Get a friendly name
29575
+ */
29576
+ PickerPlugin.prototype.getName = function () {
29577
+ return 'Picker';
29578
+ };
29579
+ /**
29580
+ * Initialize this plugin. This should only be called from Editor
29581
+ * @param editor Editor instance
29582
+ */
29583
+ PickerPlugin.prototype.initialize = function (editor) {
29584
+ this.isMac = !!editor.getEnvironment().isMac;
29585
+ this.helper = new PickerHelperImpl_1.PickerHelperImpl(editor, this.handler, this.triggerCharacter);
29586
+ this.handler.onInitialize(this.helper);
29587
+ };
29588
+ /**
29589
+ * Dispose this plugin
29590
+ */
29591
+ PickerPlugin.prototype.dispose = function () {
29592
+ this.handler.onDispose();
29593
+ this.helper = null;
29594
+ };
29595
+ /**
29596
+ * Check if the plugin should handle the given event exclusively.
29597
+ * Handle an event exclusively means other plugin will not receive this event in
29598
+ * onPluginEvent method.
29599
+ * If two plugins will return true in willHandleEventExclusively() for the same event,
29600
+ * the final result depends on the order of the plugins are added into editor
29601
+ * @param event The event to check
29602
+ */
29603
+ PickerPlugin.prototype.willHandleEventExclusively = function (event) {
29604
+ var _a;
29605
+ return (!!((_a = this.helper) === null || _a === void 0 ? void 0 : _a.direction) &&
29606
+ event.eventType == 'keyDown' &&
29607
+ ((0, roosterjs_content_model_dom_1.isCursorMovingKey)(event.rawEvent) ||
29608
+ event.rawEvent.key == 'Enter' ||
29609
+ event.rawEvent.key == 'Tab' ||
29610
+ event.rawEvent.key == 'Escape'));
29611
+ };
29612
+ /**
29613
+ * Handle events triggered from editor
29614
+ * @param event PluginEvent object
29615
+ */
29616
+ PickerPlugin.prototype.onPluginEvent = function (event) {
29617
+ if (!this.helper) {
29618
+ return;
29619
+ }
29620
+ switch (event.eventType) {
29621
+ case 'contentChanged':
29622
+ if (this.helper.direction) {
29623
+ if (event.source == roosterjs_content_model_dom_1.ChangeSource.SetContent) {
29624
+ this.helper.closePicker();
29625
+ }
29626
+ else {
29627
+ this.onSuggestingInput(this.helper);
29628
+ }
29629
+ }
29630
+ break;
29631
+ case 'keyDown':
29632
+ if (this.helper.direction) {
29633
+ this.onSuggestingKeyDown(this.helper, event.rawEvent);
29634
+ }
29635
+ break;
29636
+ case 'input':
29637
+ if (this.helper.direction) {
29638
+ this.onSuggestingInput(this.helper);
29639
+ }
29640
+ else {
29641
+ this.onInput(this.helper, event.rawEvent);
29642
+ }
29643
+ break;
29644
+ case 'mouseUp':
29645
+ if (this.helper.direction) {
29646
+ this.helper.closePicker();
29647
+ }
29648
+ break;
29649
+ }
29650
+ };
29651
+ PickerPlugin.prototype.onSuggestingKeyDown = function (helper, event) {
29652
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
29653
+ switch (event.key) {
29654
+ case 'ArrowLeft':
29655
+ case 'ArrowRight':
29656
+ if (helper.direction == 'horizontal' || helper.direction == 'both') {
29657
+ var isIncrement = event.key == 'ArrowRight';
29658
+ if (helper.editor.getDOMHelper().isRightToLeft()) {
29659
+ isIncrement = !isIncrement;
29660
+ }
29661
+ (_b = (_a = this.handler).onSelectionChanged) === null || _b === void 0 ? void 0 : _b.call(_a, isIncrement ? 'next' : 'previous');
29662
+ }
29663
+ event.preventDefault();
29664
+ break;
29665
+ case 'ArrowUp':
29666
+ case 'ArrowDown':
29667
+ {
29668
+ var isIncrement = event.key == 'ArrowDown';
29669
+ if (helper.direction != 'horizontal') {
29670
+ (_d = (_c = this.handler).onSelectionChanged) === null || _d === void 0 ? void 0 : _d.call(_c, helper.direction == 'both'
29671
+ ? isIncrement
29672
+ ? 'nextRow'
29673
+ : 'previousRow'
29674
+ : isIncrement
29675
+ ? 'next'
29676
+ : 'previous');
29677
+ }
29678
+ }
29679
+ event.preventDefault();
29680
+ break;
29681
+ case 'PageUp':
29682
+ case 'PageDown':
29683
+ (_f = (_e = this.handler).onSelectionChanged) === null || _f === void 0 ? void 0 : _f.call(_e, event.key == 'PageDown' ? 'nextPage' : 'previousPage');
29684
+ event.preventDefault();
29685
+ break;
29686
+ case 'Home':
29687
+ case 'End':
29688
+ var hasCtrl = this.isMac ? event.metaKey : event.ctrlKey;
29689
+ (_h = (_g = this.handler).onSelectionChanged) === null || _h === void 0 ? void 0 : _h.call(_g, event.key == 'Home'
29690
+ ? hasCtrl
29691
+ ? 'first'
29692
+ : 'firstInRow'
29693
+ : hasCtrl
29694
+ ? 'last'
29695
+ : 'lastInRow');
29696
+ event.preventDefault();
29697
+ break;
29698
+ case 'Escape':
29699
+ helper.closePicker();
29700
+ event.preventDefault();
29701
+ break;
29702
+ case 'Enter':
29703
+ case 'Tab':
29704
+ (_k = (_j = this.handler).onSelect) === null || _k === void 0 ? void 0 : _k.call(_j);
29705
+ event.preventDefault();
29706
+ break;
29707
+ }
29708
+ };
29709
+ PickerPlugin.prototype.onSuggestingInput = function (helper) {
29710
+ var _this = this;
29711
+ if (!(0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(helper.editor, function (_, segment, paragraph) {
29712
+ var _a, _b;
29713
+ var newQueryString = (0, getQueryString_1.getQueryString)(_this.triggerCharacter, paragraph, segment).replace(/[\u0020\u00A0]/g, ' ');
29714
+ var oldQueryString = _this.lastQueryString;
29715
+ if (newQueryString &&
29716
+ ((newQueryString.length >= oldQueryString.length &&
29717
+ newQueryString.indexOf(oldQueryString) == 0) ||
29718
+ (newQueryString.length < oldQueryString.length &&
29719
+ oldQueryString.indexOf(newQueryString) == 0))) {
29720
+ _this.lastQueryString = newQueryString;
29721
+ (_b = (_a = _this.handler).onQueryStringChanged) === null || _b === void 0 ? void 0 : _b.call(_a, newQueryString);
29722
+ }
29723
+ else {
29724
+ helper.closePicker();
29725
+ }
29726
+ return false;
29727
+ })) {
29728
+ helper.closePicker();
29729
+ }
29730
+ };
29731
+ PickerPlugin.prototype.onInput = function (helper, event) {
29732
+ var _this = this;
29733
+ if (event.inputType == 'insertText' && event.data == this.triggerCharacter) {
29734
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(helper.editor, function (_, segment) {
29735
+ if (segment.text.endsWith(_this.triggerCharacter)) {
29736
+ var charBeforeTrigger = segment.text[segment.text.length - 2];
29737
+ if (!charBeforeTrigger ||
29738
+ !charBeforeTrigger.trim() ||
29739
+ (0, roosterjs_content_model_dom_1.isPunctuation)(charBeforeTrigger)) {
29740
+ var selection = helper.editor.getDOMSelection();
29741
+ var pos = (selection === null || selection === void 0 ? void 0 : selection.type) == 'range' && selection.range.collapsed
29742
+ ? {
29743
+ node: selection.range.startContainer,
29744
+ offset: selection.range.startOffset,
29745
+ }
29746
+ : null;
29747
+ if (pos) {
29748
+ _this.lastQueryString = _this.triggerCharacter;
29749
+ helper.direction = _this.handler.onTrigger(_this.lastQueryString, pos);
29750
+ }
29751
+ }
29752
+ }
29753
+ return false;
29754
+ });
29755
+ }
29756
+ };
29757
+ return PickerPlugin;
29758
+ }());
29759
+ exports.PickerPlugin = PickerPlugin;
29760
+
29761
+
29762
+ /***/ }),
29763
+
29764
+ /***/ "./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts":
29765
+ /*!*******************************************************************************!*\
29766
+ !*** ./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts ***!
29767
+ \*******************************************************************************/
29768
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
29769
+
29770
+ "use strict";
29771
+
29772
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
29773
+ exports.getQueryString = void 0;
29774
+ var splitTextSegment_1 = __webpack_require__(/*! ../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
29775
+ /**
29776
+ * @internal
29777
+ */
29778
+ function getQueryString(triggerCharacter, paragraph, previousSegment, splittedSegmentResult) {
29779
+ var result = '';
29780
+ var i = paragraph.segments.indexOf(previousSegment);
29781
+ for (; i >= 0; i--) {
29782
+ var segment = paragraph.segments[i];
29783
+ if (segment.segmentType != 'Text') {
29784
+ result = '';
29785
+ break;
29786
+ }
29787
+ var index = segment.text.lastIndexOf(triggerCharacter);
29788
+ if (index >= 0) {
29789
+ result = segment.text.substring(index) + result;
29790
+ splittedSegmentResult === null || splittedSegmentResult === void 0 ? void 0 : splittedSegmentResult.unshift(index > 0
29791
+ ? (0, splitTextSegment_1.splitTextSegment)(segment, paragraph, index, segment.text.length)
29792
+ : segment);
29793
+ break;
29794
+ }
29795
+ else {
29796
+ result = segment.text + result;
29797
+ splittedSegmentResult === null || splittedSegmentResult === void 0 ? void 0 : splittedSegmentResult.unshift(segment);
29798
+ }
29799
+ }
29800
+ if (i < 0) {
29801
+ result = '';
29802
+ }
29803
+ return result;
29804
+ }
29805
+ exports.getQueryString = getQueryString;
29806
+
29807
+
28721
29808
  /***/ }),
28722
29809
 
28723
29810
  /***/ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/CreateElement/createElement.ts":
@@ -28911,6 +29998,73 @@ var DragAndDropHelper = /** @class */ (function () {
28911
29998
  exports.DragAndDropHelper = DragAndDropHelper;
28912
29999
 
28913
30000
 
30001
+ /***/ }),
30002
+
30003
+ /***/ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getDOMInsertPointRect.ts":
30004
+ /*!************************************************************************************************!*\
30005
+ !*** ./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getDOMInsertPointRect.ts ***!
30006
+ \************************************************************************************************/
30007
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
30008
+
30009
+ "use strict";
30010
+
30011
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
30012
+ exports.getDOMInsertPointRect = void 0;
30013
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
30014
+ /**
30015
+ * Get bounding rect of the given DOM insert point
30016
+ * @param doc The document object
30017
+ * @param pos The input DOM insert point
30018
+ */
30019
+ function getDOMInsertPointRect(doc, pos) {
30020
+ var _a;
30021
+ var node = pos.node, offset = pos.offset;
30022
+ var range = doc.createRange();
30023
+ range.setStart(node, offset);
30024
+ // 1) try to get rect using range.getBoundingClientRect()
30025
+ var rect = (0, roosterjs_content_model_dom_1.normalizeRect)(range.getBoundingClientRect());
30026
+ if (rect) {
30027
+ return rect;
30028
+ }
30029
+ // 2) try to get rect using range.getClientRects
30030
+ while (node.lastChild) {
30031
+ if (offset == node.childNodes.length) {
30032
+ node = node.lastChild;
30033
+ offset = node.childNodes.length;
30034
+ }
30035
+ else {
30036
+ node = node.childNodes[offset];
30037
+ offset = 0;
30038
+ }
30039
+ }
30040
+ var rects = range.getClientRects && range.getClientRects();
30041
+ rect = rects && rects.length == 1 ? (0, roosterjs_content_model_dom_1.normalizeRect)(rects[0]) : null;
30042
+ if (rect) {
30043
+ return rect;
30044
+ }
30045
+ // 3) if node is text node, try inserting a SPAN and get the rect of SPAN for others
30046
+ if ((0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'TEXT_NODE')) {
30047
+ var span = node.ownerDocument.createElement('span');
30048
+ span.textContent = '\u200b';
30049
+ range.insertNode(span);
30050
+ rect = (0, roosterjs_content_model_dom_1.normalizeRect)(span.getBoundingClientRect());
30051
+ (_a = span.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(span);
30052
+ if (rect) {
30053
+ return rect;
30054
+ }
30055
+ }
30056
+ // 4) try getBoundingClientRect on element
30057
+ if ((0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'ELEMENT_NODE') && node.getBoundingClientRect) {
30058
+ rect = (0, roosterjs_content_model_dom_1.normalizeRect)(node.getBoundingClientRect());
30059
+ if (rect) {
30060
+ return rect;
30061
+ }
30062
+ }
30063
+ return null;
30064
+ }
30065
+ exports.getDOMInsertPointRect = getDOMInsertPointRect;
30066
+
30067
+
28914
30068
  /***/ }),
28915
30069
 
28916
30070
  /***/ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getIntersectedRect.ts":
@@ -29025,6 +30179,7 @@ var defaultShortcuts = [
29025
30179
  shortcuts_1.ShortcutUndo,
29026
30180
  shortcuts_1.ShortcutUndo2,
29027
30181
  shortcuts_1.ShortcutRedo,
30182
+ shortcuts_1.ShortcutRedoAlt,
29028
30183
  shortcuts_1.ShortcutRedoMacOS,
29029
30184
  shortcuts_1.ShortcutBullet,
29030
30185
  shortcuts_1.ShortcutNumbering,
@@ -29144,7 +30299,7 @@ exports.ShortcutPlugin = ShortcutPlugin;
29144
30299
  "use strict";
29145
30300
 
29146
30301
  Object.defineProperty(exports, "__esModule", ({ value: true }));
29147
- exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoMacOS = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = void 0;
30302
+ exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoAlt = exports.ShortcutRedoMacOS = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = void 0;
29148
30303
  var roosterjs_content_model_core_1 = __webpack_require__(/*! roosterjs-content-model-core */ "./packages/roosterjs-content-model-core/lib/index.ts");
29149
30304
  var setShortcutIndentationCommand_1 = __webpack_require__(/*! ./utils/setShortcutIndentationCommand */ "./packages/roosterjs-content-model-plugins/lib/shortcut/utils/setShortcutIndentationCommand.ts");
29150
30305
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
@@ -29258,6 +30413,7 @@ exports.ShortcutRedo = {
29258
30413
  environment: 'nonMac',
29259
30414
  };
29260
30415
  /**
30416
+ * @deprecated
29261
30417
  * Shortcut command for Redo 2
29262
30418
  * Windows: N/A
29263
30419
  * MacOS: Meta + Shift + Z
@@ -29271,6 +30427,19 @@ exports.ShortcutRedoMacOS = {
29271
30427
  onClick: function (editor) { return (0, roosterjs_content_model_core_1.redo)(editor); },
29272
30428
  environment: 'mac',
29273
30429
  };
30430
+ /**
30431
+ * Shortcut command for Redo 3
30432
+ * Windows: Ctrl + Shift + Z
30433
+ * MacOS: Meta + Shift + Z
30434
+ */
30435
+ exports.ShortcutRedoAlt = {
30436
+ shortcutKey: {
30437
+ modifierKey: 'ctrl',
30438
+ shiftKey: true,
30439
+ which: 90 /* Z */,
30440
+ },
30441
+ onClick: function (editor) { return (0, roosterjs_content_model_core_1.redo)(editor); },
30442
+ };
29274
30443
  /**
29275
30444
  * Shortcut command for Bullet List
29276
30445
  * Windows: Ctrl + . (Period)
@@ -29375,12 +30544,12 @@ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-mo
29375
30544
  * @internal
29376
30545
  */
29377
30546
  function setShortcutIndentationCommand(editor, operation) {
29378
- editor.formatContentModel(function (model) {
30547
+ editor.formatContentModel(function (model, context) {
29379
30548
  var listItem = (0, roosterjs_content_model_dom_1.getFirstSelectedListItem)(model);
29380
30549
  if (listItem &&
29381
30550
  listItem.blocks[0].blockType == 'Paragraph' &&
29382
30551
  listItem.blocks[0].segments[0].segmentType == 'SelectionMarker') {
29383
- (0, roosterjs_content_model_api_1.setModelIndentation)(model, operation);
30552
+ (0, roosterjs_content_model_api_1.setModelIndentation)(model, operation, undefined /*length*/, context);
29384
30553
  return true;
29385
30554
  }
29386
30555
  return false;
@@ -29413,10 +30582,12 @@ var TableEditPlugin = /** @class */ (function () {
29413
30582
  * @param anchorContainerSelector An optional selector string to specify the container to host the plugin.
29414
30583
  * The container must not be affected by transform: scale(), otherwise the position calculation will be wrong.
29415
30584
  * If not specified, the plugin will be inserted in document.body
30585
+ * @param onTableEditorCreated An optional callback to customize the Table Editors elements when created.
29416
30586
  */
29417
- function TableEditPlugin(anchorContainerSelector) {
30587
+ function TableEditPlugin(anchorContainerSelector, onTableEditorCreated) {
29418
30588
  var _this = this;
29419
30589
  this.anchorContainerSelector = anchorContainerSelector;
30590
+ this.onTableEditorCreated = onTableEditorCreated;
29420
30591
  this.editor = null;
29421
30592
  this.onMouseMoveDisposer = null;
29422
30593
  this.tableRectMap = null;
@@ -29494,6 +30665,7 @@ var TableEditPlugin = /** @class */ (function () {
29494
30665
  this.disposeTableEditor();
29495
30666
  this.editor = null;
29496
30667
  this.onMouseMoveDisposer = null;
30668
+ this.onTableEditorCreated = undefined;
29497
30669
  };
29498
30670
  /**
29499
30671
  * Handle events triggered from editor
@@ -29524,7 +30696,7 @@ var TableEditPlugin = /** @class */ (function () {
29524
30696
  var container = this.anchorContainerSelector
29525
30697
  ? this.editor.getDocument().querySelector(this.anchorContainerSelector)
29526
30698
  : undefined;
29527
- this.tableEditor = new TableEditor_1.TableEditor(this.editor, table, this.invalidateTableRects, (0, roosterjs_content_model_dom_1.isNodeOfType)(container, 'ELEMENT_NODE') ? container : undefined, event === null || event === void 0 ? void 0 : event.currentTarget);
30699
+ this.tableEditor = new TableEditor_1.TableEditor(this.editor, table, this.invalidateTableRects, (0, roosterjs_content_model_dom_1.isNodeOfType)(container, 'ELEMENT_NODE') ? container : undefined, event === null || event === void 0 ? void 0 : event.currentTarget, this.onTableEditorCreated);
29528
30700
  }
29529
30701
  };
29530
30702
  TableEditPlugin.prototype.disposeTableEditor = function () {
@@ -29609,7 +30781,7 @@ var TOP_OR_SIDE;
29609
30781
  * When set a different current table or change current TD, we need to update these areas
29610
30782
  */
29611
30783
  var TableEditor = /** @class */ (function () {
29612
- function TableEditor(editor, table, onChanged, anchorContainer, contentDiv) {
30784
+ function TableEditor(editor, table, onChanged, anchorContainer, contentDiv, onTableEditorCreated) {
29613
30785
  var _this = this;
29614
30786
  var _a;
29615
30787
  this.editor = editor;
@@ -29617,6 +30789,7 @@ var TableEditor = /** @class */ (function () {
29617
30789
  this.onChanged = onChanged;
29618
30790
  this.anchorContainer = anchorContainer;
29619
30791
  this.contentDiv = contentDiv;
30792
+ this.onTableEditorCreated = onTableEditorCreated;
29620
30793
  // 1, 2 - Insert a column or a row
29621
30794
  this.horizontalInserter = null;
29622
30795
  this.verticalInserter = null;
@@ -29628,6 +30801,20 @@ var TableEditor = /** @class */ (function () {
29628
30801
  // 6 - Move as well as select whole table
29629
30802
  this.tableMover = null;
29630
30803
  this.range = null;
30804
+ this.onEditorCreated = function (editorType, element) {
30805
+ var _a;
30806
+ var disposer = (_a = _this.onTableEditorCreated) === null || _a === void 0 ? void 0 : _a.call(_this, editorType, element);
30807
+ var onMouseOut = element && _this.getOnMouseOut(element);
30808
+ if (onMouseOut) {
30809
+ element.addEventListener('mouseout', onMouseOut);
30810
+ }
30811
+ return function () {
30812
+ disposer === null || disposer === void 0 ? void 0 : disposer();
30813
+ if (onMouseOut) {
30814
+ element.removeEventListener('mouseout', onMouseOut);
30815
+ }
30816
+ };
30817
+ };
29631
30818
  this.onFinishEditing = function () {
29632
30819
  _this.editor.focus();
29633
30820
  if (_this.range) {
@@ -29656,14 +30843,16 @@ var TableEditor = /** @class */ (function () {
29656
30843
  * @param table the table to select
29657
30844
  */
29658
30845
  this.onSelect = function (table) {
30846
+ var _a, _b;
29659
30847
  _this.editor.focus();
29660
30848
  if (table) {
30849
+ var parsedTable = (0, roosterjs_content_model_dom_1.parseTableCells)(table);
29661
30850
  var selection = {
29662
30851
  table: table,
29663
30852
  firstRow: 0,
29664
30853
  firstColumn: 0,
29665
- lastRow: table.rows.length - 1,
29666
- lastColumn: table.rows[table.rows.length - 1].cells.length - 1,
30854
+ lastRow: parsedTable.length - 1,
30855
+ lastColumn: ((_b = (_a = parsedTable[0]) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) - 1,
29667
30856
  type: 'table',
29668
30857
  };
29669
30858
  _this.editor.setDOMSelection(selection);
@@ -29709,7 +30898,6 @@ var TableEditor = /** @class */ (function () {
29709
30898
  var _a;
29710
30899
  // Get whole table rect
29711
30900
  var tableRect = (0, roosterjs_content_model_dom_1.normalizeRect)(this.table.getBoundingClientRect());
29712
- //console.log('>>>tableRect', tableRect);
29713
30901
  if (!tableRect) {
29714
30902
  return;
29715
30903
  }
@@ -29780,10 +30968,10 @@ var TableEditor = /** @class */ (function () {
29780
30968
  };
29781
30969
  TableEditor.prototype.setEditorFeatures = function () {
29782
30970
  if (!this.tableMover) {
29783
- this.tableMover = (0, TableMover_1.createTableMover)(this.table, this.editor, this.isRTL, this.onSelect, this.getOnMouseOut, this.contentDiv, this.anchorContainer);
30971
+ this.tableMover = (0, TableMover_1.createTableMover)(this.table, this.editor, this.isRTL, this.onSelect, this.contentDiv, this.anchorContainer, this.onEditorCreated);
29784
30972
  }
29785
30973
  if (!this.tableResizer) {
29786
- this.tableResizer = (0, TableResizer_1.createTableResizer)(this.table, this.editor, this.isRTL, this.onStartTableResize, this.onFinishEditing, this.contentDiv, this.anchorContainer);
30974
+ this.tableResizer = (0, TableResizer_1.createTableResizer)(this.table, this.editor, this.isRTL, this.onStartTableResize, this.onFinishEditing, this.contentDiv, this.anchorContainer, this.onTableEditorCreated);
29787
30975
  }
29788
30976
  };
29789
30977
  TableEditor.prototype.setResizingTd = function (td) {
@@ -29805,7 +30993,7 @@ var TableEditor = /** @class */ (function () {
29805
30993
  this.disposeTableInserter();
29806
30994
  }
29807
30995
  if (!this.horizontalInserter && !this.verticalInserter && td) {
29808
- var newInserter = (0, TableInserter_1.createTableInserter)(this.editor, td, this.table, this.isRTL, !!isHorizontal, this.onInserted, this.getOnMouseOut, this.anchorContainer);
30996
+ var newInserter = (0, TableInserter_1.createTableInserter)(this.editor, td, this.table, this.isRTL, !!isHorizontal, this.onInserted, this.anchorContainer, this.onEditorCreated);
29809
30997
  if (isHorizontal) {
29810
30998
  this.horizontalInserter = newInserter;
29811
30999
  }
@@ -30055,10 +31243,10 @@ exports.disposeTableEditFeature = void 0;
30055
31243
  function disposeTableEditFeature(resizer) {
30056
31244
  var _a, _b, _c;
30057
31245
  if (resizer) {
30058
- (_b = (_a = resizer.div) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(resizer.div);
30059
- resizer.div = null;
30060
- (_c = resizer.featureHandler) === null || _c === void 0 ? void 0 : _c.dispose();
31246
+ (_a = resizer.featureHandler) === null || _a === void 0 ? void 0 : _a.dispose();
30061
31247
  resizer.featureHandler = null;
31248
+ (_c = (_b = resizer.div) === null || _b === void 0 ? void 0 : _b.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(resizer.div);
31249
+ resizer.div = null;
30062
31250
  }
30063
31251
  }
30064
31252
  exports.disposeTableEditFeature = disposeTableEditFeature;
@@ -30087,7 +31275,7 @@ var INSERTER_BORDER_SIZE = 1;
30087
31275
  /**
30088
31276
  * @internal
30089
31277
  */
30090
- function createTableInserter(editor, td, table, isRTL, isHorizontal, onInsert, getOnMouseOut, anchorContainer) {
31278
+ function createTableInserter(editor, td, table, isRTL, isHorizontal, onInsert, anchorContainer, onTableEditorCreated) {
30091
31279
  var tdRect = (0, roosterjs_content_model_dom_1.normalizeRect)(td.getBoundingClientRect());
30092
31280
  var viewPort = editor.getVisibleViewport();
30093
31281
  var tableRect = table && viewPort ? (0, getIntersectedRect_1.getIntersectedRect)([table], [viewPort]) : null;
@@ -30113,14 +31301,14 @@ function createTableInserter(editor, td, table, isRTL, isHorizontal, onInsert, g
30113
31301
  div.firstChild.style.height = tableRect.bottom - tableRect.top + "px";
30114
31302
  }
30115
31303
  (anchorContainer || document_1.body).appendChild(div);
30116
- var handler = new TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, getOnMouseOut);
31304
+ var handler = new TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, onTableEditorCreated);
30117
31305
  return { div: div, featureHandler: handler, node: td };
30118
31306
  }
30119
31307
  return null;
30120
31308
  }
30121
31309
  exports.createTableInserter = createTableInserter;
30122
31310
  var TableInsertHandler = /** @class */ (function () {
30123
- function TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, getOnMouseOut) {
31311
+ function TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, onTableEditorCreated) {
30124
31312
  var _this = this;
30125
31313
  this.div = div;
30126
31314
  this.td = td;
@@ -30155,15 +31343,13 @@ var TableInsertHandler = /** @class */ (function () {
30155
31343
  _this.onInsert();
30156
31344
  };
30157
31345
  this.div.addEventListener('click', this.insertTd);
30158
- this.onMouseOutEvent = getOnMouseOut(div);
30159
- this.div.addEventListener('mouseout', this.onMouseOutEvent);
31346
+ this.disposer = onTableEditorCreated === null || onTableEditorCreated === void 0 ? void 0 : onTableEditorCreated(isHorizontal ? 'HorizontalTableInserter' : 'VerticalTableInserter', div);
30160
31347
  }
30161
31348
  TableInsertHandler.prototype.dispose = function () {
31349
+ var _a;
30162
31350
  this.div.removeEventListener('click', this.insertTd);
30163
- if (this.onMouseOutEvent) {
30164
- this.div.removeEventListener('mouseout', this.onMouseOutEvent);
30165
- }
30166
- this.onMouseOutEvent = null;
31351
+ (_a = this.disposer) === null || _a === void 0 ? void 0 : _a.call(this);
31352
+ this.disposer = undefined;
30167
31353
  };
30168
31354
  return TableInsertHandler;
30169
31355
  }());
@@ -30210,7 +31396,7 @@ var TABLE_MOVER_ID = '_Table_Mover';
30210
31396
  * Contains the function to select whole table
30211
31397
  * Moving behavior not implemented yet
30212
31398
  */
30213
- function createTableMover(table, editor, isRTL, onFinishDragging, getOnMouseOut, contentDiv, anchorContainer) {
31399
+ function createTableMover(table, editor, isRTL, onFinishDragging, contentDiv, anchorContainer, onTableEditorCreated) {
30214
31400
  var rect = (0, roosterjs_content_model_dom_1.normalizeRect)(table.getBoundingClientRect());
30215
31401
  if (!isTableTopVisible(editor, rect, contentDiv)) {
30216
31402
  return null;
@@ -30241,25 +31427,22 @@ function createTableMover(table, editor, isRTL, onFinishDragging, getOnMouseOut,
30241
31427
  };
30242
31428
  var featureHandler = new TableMoverFeature(div, context, setDivPosition, {
30243
31429
  onDragEnd: onDragEnd,
30244
- }, context.zoomScale, getOnMouseOut);
31430
+ }, context.zoomScale, onTableEditorCreated);
30245
31431
  return { div: div, featureHandler: featureHandler, node: table };
30246
31432
  }
30247
31433
  exports.createTableMover = createTableMover;
30248
31434
  var TableMoverFeature = /** @class */ (function (_super) {
30249
31435
  (0, tslib_1.__extends)(TableMoverFeature, _super);
30250
- function TableMoverFeature(div, context, onSubmit, handler, zoomScale, getOnMouseOut, forceMobile, container) {
30251
- var _this = _super.call(this, div, context, onSubmit, handler, zoomScale, forceMobile) || this;
30252
- _this.div = div;
30253
- _this.onMouseOut = getOnMouseOut(div);
30254
- div.addEventListener('mouseout', _this.onMouseOut);
31436
+ function TableMoverFeature(div, context, onSubmit, handler, zoomScale, onTableEditorCreated) {
31437
+ var _this = _super.call(this, div, context, onSubmit, handler, zoomScale) || this;
31438
+ _this.disposer = onTableEditorCreated === null || onTableEditorCreated === void 0 ? void 0 : onTableEditorCreated('TableMover', div);
30255
31439
  return _this;
30256
31440
  }
30257
31441
  TableMoverFeature.prototype.dispose = function () {
31442
+ var _a;
31443
+ (_a = this.disposer) === null || _a === void 0 ? void 0 : _a.call(this);
31444
+ this.disposer = undefined;
30258
31445
  _super.prototype.dispose.call(this);
30259
- if (this.onMouseOut) {
30260
- this.div.removeEventListener('mouseout', this.onMouseOut);
30261
- }
30262
- this.onMouseOut = null;
30263
31446
  };
30264
31447
  return TableMoverFeature;
30265
31448
  }(DragAndDropHelper_1.DragAndDropHelper));
@@ -30292,6 +31475,7 @@ function isTableTopVisible(editor, rect, contentDiv) {
30292
31475
 
30293
31476
  Object.defineProperty(exports, "__esModule", ({ value: true }));
30294
31477
  exports.createTableResizer = void 0;
31478
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
30295
31479
  var createElement_1 = __webpack_require__(/*! ../../../pluginUtils/CreateElement/createElement */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/CreateElement/createElement.ts");
30296
31480
  var DragAndDropHelper_1 = __webpack_require__(/*! ../../../pluginUtils/DragAndDrop/DragAndDropHelper */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/DragAndDrop/DragAndDropHelper.ts");
30297
31481
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
@@ -30300,7 +31484,7 @@ var TABLE_RESIZER_ID = '_Table_Resizer';
30300
31484
  /**
30301
31485
  * @internal
30302
31486
  */
30303
- function createTableResizer(table, editor, isRTL, onStart, onEnd, contentDiv, anchorContainer) {
31487
+ function createTableResizer(table, editor, isRTL, onStart, onEnd, contentDiv, anchorContainer, onTableEditorCreated) {
30304
31488
  var rect = (0, roosterjs_content_model_dom_1.normalizeRect)(table.getBoundingClientRect());
30305
31489
  if (!isTableBottomVisible(editor, rect, contentDiv)) {
30306
31490
  return null;
@@ -30327,15 +31511,30 @@ function createTableResizer(table, editor, isRTL, onStart, onEnd, contentDiv, an
30327
31511
  contentDiv: contentDiv,
30328
31512
  };
30329
31513
  setDivPosition(context, div);
30330
- var featureHandler = new DragAndDropHelper_1.DragAndDropHelper(div, context, hideResizer, // Resizer is hidden while dragging only
31514
+ var featureHandler = new TableResizer(div, context, hideResizer, // Resizer is hidden while dragging only
30331
31515
  {
30332
31516
  onDragStart: onDragStart,
30333
31517
  onDragging: onDragging,
30334
31518
  onDragEnd: onDragEnd,
30335
- }, zoomScale, editor.getEnvironment().isMobileOrTablet);
31519
+ }, zoomScale, editor.getEnvironment().isMobileOrTablet, onTableEditorCreated);
30336
31520
  return { node: table, div: div, featureHandler: featureHandler };
30337
31521
  }
30338
31522
  exports.createTableResizer = createTableResizer;
31523
+ var TableResizer = /** @class */ (function (_super) {
31524
+ (0, tslib_1.__extends)(TableResizer, _super);
31525
+ function TableResizer(trigger, context, onSubmit, handler, zoomScale, forceMobile, onTableEditorCreated) {
31526
+ var _this = _super.call(this, trigger, context, onSubmit, handler, zoomScale, forceMobile) || this;
31527
+ _this.disposer = onTableEditorCreated === null || onTableEditorCreated === void 0 ? void 0 : onTableEditorCreated('TableResizer', trigger);
31528
+ return _this;
31529
+ }
31530
+ TableResizer.prototype.dispose = function () {
31531
+ var _a;
31532
+ (_a = this.disposer) === null || _a === void 0 ? void 0 : _a.call(this);
31533
+ this.disposer = undefined;
31534
+ _super.prototype.dispose.call(this);
31535
+ };
31536
+ return TableResizer;
31537
+ }(DragAndDropHelper_1.DragAndDropHelper));
30339
31538
  function onDragStart(context, event) {
30340
31539
  context.onStart();
30341
31540
  var editor = context.editor, table = context.table;