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