roosterjs 9.0.0 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/rooster.js CHANGED
@@ -2094,8 +2094,8 @@ exports["default"] = getDarkColor;
2094
2094
  "use strict";
2095
2095
 
2096
2096
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2097
- exports.setModelListStyle = exports.setListType = exports.formatSegmentWithContentModel = exports.formatParagraphWithContentModel = exports.formatImageWithContentModel = exports.formatTableWithContentModel = exports.insertTableColumn = exports.insertTableRow = exports.insertEntity = exports.toggleCode = exports.setParagraphMargin = exports.adjustImageSelection = exports.setImageAltText = exports.adjustLinkSelection = exports.removeLink = exports.insertLink = exports.clearFormat = exports.getFormatState = exports.changeImage = exports.setImageBoxShadow = exports.setImageBorder = exports.setSpacing = exports.toggleBlockQuote = exports.setHeadingLevel = exports.setDirection = exports.setAlignment = exports.setIndentation = exports.setListStartNumber = exports.setListStyle = exports.insertImage = exports.changeCapitalization = exports.applySegmentFormat = exports.changeFontSize = exports.setTextColor = exports.setFontSize = exports.setFontName = exports.setBackgroundColor = exports.toggleSuperscript = exports.toggleSubscript = exports.toggleStrikethrough = exports.toggleUnderline = exports.toggleItalic = exports.toggleBold = exports.toggleNumbering = exports.toggleBullet = exports.applyTableBorderFormat = exports.editTable = exports.setTableCellShade = exports.formatTable = exports.insertTable = void 0;
2098
- exports.matchLink = exports.setModelIndentation = exports.findListItemsInSameThread = exports.setModelListStartNumber = void 0;
2097
+ exports.formatTextSegmentBeforeSelectionMarker = exports.formatSegmentWithContentModel = exports.formatParagraphWithContentModel = exports.formatImageWithContentModel = exports.formatTableWithContentModel = exports.clearSelectedCells = exports.insertTableColumn = exports.insertTableRow = exports.insertEntity = exports.toggleCode = exports.setParagraphMargin = exports.adjustImageSelection = exports.setImageAltText = exports.adjustLinkSelection = exports.removeLink = exports.insertLink = exports.clearFormat = exports.getFormatState = exports.changeImage = exports.setImageBoxShadow = exports.setImageBorder = exports.setSpacing = exports.toggleBlockQuote = exports.setHeadingLevel = exports.setDirection = exports.setAlignment = exports.setIndentation = exports.setListStartNumber = exports.setListStyle = exports.insertImage = exports.changeCapitalization = exports.applySegmentFormat = exports.changeFontSize = exports.setTextColor = exports.setFontSize = exports.setFontName = exports.setBackgroundColor = exports.toggleSuperscript = exports.toggleSubscript = exports.toggleStrikethrough = exports.toggleUnderline = exports.toggleItalic = exports.toggleBold = exports.toggleNumbering = exports.toggleBullet = exports.applyTableBorderFormat = exports.editTable = exports.setTableCellShade = exports.formatTable = exports.insertTable = void 0;
2098
+ exports.getListAnnounceData = exports.matchLink = exports.setModelIndentation = exports.findListItemsInSameThread = exports.setModelListStartNumber = exports.setModelListStyle = exports.setListType = void 0;
2099
2099
  var insertTable_1 = __webpack_require__(/*! ./publicApi/table/insertTable */ "./packages/roosterjs-content-model-api/lib/publicApi/table/insertTable.ts");
2100
2100
  Object.defineProperty(exports, "insertTable", ({ enumerable: true, get: function () { return insertTable_1.insertTable; } }));
2101
2101
  var formatTable_1 = __webpack_require__(/*! ./publicApi/table/formatTable */ "./packages/roosterjs-content-model-api/lib/publicApi/table/formatTable.ts");
@@ -2184,6 +2184,8 @@ var insertTableRow_1 = __webpack_require__(/*! ./modelApi/table/insertTableRow *
2184
2184
  Object.defineProperty(exports, "insertTableRow", ({ enumerable: true, get: function () { return insertTableRow_1.insertTableRow; } }));
2185
2185
  var insertTableColumn_1 = __webpack_require__(/*! ./modelApi/table/insertTableColumn */ "./packages/roosterjs-content-model-api/lib/modelApi/table/insertTableColumn.ts");
2186
2186
  Object.defineProperty(exports, "insertTableColumn", ({ enumerable: true, get: function () { return insertTableColumn_1.insertTableColumn; } }));
2187
+ var clearSelectedCells_1 = __webpack_require__(/*! ./modelApi/table/clearSelectedCells */ "./packages/roosterjs-content-model-api/lib/modelApi/table/clearSelectedCells.ts");
2188
+ Object.defineProperty(exports, "clearSelectedCells", ({ enumerable: true, get: function () { return clearSelectedCells_1.clearSelectedCells; } }));
2187
2189
  var formatTableWithContentModel_1 = __webpack_require__(/*! ./publicApi/utils/formatTableWithContentModel */ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatTableWithContentModel.ts");
2188
2190
  Object.defineProperty(exports, "formatTableWithContentModel", ({ enumerable: true, get: function () { return formatTableWithContentModel_1.formatTableWithContentModel; } }));
2189
2191
  var formatImageWithContentModel_1 = __webpack_require__(/*! ./publicApi/utils/formatImageWithContentModel */ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatImageWithContentModel.ts");
@@ -2192,6 +2194,8 @@ var formatParagraphWithContentModel_1 = __webpack_require__(/*! ./publicApi/util
2192
2194
  Object.defineProperty(exports, "formatParagraphWithContentModel", ({ enumerable: true, get: function () { return formatParagraphWithContentModel_1.formatParagraphWithContentModel; } }));
2193
2195
  var formatSegmentWithContentModel_1 = __webpack_require__(/*! ./publicApi/utils/formatSegmentWithContentModel */ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatSegmentWithContentModel.ts");
2194
2196
  Object.defineProperty(exports, "formatSegmentWithContentModel", ({ enumerable: true, get: function () { return formatSegmentWithContentModel_1.formatSegmentWithContentModel; } }));
2197
+ var formatTextSegmentBeforeSelectionMarker_1 = __webpack_require__(/*! ./publicApi/utils/formatTextSegmentBeforeSelectionMarker */ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatTextSegmentBeforeSelectionMarker.ts");
2198
+ Object.defineProperty(exports, "formatTextSegmentBeforeSelectionMarker", ({ enumerable: true, get: function () { return formatTextSegmentBeforeSelectionMarker_1.formatTextSegmentBeforeSelectionMarker; } }));
2195
2199
  var setListType_1 = __webpack_require__(/*! ./modelApi/list/setListType */ "./packages/roosterjs-content-model-api/lib/modelApi/list/setListType.ts");
2196
2200
  Object.defineProperty(exports, "setListType", ({ enumerable: true, get: function () { return setListType_1.setListType; } }));
2197
2201
  var setModelListStyle_1 = __webpack_require__(/*! ./modelApi/list/setModelListStyle */ "./packages/roosterjs-content-model-api/lib/modelApi/list/setModelListStyle.ts");
@@ -2204,6 +2208,8 @@ var setModelIndentation_1 = __webpack_require__(/*! ./modelApi/block/setModelInd
2204
2208
  Object.defineProperty(exports, "setModelIndentation", ({ enumerable: true, get: function () { return setModelIndentation_1.setModelIndentation; } }));
2205
2209
  var matchLink_1 = __webpack_require__(/*! ./modelApi/link/matchLink */ "./packages/roosterjs-content-model-api/lib/modelApi/link/matchLink.ts");
2206
2210
  Object.defineProperty(exports, "matchLink", ({ enumerable: true, get: function () { return matchLink_1.matchLink; } }));
2211
+ var getListAnnounceData_1 = __webpack_require__(/*! ./modelApi/list/getListAnnounceData */ "./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts");
2212
+ Object.defineProperty(exports, "getListAnnounceData", ({ enumerable: true, get: function () { return getListAnnounceData_1.getListAnnounceData; } }));
2207
2213
 
2208
2214
 
2209
2215
  /***/ }),
@@ -2370,7 +2376,9 @@ function setProperty(format, key, value) {
2370
2376
 
2371
2377
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2372
2378
  exports.setModelIndentation = void 0;
2379
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
2373
2380
  var findListItemsInSameThread_1 = __webpack_require__(/*! ../list/findListItemsInSameThread */ "./packages/roosterjs-content-model-api/lib/modelApi/list/findListItemsInSameThread.ts");
2381
+ var getListAnnounceData_1 = __webpack_require__(/*! ../list/getListAnnounceData */ "./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts");
2374
2382
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
2375
2383
  var IndentStepInPixel = 40;
2376
2384
  /**
@@ -2379,7 +2387,7 @@ var IndentStepInPixel = 40;
2379
2387
  * @param length The length of indentation in pixel, default value is 40
2380
2388
  * Set indentation for selected list items or paragraphs
2381
2389
  */
2382
- function setModelIndentation(model, indentation, length) {
2390
+ function setModelIndentation(model, indentation, length, context) {
2383
2391
  if (length === void 0) { length = IndentStepInPixel; }
2384
2392
  var paragraphOrListItem = (0, roosterjs_content_model_dom_1.getOperationalBlocks)(model, ['ListItem'], ['TableCell']);
2385
2393
  var isIndent = indentation == 'indent';
@@ -2426,6 +2434,9 @@ function setModelIndentation(model, indentation, length) {
2426
2434
  else {
2427
2435
  block.levels.pop();
2428
2436
  }
2437
+ if (block.levels.length > 0 && context) {
2438
+ context.announceData = (0, getListAnnounceData_1.getListAnnounceData)((0, tslib_1.__spreadArray)([block], (0, tslib_1.__read)(path), false));
2439
+ }
2429
2440
  }
2430
2441
  }
2431
2442
  else if (block) {
@@ -3126,9 +3137,9 @@ exports.findListItemsInSameThread = void 0;
3126
3137
  * @param currentItem The current list item
3127
3138
  * Search for all list items in the same thread as the current list item
3128
3139
  */
3129
- function findListItemsInSameThread(model, currentItem) {
3140
+ function findListItemsInSameThread(group, currentItem) {
3130
3141
  var items = [];
3131
- findListItems(model, items);
3142
+ findListItems(group, items);
3132
3143
  return filterListItems(items, currentItem);
3133
3144
  }
3134
3145
  exports.findListItemsInSameThread = findListItemsInSameThread;
@@ -3196,7 +3207,9 @@ function filterListItems(items, currentItem) {
3196
3207
  break;
3197
3208
  }
3198
3209
  }
3199
- else if (!isOrderedList || startNumberOverride) {
3210
+ else if (!isOrderedList ||
3211
+ startNumberOverride ||
3212
+ item.levels.length < currentItem.levels.length) {
3200
3213
  break;
3201
3214
  }
3202
3215
  }
@@ -3214,7 +3227,9 @@ function filterListItems(items, currentItem) {
3214
3227
  if (areListTypesCompatible(items, currentIndex, i) && !startNumberOverride) {
3215
3228
  result.push(item);
3216
3229
  }
3217
- else if (!isOrderedList || startNumberOverride) {
3230
+ else if (!isOrderedList ||
3231
+ startNumberOverride ||
3232
+ item.levels.length < currentItem.levels.length) {
3218
3233
  break;
3219
3234
  }
3220
3235
  }
@@ -3234,6 +3249,85 @@ function hasStartNumberOverride(item, levelLength) {
3234
3249
  }
3235
3250
 
3236
3251
 
3252
+ /***/ }),
3253
+
3254
+ /***/ "./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts":
3255
+ /*!***************************************************************************************!*\
3256
+ !*** ./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts ***!
3257
+ \***************************************************************************************/
3258
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
3259
+
3260
+ "use strict";
3261
+
3262
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
3263
+ exports.getListAnnounceData = void 0;
3264
+ var findListItemsInSameThread_1 = __webpack_require__(/*! ./findListItemsInSameThread */ "./packages/roosterjs-content-model-api/lib/modelApi/list/findListItemsInSameThread.ts");
3265
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
3266
+ /**
3267
+ * Get announce data for list item
3268
+ * @param path Content model path that include the list item
3269
+ * @returns Announce data of current list item if any, or null
3270
+ */
3271
+ function getListAnnounceData(path) {
3272
+ var index = (0, roosterjs_content_model_dom_1.getClosestAncestorBlockGroupIndex)(path, ['ListItem'], ['TableCell']);
3273
+ if (index >= 0) {
3274
+ var listItem = path[index];
3275
+ var level = listItem.levels[listItem.levels.length - 1];
3276
+ if (level.format.displayForDummyItem) {
3277
+ return null;
3278
+ }
3279
+ else if (level.listType == 'OL') {
3280
+ var listNumber = getListNumber(path, listItem);
3281
+ var metadata = (0, roosterjs_content_model_dom_1.updateListMetadata)(level);
3282
+ var listStyle = (0, roosterjs_content_model_dom_1.getAutoListStyleType)('OL', metadata !== null && metadata !== void 0 ? metadata : {}, listItem.levels.length - 1, level.format.listStyleType);
3283
+ return listStyle === undefined
3284
+ ? null
3285
+ : {
3286
+ defaultStrings: 'announceListItemNumbering',
3287
+ formatStrings: [(0, roosterjs_content_model_dom_1.getOrderedListNumberStr)(listStyle, listNumber)],
3288
+ };
3289
+ }
3290
+ else {
3291
+ return {
3292
+ defaultStrings: 'announceListItemBullet',
3293
+ };
3294
+ }
3295
+ }
3296
+ else {
3297
+ return null;
3298
+ }
3299
+ }
3300
+ exports.getListAnnounceData = getListAnnounceData;
3301
+ function getListNumber(path, listItem) {
3302
+ var _a, _b;
3303
+ var items = (0, findListItemsInSameThread_1.findListItemsInSameThread)(path[path.length - 1], listItem);
3304
+ var listNumber = 0;
3305
+ for (var i = 0; i < items.length; i++) {
3306
+ var item = items[i];
3307
+ if (listNumber == 0 && item.levels.length == listItem.levels.length) {
3308
+ listNumber = (_b = (_a = item.levels[item.levels.length - 1]) === null || _a === void 0 ? void 0 : _a.format.startNumberOverride) !== null && _b !== void 0 ? _b : 1;
3309
+ }
3310
+ if (item == listItem) {
3311
+ // Found current item, so break and return
3312
+ break;
3313
+ }
3314
+ else if (item.levels.length < listItem.levels.length) {
3315
+ // Found upper level item, reset list number
3316
+ listNumber = 0;
3317
+ }
3318
+ else if (item.levels.length > listItem.levels.length) {
3319
+ // Found deeper level item, skip
3320
+ continue;
3321
+ }
3322
+ else if (!item.levels[item.levels.length - 1].format.displayForDummyItem) {
3323
+ // Save level, and is not dummy, number plus one
3324
+ listNumber++;
3325
+ }
3326
+ }
3327
+ return listNumber;
3328
+ }
3329
+
3330
+
3237
3331
  /***/ }),
3238
3332
 
3239
3333
  /***/ "./packages/roosterjs-content-model-api/lib/modelApi/list/setListType.ts":
@@ -3882,7 +3976,6 @@ exports.clearSelectedCells = void 0;
3882
3976
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
3883
3977
  /**
3884
3978
  * Clear selection of a table.
3885
- * @internal
3886
3979
  * @param table The table model where the selection is to be cleared
3887
3980
  * @param sel The selection coordinates to be cleared
3888
3981
  */
@@ -4989,6 +5082,8 @@ function insertImageWithSrc(editor, src) {
4989
5082
  (0, roosterjs_content_model_dom_1.mergeModel)(model, doc, context, {
4990
5083
  mergeFormat: 'mergeAll',
4991
5084
  });
5085
+ image.isSelected = true;
5086
+ (0, roosterjs_content_model_dom_1.setSelection)(model, image);
4992
5087
  return true;
4993
5088
  }, {
4994
5089
  apiName: 'insertImage',
@@ -6301,6 +6396,7 @@ var alignTableCell_1 = __webpack_require__(/*! ../../modelApi/table/alignTableCe
6301
6396
  */
6302
6397
  function editTable(editor, operation) {
6303
6398
  editor.focus();
6399
+ fixUpSafariSelection(editor);
6304
6400
  (0, formatTableWithContentModel_1.formatTableWithContentModel)(editor, 'editTable', function (tableModel) {
6305
6401
  switch (operation) {
6306
6402
  case 'alignCellLeft':
@@ -6356,6 +6452,22 @@ function editTable(editor, operation) {
6356
6452
  });
6357
6453
  }
6358
6454
  exports.editTable = editTable;
6455
+ // In safari, when open context menu under a table, it may expand the range selection to the beginning of next table cell.
6456
+ // So we make a workaround here to collapse the selection when need, to avoid unexpected table editing behavior
6457
+ // (e.g. insert two columns but actually need one only)
6458
+ function fixUpSafariSelection(editor) {
6459
+ if (editor.getEnvironment().isSafari) {
6460
+ var selection = editor.getDOMSelection();
6461
+ if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'range' && !selection.range.collapsed) {
6462
+ selection.range.collapse(true /*toStart*/);
6463
+ editor.setDOMSelection({
6464
+ type: 'range',
6465
+ range: selection.range,
6466
+ isReverted: false,
6467
+ });
6468
+ }
6469
+ }
6470
+ }
6359
6471
 
6360
6472
 
6361
6473
  /***/ }),
@@ -6737,7 +6849,8 @@ function formatSegmentWithContentModel(editor, apiName, toggleStyleCallback, seg
6737
6849
  segmentAndParagraphs[0][0].segmentType == 'SelectionMarker';
6738
6850
  if (isCollapsedSelection) {
6739
6851
  var para_1 = segmentAndParagraphs[0][1];
6740
- segmentAndParagraphs = (0, adjustWordSelection_1.adjustWordSelection)(model, segmentAndParagraphs[0][0]).map(function (x) { return [x, para_1]; });
6852
+ var path_1 = segmentAndParagraphs[0][2];
6853
+ segmentAndParagraphs = (0, adjustWordSelection_1.adjustWordSelection)(model, segmentAndParagraphs[0][0]).map(function (x) { return [x, para_1, path_1]; });
6741
6854
  if (segmentAndParagraphs.length > 1) {
6742
6855
  isCollapsedSelection = false;
6743
6856
  }
@@ -6822,6 +6935,48 @@ function formatTableWithContentModel(editor, apiName, callback, selectionOverrid
6822
6935
  exports.formatTableWithContentModel = formatTableWithContentModel;
6823
6936
 
6824
6937
 
6938
+ /***/ }),
6939
+
6940
+ /***/ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatTextSegmentBeforeSelectionMarker.ts":
6941
+ /*!************************************************************************************************************!*\
6942
+ !*** ./packages/roosterjs-content-model-api/lib/publicApi/utils/formatTextSegmentBeforeSelectionMarker.ts ***!
6943
+ \************************************************************************************************************/
6944
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
6945
+
6946
+ "use strict";
6947
+
6948
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
6949
+ exports.formatTextSegmentBeforeSelectionMarker = void 0;
6950
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
6951
+ /**
6952
+ * Invoke a callback to format the text segment before the selection marker using Content Model
6953
+ * @param editor The editor object
6954
+ * @param callback The callback to format the text segment.
6955
+ * @returns True if the segment before cursor is found and callback is called, otherwise false
6956
+ */
6957
+ function formatTextSegmentBeforeSelectionMarker(editor, callback, options) {
6958
+ var result = false;
6959
+ editor.formatContentModel(function (model, context) {
6960
+ var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /*includeFormatHolder*/);
6961
+ if (selectedSegmentsAndParagraphs.length > 0 && selectedSegmentsAndParagraphs[0][1]) {
6962
+ var marker = selectedSegmentsAndParagraphs[0][0];
6963
+ var paragraph = selectedSegmentsAndParagraphs[0][1];
6964
+ var markerIndex = paragraph.segments.indexOf(marker);
6965
+ if (marker.segmentType === 'SelectionMarker' && markerIndex > 0) {
6966
+ var previousSegment = paragraph.segments[markerIndex - 1];
6967
+ if (previousSegment && previousSegment.segmentType === 'Text') {
6968
+ result = true;
6969
+ return callback(model, previousSegment, paragraph, marker.format, context);
6970
+ }
6971
+ }
6972
+ }
6973
+ return false;
6974
+ }, options);
6975
+ return result;
6976
+ }
6977
+ exports.formatTextSegmentBeforeSelectionMarker = formatTextSegmentBeforeSelectionMarker;
6978
+
6979
+
6825
6980
  /***/ }),
6826
6981
 
6827
6982
  /***/ "./packages/roosterjs-content-model-core/lib/command/createModelFromHtml/convertInlineCss.ts":
@@ -8086,6 +8241,69 @@ function getPath(node, offset, rootNode) {
8086
8241
  exports.getPath = getPath;
8087
8242
 
8088
8243
 
8244
+ /***/ }),
8245
+
8246
+ /***/ "./packages/roosterjs-content-model-core/lib/coreApi/announce/announce.ts":
8247
+ /*!********************************************************************************!*\
8248
+ !*** ./packages/roosterjs-content-model-core/lib/coreApi/announce/announce.ts ***!
8249
+ \********************************************************************************/
8250
+ /***/ ((__unused_webpack_module, exports) => {
8251
+
8252
+ "use strict";
8253
+
8254
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
8255
+ exports.announce = void 0;
8256
+ /**
8257
+ * @internal
8258
+ * Announce the given data
8259
+ * @param core The EditorCore object
8260
+ * @param announceData Data to announce
8261
+ */
8262
+ var announce = function (core, announceData) {
8263
+ var _a;
8264
+ var text = announceData.text, defaultStrings = announceData.defaultStrings, _b = announceData.formatStrings, formatStrings = _b === void 0 ? [] : _b;
8265
+ var announcerStringGetter = core.lifecycle.announcerStringGetter;
8266
+ var template = defaultStrings && (announcerStringGetter === null || announcerStringGetter === void 0 ? void 0 : announcerStringGetter(defaultStrings));
8267
+ var textToAnnounce = formatString(template || text, formatStrings);
8268
+ if (textToAnnounce) {
8269
+ var announceContainer = core.lifecycle.announceContainer;
8270
+ if (!announceContainer || textToAnnounce == announceContainer.textContent) {
8271
+ (_a = announceContainer === null || announceContainer === void 0 ? void 0 : announceContainer.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(announceContainer);
8272
+ announceContainer = createAriaLiveElement(core.physicalRoot.ownerDocument);
8273
+ core.lifecycle.announceContainer = announceContainer;
8274
+ }
8275
+ if (announceContainer) {
8276
+ announceContainer.textContent = textToAnnounce;
8277
+ }
8278
+ }
8279
+ };
8280
+ exports.announce = announce;
8281
+ function formatString(text, formatStrings) {
8282
+ if (text == undefined) {
8283
+ return text;
8284
+ }
8285
+ text = text.replace(/\{(\d+)\}/g, function (_, sub) {
8286
+ var index = parseInt(sub);
8287
+ var replace = formatStrings[index];
8288
+ return replace !== null && replace !== void 0 ? replace : '';
8289
+ });
8290
+ return text;
8291
+ }
8292
+ function createAriaLiveElement(document) {
8293
+ var div = document.createElement('div');
8294
+ div.style.clip = 'rect(0px, 0px, 0px, 0px)';
8295
+ div.style.clipPath = 'inset(100%)';
8296
+ div.style.height = '1px';
8297
+ div.style.overflow = 'hidden';
8298
+ div.style.position = 'absolute';
8299
+ div.style.whiteSpace = 'nowrap';
8300
+ div.style.width = '1px';
8301
+ div.ariaLive = 'assertive';
8302
+ document.body.appendChild(div);
8303
+ return div;
8304
+ }
8305
+
8306
+
8089
8307
  /***/ }),
8090
8308
 
8091
8309
  /***/ "./packages/roosterjs-content-model-core/lib/coreApi/attachDomEvent/attachDomEvent.ts":
@@ -8145,6 +8363,7 @@ exports.attachDomEvent = attachDomEvent;
8145
8363
  Object.defineProperty(exports, "__esModule", ({ value: true }));
8146
8364
  exports.coreApiMap = void 0;
8147
8365
  var addUndoSnapshot_1 = __webpack_require__(/*! ./addUndoSnapshot/addUndoSnapshot */ "./packages/roosterjs-content-model-core/lib/coreApi/addUndoSnapshot/addUndoSnapshot.ts");
8366
+ var announce_1 = __webpack_require__(/*! ./announce/announce */ "./packages/roosterjs-content-model-core/lib/coreApi/announce/announce.ts");
8148
8367
  var attachDomEvent_1 = __webpack_require__(/*! ./attachDomEvent/attachDomEvent */ "./packages/roosterjs-content-model-core/lib/coreApi/attachDomEvent/attachDomEvent.ts");
8149
8368
  var createContentModel_1 = __webpack_require__(/*! ./createContentModel/createContentModel */ "./packages/roosterjs-content-model-core/lib/coreApi/createContentModel/createContentModel.ts");
8150
8369
  var createEditorContext_1 = __webpack_require__(/*! ./createEditorContext/createEditorContext */ "./packages/roosterjs-content-model-core/lib/coreApi/createEditorContext/createEditorContext.ts");
@@ -8179,6 +8398,7 @@ exports.coreApiMap = {
8179
8398
  switchShadowEdit: switchShadowEdit_1.switchShadowEdit,
8180
8399
  getVisibleViewport: getVisibleViewport_1.getVisibleViewport,
8181
8400
  setEditorStyle: setEditorStyle_1.setEditorStyle,
8401
+ announce: announce_1.announce,
8182
8402
  };
8183
8403
 
8184
8404
 
@@ -8262,17 +8482,12 @@ var createEditorContext = function (core, saveIndex) {
8262
8482
  var lifecycle = core.lifecycle, format = core.format, darkColorHandler = core.darkColorHandler, logicalRoot = core.logicalRoot, cache = core.cache, domHelper = core.domHelper;
8263
8483
  saveIndex = saveIndex && !core.lifecycle.shadowEditFragment;
8264
8484
  var context = (0, tslib_1.__assign)({ isDarkMode: lifecycle.isDarkMode, defaultFormat: format.defaultFormat, pendingFormat: (_a = format.pendingFormat) !== null && _a !== void 0 ? _a : undefined, darkColorHandler: darkColorHandler, addDelimiterForEntity: true, allowCacheElement: true, domIndexer: saveIndex ? cache.domIndexer : undefined, zoomScale: domHelper.calculateZoomScale() }, (0, getRootComputedStyleForContext_1.getRootComputedStyleForContext)(logicalRoot.ownerDocument));
8265
- checkRootRtl(logicalRoot, context);
8485
+ if (core.domHelper.isRightToLeft()) {
8486
+ context.isRootRtl = true;
8487
+ }
8266
8488
  return context;
8267
8489
  };
8268
8490
  exports.createEditorContext = createEditorContext;
8269
- function checkRootRtl(element, context) {
8270
- var _a;
8271
- var style = (_a = element === null || element === void 0 ? void 0 : element.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(element);
8272
- if ((style === null || style === void 0 ? void 0 : style.direction) == 'rtl') {
8273
- context.isRootRtl = true;
8274
- }
8275
- }
8276
8491
 
8277
8492
 
8278
8493
  /***/ }),
@@ -8420,19 +8635,19 @@ var formatContentModel = function (core, formatter, options, domToModelOptions)
8420
8635
  }
8421
8636
  handlePendingFormat(core, context, core.api.getDOMSelection(core));
8422
8637
  }
8638
+ if (context.announceData) {
8639
+ core.api.announce(core, context.announceData);
8640
+ }
8423
8641
  };
8424
8642
  exports.formatContentModel = formatContentModel;
8425
8643
  function handleImages(core, context) {
8426
8644
  if (context.newImages.length > 0) {
8427
- var viewport = core.api.getVisibleViewport(core);
8428
- if (viewport) {
8429
- var left = viewport.left, right = viewport.right;
8430
- var minMaxImageSize = 10;
8431
- var maxWidth_1 = Math.max(right - left, minMaxImageSize);
8432
- context.newImages.forEach(function (image) {
8433
- image.format.maxWidth = maxWidth_1 + "px";
8434
- });
8435
- }
8645
+ var width = core.domHelper.getClientWidth();
8646
+ var minMaxImageSize = 10;
8647
+ var maxWidth_1 = Math.max(width, minMaxImageSize);
8648
+ context.newImages.forEach(function (image) {
8649
+ image.format.maxWidth = maxWidth_1 + "px";
8650
+ });
8436
8651
  }
8437
8652
  }
8438
8653
  function handlePendingFormat(core, context, selection) {
@@ -8652,7 +8867,6 @@ exports.restoreSnapshotColors = restoreSnapshotColors;
8652
8867
  Object.defineProperty(exports, "__esModule", ({ value: true }));
8653
8868
  exports.restoreSnapshotHTML = void 0;
8654
8869
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
8655
- var BlockEntityContainer = '_E_EBlockEntityContainer';
8656
8870
  /**
8657
8871
  * @internal
8658
8872
  */
@@ -8704,22 +8918,19 @@ function tryGetEntityElement(entityMap, node) {
8704
8918
  var format = (0, roosterjs_content_model_dom_1.parseEntityFormat)(node);
8705
8919
  result = getEntityWrapperForReuse(entityMap, format.id);
8706
8920
  }
8707
- else if (isBlockEntityContainer(node)) {
8921
+ else if ((0, roosterjs_content_model_dom_1.isBlockEntityContainer)(node)) {
8708
8922
  result = tryGetEntityFromContainer(node, entityMap);
8709
8923
  }
8710
8924
  }
8711
8925
  return result;
8712
8926
  }
8713
- function isBlockEntityContainer(node) {
8714
- return node.classList.contains(BlockEntityContainer);
8715
- }
8716
8927
  function tryGetEntityFromContainer(element, entityMap) {
8717
8928
  var _a;
8718
8929
  for (var node = element.firstChild; node; node = node.nextSibling) {
8719
8930
  if ((0, roosterjs_content_model_dom_1.isEntityElement)(node) && (0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'ELEMENT_NODE')) {
8720
8931
  var format = (0, roosterjs_content_model_dom_1.parseEntityFormat)(node);
8721
8932
  var parent_1 = (_a = getEntityWrapperForReuse(entityMap, format.id)) === null || _a === void 0 ? void 0 : _a.parentElement;
8722
- return (0, roosterjs_content_model_dom_1.isNodeOfType)(parent_1, 'ELEMENT_NODE') && isBlockEntityContainer(parent_1)
8933
+ return (0, roosterjs_content_model_dom_1.isNodeOfType)(parent_1, 'ELEMENT_NODE') && (0, roosterjs_content_model_dom_1.isBlockEntityContainer)(parent_1)
8723
8934
  ? parent_1
8724
8935
  : null;
8725
8936
  }
@@ -8946,6 +9157,14 @@ function addRangeToSelection(doc, range, isReverted) {
8946
9157
  if (isReverted === void 0) { isReverted = false; }
8947
9158
  var selection = (_a = doc.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
8948
9159
  if (selection) {
9160
+ var currentRange = selection.rangeCount > 0 && selection.getRangeAt(0);
9161
+ if (currentRange &&
9162
+ currentRange.startContainer == range.startContainer &&
9163
+ currentRange.endContainer == range.endContainer &&
9164
+ currentRange.startOffset == range.startOffset &&
9165
+ currentRange.endOffset == range.endOffset) {
9166
+ return;
9167
+ }
8949
9168
  selection.removeAllRanges();
8950
9169
  if (!isReverted) {
8951
9170
  selection.addRange(range);
@@ -9066,11 +9285,14 @@ var findTableCellElement_1 = __webpack_require__(/*! ./findTableCellElement */ "
9066
9285
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
9067
9286
  var DOM_SELECTION_CSS_KEY = '_DOMSelection';
9068
9287
  var HIDE_CURSOR_CSS_KEY = '_DOMSelectionHideCursor';
9288
+ var HIDE_SELECTION_CSS_KEY = '_DOMSelectionHideSelection';
9069
9289
  var IMAGE_ID = 'image';
9070
9290
  var TABLE_ID = 'table';
9071
9291
  var DEFAULT_SELECTION_BORDER_COLOR = '#DB626C';
9072
9292
  var TABLE_CSS_RULE = 'background-color:#C6C6C6!important;';
9073
9293
  var CARET_CSS_RULE = 'caret-color: transparent';
9294
+ var TRANSPARENT_SELECTION_CSS_RULE = 'background-color: transparent !important';
9295
+ var SELECTION_SELECTOR = '*::selection';
9074
9296
  /**
9075
9297
  * @internal
9076
9298
  */
@@ -9083,14 +9305,15 @@ var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
9083
9305
  core.selection.skipReselectOnFocus = true;
9084
9306
  core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, null /*cssRule*/);
9085
9307
  core.api.setEditorStyle(core, HIDE_CURSOR_CSS_KEY, null /*cssRule*/);
9308
+ core.api.setEditorStyle(core, HIDE_SELECTION_CSS_KEY, null /*cssRule*/);
9086
9309
  try {
9087
9310
  switch (selection === null || selection === void 0 ? void 0 : selection.type) {
9088
9311
  case 'image':
9089
9312
  var image = selection.image;
9090
9313
  core.selection.selection = selection;
9091
9314
  core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, "outline-style:auto!important; outline-color:" + (core.selection.imageSelectionBorderColor || DEFAULT_SELECTION_BORDER_COLOR) + "!important;", ["#" + (0, ensureUniqueId_1.ensureUniqueId)(image, IMAGE_ID)]);
9092
- core.api.setEditorStyle(core, HIDE_CURSOR_CSS_KEY, CARET_CSS_RULE);
9093
- setRangeSelection(doc, image);
9315
+ core.api.setEditorStyle(core, HIDE_SELECTION_CSS_KEY, TRANSPARENT_SELECTION_CSS_RULE, [SELECTION_SELECTOR]);
9316
+ setRangeSelection(doc, image, false /* collapse */);
9094
9317
  break;
9095
9318
  case 'table':
9096
9319
  var table = selection.table, firstColumn = selection.firstColumn, firstRow = selection.firstRow, lastColumn = selection.lastColumn, lastRow = selection.lastRow;
@@ -9132,7 +9355,7 @@ var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
9132
9355
  core.api.setEditorStyle(core, HIDE_CURSOR_CSS_KEY, CARET_CSS_RULE);
9133
9356
  var nodeToSelect = ((_c = firstCell.cell) === null || _c === void 0 ? void 0 : _c.firstElementChild) || firstCell.cell;
9134
9357
  if (nodeToSelect) {
9135
- setRangeSelection(doc, nodeToSelect || undefined);
9358
+ setRangeSelection(doc, nodeToSelect || undefined, true /* collapse */);
9136
9359
  }
9137
9360
  break;
9138
9361
  case 'range':
@@ -9198,12 +9421,25 @@ function handleTableSelected(parsedTable, tableId, table, firstCell, lastCell) {
9198
9421
  });
9199
9422
  return selectors;
9200
9423
  }
9201
- function setRangeSelection(doc, element) {
9424
+ function setRangeSelection(doc, element, collapse) {
9425
+ var _a;
9202
9426
  if (element && doc.contains(element)) {
9203
9427
  var range = doc.createRange();
9428
+ var isReverted = undefined;
9204
9429
  range.selectNode(element);
9205
- range.collapse();
9206
- (0, addRangeToSelection_1.addRangeToSelection)(doc, range);
9430
+ if (collapse) {
9431
+ range.collapse();
9432
+ }
9433
+ else {
9434
+ var selection = (_a = doc.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
9435
+ var range_1 = selection && selection.rangeCount > 0 && selection.getRangeAt(0);
9436
+ if (selection && range_1) {
9437
+ isReverted =
9438
+ selection.focusNode != range_1.endContainer ||
9439
+ selection.focusOffset != range_1.endOffset;
9440
+ }
9441
+ }
9442
+ (0, addRangeToSelection_1.addRangeToSelection)(doc, range, isReverted);
9207
9443
  }
9208
9444
  }
9209
9445
 
@@ -9746,11 +9982,15 @@ function reconcileSelection(model, newSelection, oldSelection) {
9746
9982
  var newRange = newSelection.range;
9747
9983
  if (newRange) {
9748
9984
  var startContainer = newRange.startContainer, startOffset = newRange.startOffset, endContainer = newRange.endContainer, endOffset = newRange.endOffset, collapsed = newRange.collapsed;
9985
+ delete model.hasRevertedRangeSelection;
9749
9986
  if (collapsed) {
9750
9987
  return !!reconcileNodeSelection(startContainer, startOffset);
9751
9988
  }
9752
9989
  else if (startContainer == endContainer &&
9753
9990
  (0, roosterjs_content_model_dom_1.isNodeOfType)(startContainer, 'TEXT_NODE')) {
9991
+ if (newSelection.isReverted) {
9992
+ model.hasRevertedRangeSelection = true;
9993
+ }
9754
9994
  return (isIndexedSegment(startContainer) &&
9755
9995
  !!reconcileTextSelection(startContainer, startOffset, endOffset));
9756
9996
  }
@@ -9758,6 +9998,9 @@ function reconcileSelection(model, newSelection, oldSelection) {
9758
9998
  var marker1 = reconcileNodeSelection(startContainer, startOffset);
9759
9999
  var marker2 = reconcileNodeSelection(endContainer, endOffset);
9760
10000
  if (marker1 && marker2) {
10001
+ if (newSelection.isReverted) {
10002
+ model.hasRevertedRangeSelection = true;
10003
+ }
9761
10004
  (0, roosterjs_content_model_dom_1.setSelection)(model, marker1, marker2);
9762
10005
  return true;
9763
10006
  }
@@ -10221,8 +10464,8 @@ var CopyPastePlugin = /** @class */ (function () {
10221
10464
  return;
10222
10465
  }
10223
10466
  cleanUpAndRestoreSelection(tempDiv_1);
10224
- _this.editor.focus();
10225
10467
  _this.editor.setDOMSelection(selection);
10468
+ _this.editor.focus();
10226
10469
  if (isCut) {
10227
10470
  _this.editor.formatContentModel(function (model, context) {
10228
10471
  if ((0, roosterjs_content_model_dom_1.deleteSelection)(model, [deleteEmptyList_1.deleteEmptyList], context)
@@ -10889,6 +11132,123 @@ function createEntityPlugin() {
10889
11132
  exports.createEntityPlugin = createEntityPlugin;
10890
11133
 
10891
11134
 
11135
+ /***/ }),
11136
+
11137
+ /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/entity/adjustSelectionAroundEntity.ts":
11138
+ /*!****************************************************************************************************!*\
11139
+ !*** ./packages/roosterjs-content-model-core/lib/corePlugin/entity/adjustSelectionAroundEntity.ts ***!
11140
+ \****************************************************************************************************/
11141
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
11142
+
11143
+ "use strict";
11144
+
11145
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
11146
+ exports.adjustSelectionAroundEntity = void 0;
11147
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
11148
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
11149
+ /**
11150
+ * @internal
11151
+ */
11152
+ function adjustSelectionAroundEntity(editor, key, shiftKey) {
11153
+ var _a;
11154
+ var selection = editor.isDisposed() ? null : editor.getDOMSelection();
11155
+ if (!selection || selection.type != 'range') {
11156
+ return;
11157
+ }
11158
+ var range = selection.range, isReverted = selection.isReverted;
11159
+ var anchorNode = isReverted ? range.startContainer : range.endContainer;
11160
+ var offset = isReverted ? range.startOffset : range.endOffset;
11161
+ var delimiter = (0, roosterjs_content_model_dom_1.isNodeOfType)(anchorNode, 'ELEMENT_NODE')
11162
+ ? anchorNode
11163
+ : anchorNode.parentElement;
11164
+ var isRtl = delimiter &&
11165
+ ((_a = editor.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(delimiter).direction) == 'rtl';
11166
+ var movingBefore = (key == 'ArrowLeft') != !!isRtl;
11167
+ if (delimiter &&
11168
+ (((0, roosterjs_content_model_dom_1.isEntityDelimiter)(delimiter, !movingBefore) &&
11169
+ ((movingBefore && offset == 0) || (!movingBefore && offset == 1))) ||
11170
+ (0, roosterjs_content_model_dom_1.isBlockEntityContainer)(delimiter))) {
11171
+ editor.formatContentModel(function (model) {
11172
+ var _a, _b;
11173
+ var allSel = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /*includingFormatHolder*/, true /*includingEntity*/);
11174
+ var sel = allSel[isReverted ? 0 : allSel.length - 1];
11175
+ var index = (_b = (_a = sel === null || sel === void 0 ? void 0 : sel[1]) === null || _a === void 0 ? void 0 : _a.segments.indexOf(sel[0])) !== null && _b !== void 0 ? _b : -1;
11176
+ if (sel && sel[1] && index >= 0) {
11177
+ var _c = (0, tslib_1.__read)(sel, 3), segment = _c[0], paragraph = _c[1], path = _c[2];
11178
+ var isShrinking = shiftKey && !range.collapsed && movingBefore != !!isReverted;
11179
+ var entitySegment = isShrinking
11180
+ ? segment
11181
+ : paragraph.segments[movingBefore ? index - 1 : index + 1];
11182
+ var pairedDelimiter = findPairedDelimiter(entitySegment, path, paragraph, movingBefore);
11183
+ if (pairedDelimiter) {
11184
+ var newRange = getNewRange(range, isShrinking, movingBefore, pairedDelimiter, shiftKey);
11185
+ editor.setDOMSelection({
11186
+ type: 'range',
11187
+ range: newRange,
11188
+ isReverted: newRange.collapsed ? false : isReverted,
11189
+ });
11190
+ }
11191
+ }
11192
+ return false;
11193
+ });
11194
+ }
11195
+ }
11196
+ exports.adjustSelectionAroundEntity = adjustSelectionAroundEntity;
11197
+ function getNewRange(originalRange, isShrinking, movingBefore, pairedDelimiter, shiftKey) {
11198
+ var newRange = originalRange.cloneRange();
11199
+ if (isShrinking) {
11200
+ if (movingBefore) {
11201
+ newRange.setEndBefore(pairedDelimiter);
11202
+ }
11203
+ else {
11204
+ newRange.setStartAfter(pairedDelimiter);
11205
+ }
11206
+ }
11207
+ else {
11208
+ if (movingBefore) {
11209
+ newRange.setStartBefore(pairedDelimiter);
11210
+ }
11211
+ else {
11212
+ newRange.setEndAfter(pairedDelimiter);
11213
+ }
11214
+ if (!shiftKey) {
11215
+ if (movingBefore) {
11216
+ newRange.setEndBefore(pairedDelimiter);
11217
+ }
11218
+ else {
11219
+ newRange.setStartAfter(pairedDelimiter);
11220
+ }
11221
+ }
11222
+ }
11223
+ return newRange;
11224
+ }
11225
+ function findPairedDelimiter(entitySegment, path, paragraph, movingBefore) {
11226
+ var entity = null;
11227
+ if ((entitySegment === null || entitySegment === void 0 ? void 0 : entitySegment.segmentType) == 'Entity') {
11228
+ // Inline entity
11229
+ entity = entitySegment;
11230
+ }
11231
+ else {
11232
+ // Block entity
11233
+ var blocks = path[0].blocks;
11234
+ var paraIndex = blocks.indexOf(paragraph);
11235
+ var entityBlock = paraIndex >= 0 ? blocks[movingBefore ? paraIndex - 1 : paraIndex + 1] : null;
11236
+ if ((entityBlock === null || entityBlock === void 0 ? void 0 : entityBlock.blockType) == 'Entity') {
11237
+ entity = entityBlock;
11238
+ }
11239
+ }
11240
+ var pairedDelimiter = entity
11241
+ ? movingBefore
11242
+ ? entity.wrapper.previousElementSibling
11243
+ : entity.wrapper.nextElementSibling
11244
+ : null;
11245
+ return (0, roosterjs_content_model_dom_1.isNodeOfType)(pairedDelimiter, 'ELEMENT_NODE') &&
11246
+ (0, roosterjs_content_model_dom_1.isEntityDelimiter)(pairedDelimiter, movingBefore)
11247
+ ? pairedDelimiter
11248
+ : null;
11249
+ }
11250
+
11251
+
10892
11252
  /***/ }),
10893
11253
 
10894
11254
  /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/entity/entityDelimiterUtils.ts":
@@ -10902,6 +11262,7 @@ exports.createEntityPlugin = createEntityPlugin;
10902
11262
  Object.defineProperty(exports, "__esModule", ({ value: true }));
10903
11263
  exports.handleEnterInlineEntity = exports.handleKeyDownInBlockDelimiter = exports.handleDelimiterKeyDownEvent = exports.handleCompositionEndEvent = exports.handleDelimiterContentChangedEvent = exports.preventTypeInDelimiter = void 0;
10904
11264
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
11265
+ var adjustSelectionAroundEntity_1 = __webpack_require__(/*! ./adjustSelectionAroundEntity */ "./packages/roosterjs-content-model-core/lib/corePlugin/entity/adjustSelectionAroundEntity.ts");
10905
11266
  var normalizePos_1 = __webpack_require__(/*! ../selection/normalizePos */ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/normalizePos.ts");
10906
11267
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
10907
11268
  var DelimiterBefore = 'entityDelimiterBefore';
@@ -10910,8 +11271,6 @@ var DelimiterSelector = '.' + DelimiterAfter + ',.' + DelimiterBefore;
10910
11271
  var ZeroWidthSpace = '\u200B';
10911
11272
  var EntityInfoName = '_Entity';
10912
11273
  var InlineEntitySelector = 'span.' + EntityInfoName;
10913
- var BlockEntityContainer = '_E_EBlockEntityContainer';
10914
- var BlockEntityContainerSelector = '.' + BlockEntityContainer;
10915
11274
  /**
10916
11275
  * @internal exported only for unit test
10917
11276
  */
@@ -11053,61 +11412,86 @@ exports.handleCompositionEndEvent = handleCompositionEndEvent;
11053
11412
  function handleDelimiterKeyDownEvent(editor, event) {
11054
11413
  var _a;
11055
11414
  var selection = editor.getDOMSelection();
11056
- var rawEvent = event.rawEvent;
11057
11415
  if (!selection || selection.type != 'range') {
11058
11416
  return;
11059
11417
  }
11060
- var isEnter = rawEvent.key === 'Enter';
11061
- var helper = editor.getDOMHelper();
11062
- if (selection.range.collapsed && ((0, roosterjs_content_model_dom_1.isCharacterValue)(rawEvent) || isEnter)) {
11063
- var helper_1 = editor.getDOMHelper();
11064
- var node_1 = getFocusedElement(selection);
11065
- if (node_1 && (0, roosterjs_content_model_dom_1.isEntityDelimiter)(node_1) && helper_1.isNodeInEditor(node_1)) {
11066
- var blockEntityContainer = node_1.closest(BlockEntityContainerSelector);
11067
- if (blockEntityContainer && helper_1.isNodeInEditor(blockEntityContainer)) {
11068
- var isAfter = node_1.classList.contains(DelimiterAfter);
11069
- if (isAfter) {
11070
- selection.range.setStartAfter(blockEntityContainer);
11071
- }
11072
- else {
11073
- selection.range.setStartBefore(blockEntityContainer);
11074
- }
11075
- selection.range.collapse(true /* toStart */);
11076
- if (isEnter) {
11077
- event.rawEvent.preventDefault();
11418
+ var rawEvent = event.rawEvent;
11419
+ var range = selection.range;
11420
+ var key = rawEvent.key;
11421
+ switch (key) {
11422
+ case 'Enter':
11423
+ if (range.collapsed) {
11424
+ handleInputOnDelimiter(editor, range, getFocusedElement(selection), rawEvent);
11425
+ }
11426
+ else {
11427
+ var helper = editor.getDOMHelper();
11428
+ var entity = (0, roosterjs_content_model_dom_1.findClosestEntityWrapper)(range.startContainer, helper);
11429
+ if (entity &&
11430
+ (0, roosterjs_content_model_dom_1.isNodeOfType)(entity, 'ELEMENT_NODE') &&
11431
+ helper.isNodeInEditor(entity)) {
11432
+ triggerEntityEventOnEnter(editor, entity, rawEvent);
11078
11433
  }
11079
- editor.formatContentModel(exports.handleKeyDownInBlockDelimiter, {
11080
- selectionOverride: {
11081
- type: 'range',
11082
- isReverted: false,
11083
- range: selection.range,
11084
- },
11434
+ }
11435
+ break;
11436
+ case 'ArrowLeft':
11437
+ case 'ArrowRight':
11438
+ if (!rawEvent.altKey && !rawEvent.ctrlKey && !rawEvent.metaKey) {
11439
+ // Handle in async so focus is already moved, this makes us easier to check if we should adjust the selection
11440
+ (_a = editor.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.requestAnimationFrame(function () {
11441
+ (0, adjustSelectionAroundEntity_1.adjustSelectionAroundEntity)(editor, key, rawEvent.shiftKey);
11085
11442
  });
11086
11443
  }
11444
+ break;
11445
+ default:
11446
+ if ((0, roosterjs_content_model_dom_1.isCharacterValue)(rawEvent) && range.collapsed) {
11447
+ handleInputOnDelimiter(editor, range, getFocusedElement(selection), rawEvent);
11448
+ }
11449
+ break;
11450
+ }
11451
+ }
11452
+ exports.handleDelimiterKeyDownEvent = handleDelimiterKeyDownEvent;
11453
+ function handleInputOnDelimiter(editor, range, focusedNode, rawEvent) {
11454
+ var _a;
11455
+ var helper = editor.getDOMHelper();
11456
+ if (focusedNode && (0, roosterjs_content_model_dom_1.isEntityDelimiter)(focusedNode) && helper.isNodeInEditor(focusedNode)) {
11457
+ var blockEntityContainer = (0, roosterjs_content_model_dom_1.findClosestBlockEntityContainer)(focusedNode, helper);
11458
+ var isEnter = rawEvent.key === 'Enter';
11459
+ if (blockEntityContainer && helper.isNodeInEditor(blockEntityContainer)) {
11460
+ var isAfter = focusedNode.classList.contains(DelimiterAfter);
11461
+ if (isAfter) {
11462
+ range.setStartAfter(blockEntityContainer);
11463
+ }
11087
11464
  else {
11088
- if (isEnter) {
11089
- event.rawEvent.preventDefault();
11090
- editor.formatContentModel(exports.handleEnterInlineEntity);
11091
- }
11092
- else {
11093
- editor.takeSnapshot();
11094
- (_a = editor
11095
- .getDocument()
11096
- .defaultView) === null || _a === void 0 ? void 0 : _a.requestAnimationFrame(function () {
11097
- return preventTypeInDelimiter(node_1, editor);
11098
- });
11099
- }
11465
+ range.setStartBefore(blockEntityContainer);
11466
+ }
11467
+ range.collapse(true /* toStart */);
11468
+ if (isEnter) {
11469
+ rawEvent.preventDefault();
11100
11470
  }
11471
+ editor.formatContentModel(exports.handleKeyDownInBlockDelimiter, {
11472
+ selectionOverride: {
11473
+ type: 'range',
11474
+ isReverted: false,
11475
+ range: range,
11476
+ },
11477
+ });
11101
11478
  }
11102
- }
11103
- else if (isEnter) {
11104
- var entity = (0, roosterjs_content_model_dom_1.findClosestEntityWrapper)(selection.range.startContainer, helper);
11105
- if (entity && (0, roosterjs_content_model_dom_1.isNodeOfType)(entity, 'ELEMENT_NODE') && helper.isNodeInEditor(entity)) {
11106
- triggerEntityEventOnEnter(editor, entity, rawEvent);
11479
+ else {
11480
+ if (isEnter) {
11481
+ rawEvent.preventDefault();
11482
+ editor.formatContentModel(exports.handleEnterInlineEntity);
11483
+ }
11484
+ else {
11485
+ editor.takeSnapshot();
11486
+ (_a = editor
11487
+ .getDocument()
11488
+ .defaultView) === null || _a === void 0 ? void 0 : _a.requestAnimationFrame(function () {
11489
+ return preventTypeInDelimiter(focusedNode, editor);
11490
+ });
11491
+ }
11107
11492
  }
11108
11493
  }
11109
11494
  }
11110
- exports.handleDelimiterKeyDownEvent = handleDelimiterKeyDownEvent;
11111
11495
  /**
11112
11496
  * @internal Exported Only for unit test
11113
11497
  * @returns
@@ -11602,6 +11986,7 @@ var LifecyclePlugin = /** @class */ (function () {
11602
11986
  isDarkMode: !!options.inDarkMode,
11603
11987
  shadowEditFragment: null,
11604
11988
  styleElements: {},
11989
+ announcerStringGetter: options.announcerStringGetter,
11605
11990
  };
11606
11991
  }
11607
11992
  /**
@@ -11629,7 +12014,7 @@ var LifecyclePlugin = /** @class */ (function () {
11629
12014
  */
11630
12015
  LifecyclePlugin.prototype.dispose = function () {
11631
12016
  var _this = this;
11632
- var _a;
12017
+ var _a, _b;
11633
12018
  (_a = this.editor) === null || _a === void 0 ? void 0 : _a.triggerEvent('beforeDispose', {}, true /*broadcast*/);
11634
12019
  (0, roosterjs_content_model_dom_1.getObjectKeys)(this.state.styleElements).forEach(function (key) {
11635
12020
  var _a;
@@ -11637,6 +12022,11 @@ var LifecyclePlugin = /** @class */ (function () {
11637
12022
  (_a = element.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(element);
11638
12023
  delete _this.state.styleElements[key];
11639
12024
  });
12025
+ var announceContainer = this.state.announceContainer;
12026
+ if (announceContainer) {
12027
+ (_b = announceContainer.parentElement) === null || _b === void 0 ? void 0 : _b.removeChild(announceContainer);
12028
+ delete this.state.announceContainer;
12029
+ }
11640
12030
  if (this.disposer) {
11641
12031
  this.disposer();
11642
12032
  this.disposer = null;
@@ -11697,6 +12087,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
11697
12087
  exports.createSelectionPlugin = void 0;
11698
12088
  var findCoordinate_1 = __webpack_require__(/*! ./findCoordinate */ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/findCoordinate.ts");
11699
12089
  var findTableCellElement_1 = __webpack_require__(/*! ../../coreApi/setDOMSelection/findTableCellElement */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/findTableCellElement.ts");
12090
+ var isSingleImageInSelection_1 = __webpack_require__(/*! ./isSingleImageInSelection */ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/isSingleImageInSelection.ts");
11700
12091
  var normalizePos_1 = __webpack_require__(/*! ./normalizePos */ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/normalizePos.ts");
11701
12092
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
11702
12093
  var MouseLeftButton = 0;
@@ -11706,6 +12097,7 @@ var Up = 'ArrowUp';
11706
12097
  var Down = 'ArrowDown';
11707
12098
  var Left = 'ArrowLeft';
11708
12099
  var Right = 'ArrowRight';
12100
+ var Tab = 'Tab';
11709
12101
  var SelectionPlugin = /** @class */ (function () {
11710
12102
  function SelectionPlugin(options) {
11711
12103
  var _this = this;
@@ -11713,6 +12105,7 @@ var SelectionPlugin = /** @class */ (function () {
11713
12105
  this.disposer = null;
11714
12106
  this.isSafari = false;
11715
12107
  this.isMac = false;
12108
+ this.scrollTopCache = 0;
11716
12109
  this.onMouseMove = function (event) {
11717
12110
  var _a, _b, _c;
11718
12111
  if (_this.editor && _this.state.tableSelection) {
@@ -11783,20 +12176,45 @@ var SelectionPlugin = /** @class */ (function () {
11783
12176
  // Editor is focused, now we can get live selection. So no need to keep a selection if the selection type is range.
11784
12177
  _this.state.selection = null;
11785
12178
  }
12179
+ if (_this.scrollTopCache && _this.editor) {
12180
+ var sc = _this.editor.getScrollContainer();
12181
+ sc.scrollTop = _this.scrollTopCache;
12182
+ _this.scrollTopCache = 0;
12183
+ }
11786
12184
  };
11787
12185
  this.onBlur = function () {
11788
- if (!_this.state.selection && _this.editor) {
11789
- _this.state.selection = _this.editor.getDOMSelection();
12186
+ if (_this.editor) {
12187
+ if (!_this.state.selection) {
12188
+ _this.state.selection = _this.editor.getDOMSelection();
12189
+ }
12190
+ var sc = _this.editor.getScrollContainer();
12191
+ _this.scrollTopCache = sc.scrollTop;
11790
12192
  }
11791
12193
  };
11792
- this.onSelectionChangeSafari = function () {
12194
+ this.onSelectionChange = function () {
11793
12195
  var _a;
11794
12196
  if (((_a = _this.editor) === null || _a === void 0 ? void 0 : _a.hasFocus()) && !_this.editor.isInShadowEdit()) {
12197
+ var newSelection = _this.editor.getDOMSelection();
12198
+ //If am image selection changed to a wider range due a keyboard event, we should update the selection
12199
+ var selection = _this.editor.getDocument().getSelection();
12200
+ if ((newSelection === null || newSelection === void 0 ? void 0 : newSelection.type) == 'image' && selection) {
12201
+ if (selection && !(0, isSingleImageInSelection_1.isSingleImageInSelection)(selection)) {
12202
+ var range = selection.getRangeAt(0);
12203
+ _this.editor.setDOMSelection({
12204
+ type: 'range',
12205
+ range: range,
12206
+ isReverted: selection.focusNode != range.endContainer ||
12207
+ selection.focusOffset != range.endOffset,
12208
+ });
12209
+ }
12210
+ }
11795
12211
  // Safari has problem to handle onBlur event. When blur, we cannot get the original selection from editor.
11796
12212
  // So we always save a selection whenever editor has focus. Then after blur, we can still use this cached selection.
11797
- var newSelection = _this.editor.getDOMSelection();
11798
12213
  if ((newSelection === null || newSelection === void 0 ? void 0 : newSelection.type) == 'range') {
11799
- _this.state.selection = newSelection;
12214
+ if (_this.isSafari) {
12215
+ _this.state.selection = newSelection;
12216
+ }
12217
+ _this.trySelectSingleImage(newSelection);
11800
12218
  }
11801
12219
  }
11802
12220
  };
@@ -11815,8 +12233,8 @@ var SelectionPlugin = /** @class */ (function () {
11815
12233
  var document = this.editor.getDocument();
11816
12234
  this.isSafari = !!env.isSafari;
11817
12235
  this.isMac = !!env.isMac;
12236
+ document.addEventListener('selectionchange', this.onSelectionChange);
11818
12237
  if (this.isSafari) {
11819
- document.addEventListener('selectionchange', this.onSelectionChangeSafari);
11820
12238
  this.disposer = this.editor.attachDomEvent({
11821
12239
  focus: { beforeDispatch: this.onFocus },
11822
12240
  drop: { beforeDispatch: this.onDrop },
@@ -11832,7 +12250,7 @@ var SelectionPlugin = /** @class */ (function () {
11832
12250
  };
11833
12251
  SelectionPlugin.prototype.dispose = function () {
11834
12252
  var _a;
11835
- (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDocument().removeEventListener('selectionchange', this.onSelectionChangeSafari);
12253
+ (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDocument().removeEventListener('selectionchange', this.onSelectionChange);
11836
12254
  if (this.disposer) {
11837
12255
  this.disposer();
11838
12256
  this.disposer = null;
@@ -11860,6 +12278,11 @@ var SelectionPlugin = /** @class */ (function () {
11860
12278
  case 'contentChanged':
11861
12279
  this.state.tableSelection = null;
11862
12280
  break;
12281
+ case 'scroll':
12282
+ if (!this.editor.hasFocus()) {
12283
+ this.scrollTopCache = event.scrollContainer.scrollTop;
12284
+ }
12285
+ break;
11863
12286
  }
11864
12287
  };
11865
12288
  SelectionPlugin.prototype.onMouseDown = function (editor, rawEvent) {
@@ -11871,11 +12294,11 @@ var SelectionPlugin = /** @class */ (function () {
11871
12294
  (image =
11872
12295
  (_a = this.getClickingImage(rawEvent)) !== null && _a !== void 0 ? _a : this.getContainedTargetImage(rawEvent, selection)) &&
11873
12296
  image.isContentEditable) {
11874
- this.selectImage(image);
12297
+ this.selectImageWithRange(image, rawEvent);
11875
12298
  return;
11876
12299
  }
11877
12300
  else if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'image' && selection.image !== rawEvent.target) {
11878
- this.selectBeforeImage(editor, selection.image);
12301
+ this.selectBeforeOrAfterElement(editor, selection.image);
11879
12302
  return;
11880
12303
  }
11881
12304
  // Table selection
@@ -11904,6 +12327,22 @@ var SelectionPlugin = /** @class */ (function () {
11904
12327
  });
11905
12328
  }
11906
12329
  };
12330
+ SelectionPlugin.prototype.selectImageWithRange = function (image, event) {
12331
+ var _a;
12332
+ var range = image.ownerDocument.createRange();
12333
+ range.selectNode(image);
12334
+ var domSelection = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDOMSelection();
12335
+ if ((domSelection === null || domSelection === void 0 ? void 0 : domSelection.type) == 'image' && image == domSelection.image) {
12336
+ event.preventDefault();
12337
+ }
12338
+ else {
12339
+ this.setDOMSelection({
12340
+ type: 'range',
12341
+ isReverted: false,
12342
+ range: range,
12343
+ }, null);
12344
+ }
12345
+ };
11907
12346
  SelectionPlugin.prototype.onMouseUp = function (event) {
11908
12347
  var image;
11909
12348
  if ((image = this.getClickingImage(event.rawEvent)) &&
@@ -11912,7 +12351,7 @@ var SelectionPlugin = /** @class */ (function () {
11912
12351
  (event.rawEvent.button ==
11913
12352
  MouseRightButton /* it's not possible to drag using right click */ ||
11914
12353
  event.isClicking)) {
11915
- this.selectImage(image);
12354
+ this.selectImageWithRange(image, event.rawEvent);
11916
12355
  }
11917
12356
  this.detachMouseEvent();
11918
12357
  };
@@ -11926,20 +12365,21 @@ var SelectionPlugin = /** @class */ (function () {
11926
12365
  case 'image':
11927
12366
  if (!(0, roosterjs_content_model_dom_1.isModifierKey)(rawEvent) && !rawEvent.shiftKey && selection.image.parentNode) {
11928
12367
  if (key === 'Escape') {
11929
- this.selectBeforeImage(editor, selection.image);
12368
+ this.selectBeforeOrAfterElement(editor, selection.image);
11930
12369
  rawEvent.stopPropagation();
11931
12370
  }
11932
12371
  else if (key !== 'Delete' && key !== 'Backspace') {
11933
- this.selectBeforeImage(editor, selection.image);
12372
+ this.selectBeforeOrAfterElement(editor, selection.image);
11934
12373
  }
11935
12374
  }
11936
12375
  break;
11937
12376
  case 'range':
11938
- if (key == Up || key == Down || key == Left || key == Right) {
12377
+ if (key == Up || key == Down || key == Left || key == Right || key == Tab) {
11939
12378
  var start = selection.range.startContainer;
11940
12379
  this.state.tableSelection = this.parseTableSelection(start, start, editor.getDOMHelper());
12380
+ var rangeKey_1 = key == Tab ? this.getTabKey(rawEvent) : key;
11941
12381
  if (this.state.tableSelection) {
11942
- win === null || win === void 0 ? void 0 : win.requestAnimationFrame(function () { return _this.handleSelectionInTable(key); });
12382
+ win === null || win === void 0 ? void 0 : win.requestAnimationFrame(function () { return _this.handleSelectionInTable(rangeKey_1); });
11943
12383
  }
11944
12384
  }
11945
12385
  break;
@@ -11966,15 +12406,18 @@ var SelectionPlugin = /** @class */ (function () {
11966
12406
  break;
11967
12407
  }
11968
12408
  };
12409
+ SelectionPlugin.prototype.getTabKey = function (rawEvent) {
12410
+ return rawEvent.shiftKey ? 'TabLeft' : 'TabRight';
12411
+ };
11969
12412
  SelectionPlugin.prototype.handleSelectionInTable = function (key) {
11970
- var _a, _b;
12413
+ var _a, _b, _c, _d, _e, _f;
11971
12414
  if (!this.editor || !this.state.tableSelection) {
11972
12415
  return;
11973
12416
  }
11974
12417
  var selection = this.editor.getDOMSelection();
11975
12418
  var domHelper = this.editor.getDOMHelper();
11976
12419
  if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'range') {
11977
- var _c = selection.range, collapsed = _c.collapsed, startContainer = _c.startContainer, endContainer = _c.endContainer, commonAncestorContainer = _c.commonAncestorContainer, isReverted = selection.isReverted;
12420
+ var _g = selection.range, collapsed = _g.collapsed, startContainer = _g.startContainer, endContainer = _g.endContainer, commonAncestorContainer = _g.commonAncestorContainer, isReverted = selection.isReverted;
11978
12421
  var start = isReverted ? endContainer : startContainer;
11979
12422
  var end = isReverted ? startContainer : endContainer;
11980
12423
  var tableSel = this.parseTableSelection(commonAncestorContainer, start, domHelper);
@@ -11982,9 +12425,9 @@ var SelectionPlugin = /** @class */ (function () {
11982
12425
  return;
11983
12426
  }
11984
12427
  var lastCo = (0, findCoordinate_1.findCoordinate)(tableSel === null || tableSel === void 0 ? void 0 : tableSel.parsedTable, end, domHelper);
11985
- var _d = this.state.tableSelection, parsedTable = _d.parsedTable, oldCo = _d.firstCo, table = _d.table;
11986
- if (lastCo && tableSel.table == table && lastCo.col != oldCo.col) {
11987
- if (key == Up || key == Down) {
12428
+ var _h = this.state.tableSelection, parsedTable = _h.parsedTable, oldCo = _h.firstCo, table = _h.table;
12429
+ if (lastCo && tableSel.table == table) {
12430
+ if (lastCo.col != oldCo.col && (key == Up || key == Down)) {
11988
12431
  var change = key == Up ? -1 : 1;
11989
12432
  var originalTd = (_a = (0, findTableCellElement_1.findTableCellElement)(parsedTable, oldCo)) === null || _a === void 0 ? void 0 : _a.cell;
11990
12433
  var td = null;
@@ -11999,20 +12442,43 @@ var SelectionPlugin = /** @class */ (function () {
11999
12442
  }
12000
12443
  }
12001
12444
  if (collapsed && td) {
12002
- var _e = (0, normalizePos_1.normalizePos)(td, key == Up ? td.childNodes.length : 0), node = _e.node, offset = _e.offset;
12003
- var range = this.editor.getDocument().createRange();
12004
- range.setStart(node, offset);
12005
- range.collapse(true /*toStart*/);
12006
- this.setDOMSelection({
12007
- type: 'range',
12008
- range: range,
12009
- isReverted: false,
12010
- }, null /*tableSelection*/);
12445
+ this.setRangeSelectionInTable(td, key == Up ? td.childNodes.length : 0, this.editor);
12446
+ }
12447
+ }
12448
+ else if (key == 'TabLeft' || key == 'TabRight') {
12449
+ var reverse = key == 'TabLeft';
12450
+ for (var step = reverse ? -1 : 1, row = (_c = lastCo.row) !== null && _c !== void 0 ? _c : 0, col = ((_d = lastCo.col) !== null && _d !== void 0 ? _d : 0) + step;; col += step) {
12451
+ if (col < 0 || col >= parsedTable[row].length) {
12452
+ row += step;
12453
+ if (row < 0) {
12454
+ this.selectBeforeOrAfterElement(this.editor, tableSel.table);
12455
+ break;
12456
+ }
12457
+ else if (row >= parsedTable.length) {
12458
+ this.selectBeforeOrAfterElement(this.editor, tableSel.table, true /*after*/);
12459
+ break;
12460
+ }
12461
+ col = reverse ? parsedTable[row].length - 1 : 0;
12462
+ }
12463
+ var cell = parsedTable[row][col];
12464
+ if (typeof cell != 'string') {
12465
+ this.setRangeSelectionInTable(cell, 0, this.editor);
12466
+ lastCo.row = row;
12467
+ lastCo.col = col;
12468
+ break;
12469
+ }
12011
12470
  }
12012
12471
  }
12013
12472
  else {
12014
12473
  this.state.tableSelection = null;
12015
12474
  }
12475
+ if (collapsed &&
12476
+ (lastCo.col != oldCo.col || lastCo.row != oldCo.row) &&
12477
+ lastCo.row >= 0 &&
12478
+ lastCo.row == parsedTable.length - 1 &&
12479
+ lastCo.col == ((_e = parsedTable[lastCo.row]) === null || _e === void 0 ? void 0 : _e.length) - 1) {
12480
+ (_f = this.editor) === null || _f === void 0 ? void 0 : _f.announce({ defaultStrings: 'announceOnFocusLastCell' });
12481
+ }
12016
12482
  }
12017
12483
  if (!collapsed && lastCo) {
12018
12484
  this.state.tableSelection = tableSel;
@@ -12020,9 +12486,21 @@ var SelectionPlugin = /** @class */ (function () {
12020
12486
  }
12021
12487
  }
12022
12488
  };
12023
- SelectionPlugin.prototype.updateTableSelectionFromKeyboard = function (rowChange, colChange) {
12024
- var _a;
12025
- if (((_a = this.state.tableSelection) === null || _a === void 0 ? void 0 : _a.lastCo) && this.editor) {
12489
+ SelectionPlugin.prototype.setRangeSelectionInTable = function (cell, nodeOffset, editor) {
12490
+ // Get deepest editable position in the cell
12491
+ var _a = (0, normalizePos_1.normalizePos)(cell, nodeOffset), node = _a.node, offset = _a.offset;
12492
+ var range = editor.getDocument().createRange();
12493
+ range.setStart(node, offset);
12494
+ range.collapse(true /*toStart*/);
12495
+ this.setDOMSelection({
12496
+ type: 'range',
12497
+ range: range,
12498
+ isReverted: false,
12499
+ }, null /*tableSelection*/);
12500
+ };
12501
+ SelectionPlugin.prototype.updateTableSelectionFromKeyboard = function (rowChange, colChange) {
12502
+ var _a;
12503
+ if (((_a = this.state.tableSelection) === null || _a === void 0 ? void 0 : _a.lastCo) && this.editor) {
12026
12504
  var _b = this.state.tableSelection, lastCo = _b.lastCo, parsedTable = _b.parsedTable;
12027
12505
  var row = lastCo.row + rowChange;
12028
12506
  var col = lastCo.col + colChange;
@@ -12031,19 +12509,13 @@ var SelectionPlugin = /** @class */ (function () {
12031
12509
  }
12032
12510
  }
12033
12511
  };
12034
- SelectionPlugin.prototype.selectImage = function (image) {
12035
- this.setDOMSelection({
12036
- type: 'image',
12037
- image: image,
12038
- }, null /*tableSelection*/);
12039
- };
12040
- SelectionPlugin.prototype.selectBeforeImage = function (editor, image) {
12512
+ SelectionPlugin.prototype.selectBeforeOrAfterElement = function (editor, element, after) {
12041
12513
  var doc = editor.getDocument();
12042
- var parent = image.parentNode;
12043
- var index = parent && (0, roosterjs_content_model_dom_1.toArray)(parent.childNodes).indexOf(image);
12514
+ var parent = element.parentNode;
12515
+ var index = parent && (0, roosterjs_content_model_dom_1.toArray)(parent.childNodes).indexOf(element);
12044
12516
  if (parent && index !== null && index >= 0) {
12045
12517
  var range = doc.createRange();
12046
- range.setStart(parent, index);
12518
+ range.setStart(parent, index + (after ? 1 : 0));
12047
12519
  range.collapse();
12048
12520
  this.setDOMSelection({
12049
12521
  type: 'range',
@@ -12100,6 +12572,17 @@ var SelectionPlugin = /** @class */ (function () {
12100
12572
  this.state.mouseDisposer = undefined;
12101
12573
  }
12102
12574
  };
12575
+ SelectionPlugin.prototype.trySelectSingleImage = function (selection) {
12576
+ if (!selection.range.collapsed) {
12577
+ var image = (0, isSingleImageInSelection_1.isSingleImageInSelection)(selection.range);
12578
+ if (image) {
12579
+ this.setDOMSelection({
12580
+ type: 'image',
12581
+ image: image,
12582
+ }, null /*tableSelection*/);
12583
+ }
12584
+ }
12585
+ };
12103
12586
  return SelectionPlugin;
12104
12587
  }());
12105
12588
  /**
@@ -12152,6 +12635,58 @@ function findCoordinate(parsedTable, element, domHelper) {
12152
12635
  exports.findCoordinate = findCoordinate;
12153
12636
 
12154
12637
 
12638
+ /***/ }),
12639
+
12640
+ /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/isSingleImageInSelection.ts":
12641
+ /*!****************************************************************************************************!*\
12642
+ !*** ./packages/roosterjs-content-model-core/lib/corePlugin/selection/isSingleImageInSelection.ts ***!
12643
+ \****************************************************************************************************/
12644
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
12645
+
12646
+ "use strict";
12647
+
12648
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
12649
+ exports.isSingleImageInSelection = void 0;
12650
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
12651
+ /**
12652
+ * @internal
12653
+ */
12654
+ function isSingleImageInSelection(selection) {
12655
+ var _a = getProps(selection), startNode = _a.startNode, endNode = _a.endNode, startOffset = _a.startOffset, endOffset = _a.endOffset;
12656
+ var max = Math.max(startOffset, endOffset);
12657
+ var min = Math.min(startOffset, endOffset);
12658
+ if (startNode && endNode && startNode == endNode && max - min == 1) {
12659
+ var node = startNode === null || startNode === void 0 ? void 0 : startNode.childNodes.item(min);
12660
+ if ((0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'ELEMENT_NODE') && (0, roosterjs_content_model_dom_1.isElementOfType)(node, 'img')) {
12661
+ return node;
12662
+ }
12663
+ }
12664
+ return null;
12665
+ }
12666
+ exports.isSingleImageInSelection = isSingleImageInSelection;
12667
+ function getProps(selection) {
12668
+ if (isSelection(selection)) {
12669
+ return {
12670
+ startNode: selection.anchorNode,
12671
+ endNode: selection.focusNode,
12672
+ startOffset: selection.anchorOffset,
12673
+ endOffset: selection.focusOffset,
12674
+ };
12675
+ }
12676
+ else {
12677
+ return {
12678
+ startNode: selection.startContainer,
12679
+ endNode: selection.endContainer,
12680
+ startOffset: selection.startOffset,
12681
+ endOffset: selection.endOffset,
12682
+ };
12683
+ }
12684
+ }
12685
+ function isSelection(selection) {
12686
+ return !!selection.getRangeAt;
12687
+ }
12688
+
12689
+
12155
12690
  /***/ }),
12156
12691
 
12157
12692
  /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/normalizePos.ts":
@@ -12165,6 +12700,30 @@ exports.findCoordinate = findCoordinate;
12165
12700
  Object.defineProperty(exports, "__esModule", ({ value: true }));
12166
12701
  exports.normalizePos = void 0;
12167
12702
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
12703
+ /**
12704
+ * HTML void elements
12705
+ * Per https://www.w3.org/TR/html/syntax.html#syntax-elements, cannot have child nodes
12706
+ * This regex is used when we move focus to very begin of editor. We should avoid putting focus inside
12707
+ * void elements so users don't accidentally create child nodes in them
12708
+ */
12709
+ var HTML_VOID_ELEMENTS = [
12710
+ 'AREA',
12711
+ 'BASE',
12712
+ 'BR',
12713
+ 'COL',
12714
+ 'COMMAND',
12715
+ 'EMBED',
12716
+ 'HR',
12717
+ 'IMG',
12718
+ 'INPUT',
12719
+ 'KEYGEN',
12720
+ 'LINK',
12721
+ 'META',
12722
+ 'PARAM',
12723
+ 'SOURCE',
12724
+ 'TRACK',
12725
+ 'WBR',
12726
+ ];
12168
12727
  /**
12169
12728
  * @internal
12170
12729
  */
@@ -12182,8 +12741,15 @@ function normalizePos(node, offset) {
12182
12741
  : node.childNodes.length;
12183
12742
  }
12184
12743
  else {
12185
- node = node.childNodes[offset];
12186
- offset = 0;
12744
+ var nextNode = node.childNodes[offset];
12745
+ if ((0, roosterjs_content_model_dom_1.isNodeOfType)(nextNode, 'ELEMENT_NODE') &&
12746
+ HTML_VOID_ELEMENTS.indexOf(nextNode.tagName) >= 0) {
12747
+ break;
12748
+ }
12749
+ else {
12750
+ node = node.childNodes[offset];
12751
+ offset = 0;
12752
+ }
12187
12753
  }
12188
12754
  }
12189
12755
  return { node: node, offset: offset };
@@ -12865,6 +13431,14 @@ var Editor = /** @class */ (function () {
12865
13431
  var core = this.getCore();
12866
13432
  core.api.setEditorStyle(core, key, cssRule, subSelectors);
12867
13433
  };
13434
+ /**
13435
+ * Announce the given data
13436
+ * @param announceData Data to announce
13437
+ */
13438
+ Editor.prototype.announce = function (announceData) {
13439
+ var core = this.getCore();
13440
+ core.api.announce(core, announceData);
13441
+ };
12868
13442
  /**
12869
13443
  * @returns the current EditorCore object
12870
13444
  * @throws a standard Error if there's no core object
@@ -12945,6 +13519,26 @@ var DOMHelperImpl = /** @class */ (function () {
12945
13519
  var activeElement = this.contentDiv.ownerDocument.activeElement;
12946
13520
  return !!(activeElement && this.contentDiv.contains(activeElement));
12947
13521
  };
13522
+ /**
13523
+ * Check if the root element is in RTL mode
13524
+ */
13525
+ DOMHelperImpl.prototype.isRightToLeft = function () {
13526
+ var _a;
13527
+ var contentDiv = this.contentDiv;
13528
+ var style = (_a = contentDiv.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(contentDiv);
13529
+ return (style === null || style === void 0 ? void 0 : style.direction) == 'rtl';
13530
+ };
13531
+ /**
13532
+ * Get the width of the editable area of the editor content div
13533
+ */
13534
+ DOMHelperImpl.prototype.getClientWidth = function () {
13535
+ var _a;
13536
+ var contentDiv = this.contentDiv;
13537
+ var style = (_a = contentDiv.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(contentDiv);
13538
+ var paddingLeft = (0, roosterjs_content_model_dom_1.parseValueWithUnit)(style === null || style === void 0 ? void 0 : style.paddingLeft);
13539
+ var paddingRight = (0, roosterjs_content_model_dom_1.parseValueWithUnit)(style === null || style === void 0 ? void 0 : style.paddingRight);
13540
+ return this.contentDiv.clientWidth - (paddingLeft + paddingRight);
13541
+ };
12948
13542
  return DOMHelperImpl;
12949
13543
  }());
12950
13544
  /**
@@ -13235,95 +13829,24 @@ exports.containerSizeFormatParser = containerSizeFormatParser;
13235
13829
 
13236
13830
  Object.defineProperty(exports, "__esModule", ({ value: true }));
13237
13831
  exports.listLevelMetadataApplier = exports.listItemMetadataApplier = void 0;
13238
- var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
13239
13832
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
13240
- var DefaultOrderedListStyles = ['decimal', 'lower-alpha', 'lower-roman'];
13241
- var DefaultUnorderedListStyles = ['disc', 'circle', 'square'];
13242
13833
  var OrderedMapPlaceholderRegex = /\$\{(\w+)\}/;
13243
- var CharCodeOfA = 65;
13244
- var RomanValues = {
13245
- M: 1000,
13246
- CM: 900,
13247
- D: 500,
13248
- CD: 400,
13249
- C: 100,
13250
- XC: 90,
13251
- L: 50,
13252
- XL: 40,
13253
- X: 10,
13254
- IX: 9,
13255
- V: 5,
13256
- IV: 4,
13257
- I: 1,
13258
- };
13259
- function getOrderedListStyleValue(template, listNumber) {
13260
- return template
13261
- ? template.replace(OrderedMapPlaceholderRegex, function (_, subStr) {
13262
- switch (subStr) {
13263
- case 'Number':
13264
- return listNumber + '';
13265
- case 'LowerAlpha':
13266
- return convertDecimalsToAlpha(listNumber, true /*isLowerCase*/);
13267
- case 'UpperAlpha':
13268
- return convertDecimalsToAlpha(listNumber, false /*isLowerCase*/);
13269
- case 'LowerRoman':
13270
- return convertDecimalsToRoman(listNumber, true /*isLowerCase*/);
13271
- case 'UpperRoman':
13272
- return convertDecimalsToRoman(listNumber, false /*isLowerCase*/);
13273
- }
13274
- return '';
13275
- })
13276
- : undefined;
13277
- }
13278
- function convertDecimalsToAlpha(decimal, isLowerCase) {
13279
- var alpha = '';
13280
- decimal--;
13281
- while (decimal >= 0) {
13282
- alpha = String.fromCharCode((decimal % 26) + CharCodeOfA) + alpha;
13283
- decimal = Math.floor(decimal / 26) - 1;
13284
- }
13285
- return isLowerCase ? alpha.toLowerCase() : alpha;
13286
- }
13287
- function convertDecimalsToRoman(decimal, isLowerCase) {
13288
- var e_1, _a;
13289
- var romanValue = '';
13290
- try {
13291
- for (var _b = (0, tslib_1.__values)((0, roosterjs_content_model_dom_1.getObjectKeys)(RomanValues)), _c = _b.next(); !_c.done; _c = _b.next()) {
13292
- var i = _c.value;
13293
- var timesRomanCharAppear = Math.floor(decimal / RomanValues[i]);
13294
- decimal = decimal - timesRomanCharAppear * RomanValues[i];
13295
- romanValue = romanValue + i.repeat(timesRomanCharAppear);
13296
- }
13297
- }
13298
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
13299
- finally {
13300
- try {
13301
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
13302
- }
13303
- finally { if (e_1) throw e_1.error; }
13304
- }
13305
- return isLowerCase ? romanValue.toLocaleLowerCase() : romanValue;
13306
- }
13307
- function shouldApplyToItem(listStyleType) {
13308
- return listStyleType.indexOf('"') >= 0;
13309
- }
13310
- function getRawListStyleType(listType, metadata, depth) {
13311
- var orderedStyleType = metadata.orderedStyleType, unorderedStyleType = metadata.unorderedStyleType, applyListStyleFromLevel = metadata.applyListStyleFromLevel;
13834
+ function getListStyleValue(listType, listStyleType, listNumber) {
13312
13835
  if (listType == 'OL') {
13313
- return typeof orderedStyleType == 'number'
13314
- ? roosterjs_content_model_dom_1.OrderedListStyleMap[orderedStyleType]
13315
- : applyListStyleFromLevel
13316
- ? DefaultOrderedListStyles[depth % DefaultOrderedListStyles.length]
13317
- : undefined;
13836
+ var numberStr = (0, roosterjs_content_model_dom_1.getOrderedListNumberStr)(listStyleType, listNumber !== null && listNumber !== void 0 ? listNumber : 1);
13837
+ var template = roosterjs_content_model_dom_1.OrderedListStyleMap[listStyleType];
13838
+ return template ? template.replace(OrderedMapPlaceholderRegex, numberStr) : undefined;
13318
13839
  }
13319
13840
  else {
13320
- return typeof unorderedStyleType == 'number'
13321
- ? roosterjs_content_model_dom_1.UnorderedListStyleMap[unorderedStyleType]
13322
- : applyListStyleFromLevel
13323
- ? DefaultUnorderedListStyles[depth % DefaultUnorderedListStyles.length]
13324
- : undefined;
13841
+ return roosterjs_content_model_dom_1.UnorderedListStyleMap[listStyleType];
13325
13842
  }
13326
13843
  }
13844
+ function shouldApplyToItem(listStyleType, listType) {
13845
+ var style = listType == 'OL'
13846
+ ? roosterjs_content_model_dom_1.OrderedListStyleMap[listStyleType]
13847
+ : roosterjs_content_model_dom_1.UnorderedListStyleMap[listStyleType];
13848
+ return (style === null || style === void 0 ? void 0 : style.indexOf('"')) >= 0;
13849
+ }
13327
13850
  /**
13328
13851
  * @internal
13329
13852
  */
@@ -13334,13 +13857,10 @@ exports.listItemMetadataApplier = {
13334
13857
  var depth = context.listFormat.nodeStack.length - 2; // Minus two for the parent element and convert length to index
13335
13858
  if (depth >= 0) {
13336
13859
  var listType = (_a = context.listFormat.nodeStack[depth + 1].listType) !== null && _a !== void 0 ? _a : 'OL';
13337
- var listStyleType = getRawListStyleType(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13338
- if (listStyleType) {
13339
- if (shouldApplyToItem(listStyleType)) {
13340
- format.listStyleType =
13341
- listType == 'OL'
13342
- ? getOrderedListStyleValue(listStyleType, context.listFormat.threadItemCounts[depth])
13343
- : listStyleType;
13860
+ var listStyleType = (0, roosterjs_content_model_dom_1.getAutoListStyleType)(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13861
+ if (listStyleType !== undefined) {
13862
+ if (shouldApplyToItem(listStyleType, listType)) {
13863
+ format.listStyleType = getListStyleValue(listType, listStyleType, context.listFormat.threadItemCounts[depth]);
13344
13864
  }
13345
13865
  else {
13346
13866
  delete format.listStyleType;
@@ -13359,10 +13879,13 @@ exports.listLevelMetadataApplier = {
13359
13879
  var depth = context.listFormat.nodeStack.length - 2; // Minus two for the parent element and convert length to index
13360
13880
  if (depth >= 0) {
13361
13881
  var listType = (_a = context.listFormat.nodeStack[depth + 1].listType) !== null && _a !== void 0 ? _a : 'OL';
13362
- var listStyleType = getRawListStyleType(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13363
- if (listStyleType) {
13364
- if (!shouldApplyToItem(listStyleType)) {
13365
- format.listStyleType = listStyleType;
13882
+ var listStyleType = (0, roosterjs_content_model_dom_1.getAutoListStyleType)(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13883
+ if (listStyleType !== undefined) {
13884
+ if (!shouldApplyToItem(listStyleType, listType)) {
13885
+ var listStyleTypeFormat = getListStyleValue(listType, listStyleType, context.listFormat.threadItemCounts[depth]);
13886
+ if (listStyleTypeFormat) {
13887
+ format.listStyleType = listStyleTypeFormat;
13888
+ }
13366
13889
  }
13367
13890
  else {
13368
13891
  delete format.listStyleType;
@@ -13610,6 +14133,7 @@ exports.defaultContentModelFormatMap = void 0;
13610
14133
  exports.defaultContentModelFormatMap = {
13611
14134
  a: {
13612
14135
  underline: true,
14136
+ textColor: undefined, // Set to undefined to force override color from parent element so we can write correct link color if any, because browser will assign a default color for link if it doesn't have one
13613
14137
  },
13614
14138
  blockquote: {
13615
14139
  marginTop: '1em',
@@ -13927,6 +14451,10 @@ exports.ChangeSource = {
13927
14451
  * Data of this event will be the key code number
13928
14452
  */
13929
14453
  Keyboard: 'Keyboard',
14454
+ /**
14455
+ * Content changed by auto format
14456
+ */
14457
+ AutoFormat: 'AutoFormat',
13930
14458
  };
13931
14459
 
13932
14460
 
@@ -14417,7 +14945,11 @@ var normalizeContentModel_1 = __webpack_require__(/*! ../modelApi/common/normali
14417
14945
  * @returns A ContentModelDocument object that contains all the models created from the give root element
14418
14946
  */
14419
14947
  function domToContentModel(root, context) {
14948
+ var _a;
14420
14949
  var model = (0, createContentModelDocument_1.createContentModelDocument)(context.defaultFormat);
14950
+ if (((_a = context.selection) === null || _a === void 0 ? void 0 : _a.type) == 'range' && context.selection.isReverted) {
14951
+ model.hasRevertedRangeSelection = true;
14952
+ }
14421
14953
  context.elementProcessors.child(model, root, context);
14422
14954
  (0, normalizeContentModel_1.normalizeContentModel)(model);
14423
14955
  return model;
@@ -16015,19 +16547,22 @@ function stackFormatInternal(format, processType) {
16015
16547
  "use strict";
16016
16548
 
16017
16549
  Object.defineProperty(exports, "__esModule", ({ value: true }));
16018
- exports.addDelimiters = exports.isEntityDelimiter = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestEntityWrapper = exports.isEntityElement = void 0;
16550
+ exports.addDelimiters = exports.isBlockEntityContainer = exports.isEntityDelimiter = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestBlockEntityContainer = exports.findClosestEntityWrapper = exports.isEntityElement = void 0;
16019
16551
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
16020
16552
  var applyFormat_1 = __webpack_require__(/*! ../modelToDom/utils/applyFormat */ "./packages/roosterjs-content-model-dom/lib/modelToDom/utils/applyFormat.ts");
16021
16553
  var isElementOfType_1 = __webpack_require__(/*! ./isElementOfType */ "./packages/roosterjs-content-model-dom/lib/domUtils/isElementOfType.ts");
16022
16554
  var isNodeOfType_1 = __webpack_require__(/*! ./isNodeOfType */ "./packages/roosterjs-content-model-dom/lib/domUtils/isNodeOfType.ts");
16023
16555
  var toArray_1 = __webpack_require__(/*! ./toArray */ "./packages/roosterjs-content-model-dom/lib/domUtils/toArray.ts");
16024
16556
  var ENTITY_INFO_NAME = '_Entity';
16557
+ var ENTITY_INFO_SELECTOR = '.' + ENTITY_INFO_NAME;
16025
16558
  var ENTITY_TYPE_PREFIX = '_EType_';
16026
16559
  var ENTITY_ID_PREFIX = '_EId_';
16027
16560
  var ENTITY_READONLY_PREFIX = '_EReadonly_';
16028
16561
  var ZERO_WIDTH_SPACE = '\u200B';
16029
16562
  var DELIMITER_BEFORE = 'entityDelimiterBefore';
16030
16563
  var DELIMITER_AFTER = 'entityDelimiterAfter';
16564
+ var BLOCK_ENTITY_CONTAINER = '_E_EBlockEntityContainer';
16565
+ var BLOCK_ENTITY_CONTAINER_SELECTOR = '.' + BLOCK_ENTITY_CONTAINER;
16031
16566
  /**
16032
16567
  * Check if the given DOM Node is an entity wrapper element
16033
16568
  */
@@ -16041,9 +16576,19 @@ exports.isEntityElement = isEntityElement;
16041
16576
  * @param domHelper The DOM helper to use
16042
16577
  */
16043
16578
  function findClosestEntityWrapper(startNode, domHelper) {
16044
- return domHelper.findClosestElementAncestor(startNode, "." + ENTITY_INFO_NAME);
16579
+ return domHelper.findClosestElementAncestor(startNode, ENTITY_INFO_SELECTOR);
16045
16580
  }
16046
16581
  exports.findClosestEntityWrapper = findClosestEntityWrapper;
16582
+ /**
16583
+ * Find the closest block entity wrapper element from a given DOM node
16584
+ * @param node The node to start looking for entity container
16585
+ * @param domHelper The DOM helper
16586
+ * @returns
16587
+ */
16588
+ function findClosestBlockEntityContainer(node, domHelper) {
16589
+ return domHelper.findClosestElementAncestor(node, BLOCK_ENTITY_CONTAINER_SELECTOR);
16590
+ }
16591
+ exports.findClosestBlockEntityContainer = findClosestBlockEntityContainer;
16047
16592
  /**
16048
16593
  * Get all entity wrapper elements under the given root element
16049
16594
  * @param root The root element to query from
@@ -16105,15 +16650,27 @@ exports.generateEntityClassNames = generateEntityClassNames;
16105
16650
  /**
16106
16651
  * Checks whether the node provided is a Entity delimiter
16107
16652
  * @param node the node to check
16653
+ * @param isBefore True to match delimiter before entity only, false to match delimiter after entity, or undefined means match both
16108
16654
  * @return true if it is a delimiter
16109
16655
  */
16110
- function isEntityDelimiter(element) {
16656
+ function isEntityDelimiter(element, isBefore) {
16657
+ var matchBefore = isBefore === undefined || isBefore;
16658
+ var matchAfter = isBefore === undefined || !isBefore;
16111
16659
  return ((0, isElementOfType_1.isElementOfType)(element, 'span') &&
16112
- (element.classList.contains(DELIMITER_AFTER) ||
16113
- element.classList.contains(DELIMITER_BEFORE)) &&
16660
+ ((matchAfter && element.classList.contains(DELIMITER_AFTER)) ||
16661
+ (matchBefore && element.classList.contains(DELIMITER_BEFORE))) &&
16114
16662
  element.textContent === ZERO_WIDTH_SPACE);
16115
16663
  }
16116
16664
  exports.isEntityDelimiter = isEntityDelimiter;
16665
+ /**
16666
+ * Check if the given element is a container element of block entity
16667
+ * @param element The element to check
16668
+ * @returns True if the element is a block entity container, otherwise false
16669
+ */
16670
+ function isBlockEntityContainer(element) {
16671
+ return (0, isElementOfType_1.isElementOfType)(element, 'div') && element.classList.contains(BLOCK_ENTITY_CONTAINER);
16672
+ }
16673
+ exports.isBlockEntityContainer = isBlockEntityContainer;
16117
16674
  /**
16118
16675
  * Adds delimiters to the element provided. If the delimiters already exists, will not be added
16119
16676
  * @param element the node to add the delimiters
@@ -19007,9 +19564,9 @@ exports.shouldSetValue = shouldSetValue;
19007
19564
  "use strict";
19008
19565
 
19009
19566
  Object.defineProperty(exports, "__esModule", ({ value: true }));
19010
- 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;
19011
- 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;
19012
- exports.UnorderedListStyleMap = exports.OrderedListStyleMap = exports.TableBorderFormat = exports.NumberingListType = exports.BulletListType = exports.ChangeSource = exports.ListMetadataDefinition = exports.updateListMetadata = exports.updateTableMetadata = exports.updateTableCellMetadata = exports.updateImageMetadata = exports.getSegmentTextFormat = exports.getListStyleTypeFromString = exports.retrieveModelFormatState = exports.setTableCellBackgroundColor = exports.MIN_ALLOWED_TABLE_CELL_WIDTH = exports.normalizeTable = exports.applyTableFormat = exports.deleteBlock = exports.deleteSegment = exports.deleteSelection = exports.mergeModel = exports.cloneModel = exports.setSelection = exports.hasSelectionInBlockGroup = void 0;
19567
+ exports.createListLevel = exports.createDivider = exports.createEntity = exports.createGeneralBlock = exports.createGeneralSegment = exports.createParagraphDecorator = exports.createContentModelDocument = exports.createImage = exports.createText = exports.createTableCell = exports.createTable = exports.createSelectionMarker = exports.createParagraph = exports.createFormatContainer = exports.createListItem = exports.createBr = exports.normalizeRect = exports.isWhiteSpacePreserved = exports.reuseCachedElement = exports.findClosestBlockEntityContainer = exports.isBlockEntityContainer = exports.isEntityDelimiter = exports.addDelimiters = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestEntityWrapper = exports.isEntityElement = exports.wrap = exports.wrapAllChildNodes = exports.moveChildNodes = exports.toArray = exports.getObjectKeys = exports.isElementOfType = exports.isNodeOfType = exports.hasMetadata = exports.updateMetadata = exports.buildSelectionMarker = exports.isBlockElement = exports.areSameFormats = exports.parseFormat = exports.getRegularSelectionOffsets = exports.tableProcessor = exports.entityProcessor = exports.processChildNode = exports.handleRegularSelection = exports.childProcessor = exports.contentModelToText = exports.contentModelToDom = exports.domToContentModel = void 0;
19568
+ exports.getSelectedSegments = exports.getSelectedParagraphs = exports.getOperationalBlocks = exports.getFirstSelectedTable = exports.getFirstSelectedListItem = exports.iterateSelections = exports.getClosestAncestorBlockGroupIndex = exports.isBlockGroupOfType = exports.cacheGetEventData = exports.extractClipboardItems = exports.transformColor = exports.readFile = exports.parseTableCells = exports.normalizeText = exports.isSpace = exports.isPunctuation = exports.extractBorderValues = exports.combineBorderValue = exports.isCursorMovingKey = exports.isModifierKey = exports.isCharacterValue = exports.getSelectionRootNode = exports.isBold = exports.createModelToDomConfig = exports.createModelToDomContextWithConfig = exports.createModelToDomContext = exports.createDomToModelConfig = exports.createDomToModelContextWithConfig = exports.createDomToModelContext = exports.parseColor = exports.setColor = exports.getColor = exports.DeprecatedColors = exports.BorderKeys = exports.parseValueWithUnit = exports.getAutoListStyleType = exports.getOrderedListNumberStr = exports.setParagraphNotImplicit = exports.normalizeSingleSegment = exports.isEmpty = exports.addSegment = exports.unwrapBlock = exports.isGeneralSegment = exports.normalizeContentModel = exports.normalizeParagraph = exports.addTextSegment = exports.addLink = exports.addCode = exports.addBlock = exports.createEmptyModel = void 0;
19569
+ exports.UnorderedListStyleMap = exports.OrderedListStyleMap = exports.TableBorderFormat = exports.NumberingListType = exports.BulletListType = exports.ChangeSource = exports.ListMetadataDefinition = exports.updateListMetadata = exports.updateTableMetadata = exports.updateTableCellMetadata = exports.updateImageMetadata = exports.getSegmentTextFormat = exports.getListStyleTypeFromString = exports.retrieveModelFormatState = exports.setTableCellBackgroundColor = exports.MIN_ALLOWED_TABLE_CELL_WIDTH = exports.normalizeTable = exports.applyTableFormat = exports.deleteBlock = exports.deleteSegment = exports.deleteSelection = exports.mergeModel = exports.cloneModel = exports.setSelection = exports.hasSelectionInBlockGroup = exports.hasSelectionInSegment = exports.hasSelectionInBlock = exports.getSelectedCells = exports.getSelectedSegmentsAndParagraphs = void 0;
19013
19570
  var domToContentModel_1 = __webpack_require__(/*! ./domToModel/domToContentModel */ "./packages/roosterjs-content-model-dom/lib/domToModel/domToContentModel.ts");
19014
19571
  Object.defineProperty(exports, "domToContentModel", ({ enumerable: true, get: function () { return domToContentModel_1.domToContentModel; } }));
19015
19572
  var contentModelToDom_1 = __webpack_require__(/*! ./modelToDom/contentModelToDom */ "./packages/roosterjs-content-model-dom/lib/modelToDom/contentModelToDom.ts");
@@ -19058,6 +19615,8 @@ Object.defineProperty(exports, "parseEntityFormat", ({ enumerable: true, get: fu
19058
19615
  Object.defineProperty(exports, "generateEntityClassNames", ({ enumerable: true, get: function () { return entityUtils_1.generateEntityClassNames; } }));
19059
19616
  Object.defineProperty(exports, "addDelimiters", ({ enumerable: true, get: function () { return entityUtils_1.addDelimiters; } }));
19060
19617
  Object.defineProperty(exports, "isEntityDelimiter", ({ enumerable: true, get: function () { return entityUtils_1.isEntityDelimiter; } }));
19618
+ Object.defineProperty(exports, "isBlockEntityContainer", ({ enumerable: true, get: function () { return entityUtils_1.isBlockEntityContainer; } }));
19619
+ Object.defineProperty(exports, "findClosestBlockEntityContainer", ({ enumerable: true, get: function () { return entityUtils_1.findClosestBlockEntityContainer; } }));
19061
19620
  var reuseCachedElement_1 = __webpack_require__(/*! ./domUtils/reuseCachedElement */ "./packages/roosterjs-content-model-dom/lib/domUtils/reuseCachedElement.ts");
19062
19621
  Object.defineProperty(exports, "reuseCachedElement", ({ enumerable: true, get: function () { return reuseCachedElement_1.reuseCachedElement; } }));
19063
19622
  var isWhiteSpacePreserved_1 = __webpack_require__(/*! ./domUtils/isWhiteSpacePreserved */ "./packages/roosterjs-content-model-dom/lib/domUtils/isWhiteSpacePreserved.ts");
@@ -19122,6 +19681,10 @@ var normalizeSegment_1 = __webpack_require__(/*! ./modelApi/common/normalizeSegm
19122
19681
  Object.defineProperty(exports, "normalizeSingleSegment", ({ enumerable: true, get: function () { return normalizeSegment_1.normalizeSingleSegment; } }));
19123
19682
  var setParagraphNotImplicit_1 = __webpack_require__(/*! ./modelApi/block/setParagraphNotImplicit */ "./packages/roosterjs-content-model-dom/lib/modelApi/block/setParagraphNotImplicit.ts");
19124
19683
  Object.defineProperty(exports, "setParagraphNotImplicit", ({ enumerable: true, get: function () { return setParagraphNotImplicit_1.setParagraphNotImplicit; } }));
19684
+ var getOrderedListNumberStr_1 = __webpack_require__(/*! ./modelApi/list/getOrderedListNumberStr */ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getOrderedListNumberStr.ts");
19685
+ Object.defineProperty(exports, "getOrderedListNumberStr", ({ enumerable: true, get: function () { return getOrderedListNumberStr_1.getOrderedListNumberStr; } }));
19686
+ var getAutoListStyleType_1 = __webpack_require__(/*! ./modelApi/list/getAutoListStyleType */ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getAutoListStyleType.ts");
19687
+ Object.defineProperty(exports, "getAutoListStyleType", ({ enumerable: true, get: function () { return getAutoListStyleType_1.getAutoListStyleType; } }));
19125
19688
  var parseValueWithUnit_1 = __webpack_require__(/*! ./formatHandlers/utils/parseValueWithUnit */ "./packages/roosterjs-content-model-dom/lib/formatHandlers/utils/parseValueWithUnit.ts");
19126
19689
  Object.defineProperty(exports, "parseValueWithUnit", ({ enumerable: true, get: function () { return parseValueWithUnit_1.parseValueWithUnit; } }));
19127
19690
  var borderFormatHandler_1 = __webpack_require__(/*! ./formatHandlers/common/borderFormatHandler */ "./packages/roosterjs-content-model-dom/lib/formatHandlers/common/borderFormatHandler.ts");
@@ -22138,6 +22701,175 @@ function calculateLightness(color) {
22138
22701
  }
22139
22702
 
22140
22703
 
22704
+ /***/ }),
22705
+
22706
+ /***/ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getAutoListStyleType.ts":
22707
+ /*!****************************************************************************************!*\
22708
+ !*** ./packages/roosterjs-content-model-dom/lib/modelApi/list/getAutoListStyleType.ts ***!
22709
+ \****************************************************************************************/
22710
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
22711
+
22712
+ "use strict";
22713
+
22714
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
22715
+ exports.getAutoListStyleType = void 0;
22716
+ var BulletListType_1 = __webpack_require__(/*! ../../constants/BulletListType */ "./packages/roosterjs-content-model-dom/lib/constants/BulletListType.ts");
22717
+ var NumberingListType_1 = __webpack_require__(/*! ../../constants/NumberingListType */ "./packages/roosterjs-content-model-dom/lib/constants/NumberingListType.ts");
22718
+ var DefaultOrderedListStyles = [
22719
+ NumberingListType_1.NumberingListType.Decimal,
22720
+ NumberingListType_1.NumberingListType.LowerAlpha,
22721
+ NumberingListType_1.NumberingListType.LowerRoman,
22722
+ ];
22723
+ var DefaultUnorderedListStyles = [
22724
+ BulletListType_1.BulletListType.Disc,
22725
+ BulletListType_1.BulletListType.Circle,
22726
+ BulletListType_1.BulletListType.Square,
22727
+ ];
22728
+ var OrderedListStyleRevertMap = {
22729
+ 'lower-alpha': NumberingListType_1.NumberingListType.LowerAlpha,
22730
+ 'lower-latin': NumberingListType_1.NumberingListType.LowerAlpha,
22731
+ 'upper-alpha': NumberingListType_1.NumberingListType.UpperAlpha,
22732
+ 'upper-latin': NumberingListType_1.NumberingListType.UpperAlpha,
22733
+ 'lower-roman': NumberingListType_1.NumberingListType.LowerRoman,
22734
+ 'upper-roman': NumberingListType_1.NumberingListType.UpperRoman,
22735
+ };
22736
+ var UnorderedListStyleRevertMap = {
22737
+ disc: BulletListType_1.BulletListType.Disc,
22738
+ circle: BulletListType_1.BulletListType.Circle,
22739
+ square: BulletListType_1.BulletListType.Square,
22740
+ };
22741
+ /**
22742
+ * Get automatic list style of a list item according to its lis type and metadata.
22743
+ * @param listType The list type, either OL or UL
22744
+ * @param metadata Metadata of this list item from list item model
22745
+ * @param depth Depth of list level, start from 0
22746
+ * @param existingStyleType Existing list style type in format, if any
22747
+ * @returns A number to represent list style type.
22748
+ * This will be the value of either NumberingListType (when listType is OL) or BulletListType (when listType is UL).
22749
+ * When there is a specified list style in its metadata, return this value, otherwise
22750
+ * When specified "applyListStyleFromLevel" in metadata, calculate auto list type from its depth, otherwise
22751
+ * When there is already listStyleType in list level format, find a related style type index, otherwise
22752
+ * return undefined
22753
+ */
22754
+ function getAutoListStyleType(listType, metadata, depth, existingStyleType) {
22755
+ var orderedStyleType = metadata.orderedStyleType, unorderedStyleType = metadata.unorderedStyleType, applyListStyleFromLevel = metadata.applyListStyleFromLevel;
22756
+ if (listType == 'OL') {
22757
+ return typeof orderedStyleType == 'number'
22758
+ ? orderedStyleType
22759
+ : applyListStyleFromLevel
22760
+ ? DefaultOrderedListStyles[depth % DefaultOrderedListStyles.length]
22761
+ : existingStyleType
22762
+ ? OrderedListStyleRevertMap[existingStyleType]
22763
+ : undefined;
22764
+ }
22765
+ else {
22766
+ return typeof unorderedStyleType == 'number'
22767
+ ? unorderedStyleType
22768
+ : applyListStyleFromLevel
22769
+ ? DefaultUnorderedListStyles[depth % DefaultUnorderedListStyles.length]
22770
+ : existingStyleType
22771
+ ? UnorderedListStyleRevertMap[existingStyleType]
22772
+ : undefined;
22773
+ }
22774
+ }
22775
+ exports.getAutoListStyleType = getAutoListStyleType;
22776
+
22777
+
22778
+ /***/ }),
22779
+
22780
+ /***/ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getOrderedListNumberStr.ts":
22781
+ /*!*******************************************************************************************!*\
22782
+ !*** ./packages/roosterjs-content-model-dom/lib/modelApi/list/getOrderedListNumberStr.ts ***!
22783
+ \*******************************************************************************************/
22784
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
22785
+
22786
+ "use strict";
22787
+
22788
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
22789
+ exports.getOrderedListNumberStr = void 0;
22790
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
22791
+ var getObjectKeys_1 = __webpack_require__(/*! ../../domUtils/getObjectKeys */ "./packages/roosterjs-content-model-dom/lib/domUtils/getObjectKeys.ts");
22792
+ var NumberingListType_1 = __webpack_require__(/*! ../../constants/NumberingListType */ "./packages/roosterjs-content-model-dom/lib/constants/NumberingListType.ts");
22793
+ var CharCodeOfA = 65;
22794
+ var RomanValues = {
22795
+ M: 1000,
22796
+ CM: 900,
22797
+ D: 500,
22798
+ CD: 400,
22799
+ C: 100,
22800
+ XC: 90,
22801
+ L: 50,
22802
+ XL: 40,
22803
+ X: 10,
22804
+ IX: 9,
22805
+ V: 5,
22806
+ IV: 4,
22807
+ I: 1,
22808
+ };
22809
+ /**
22810
+ * Get the list number for a list item according to list style type and its index number
22811
+ * @param styleType The list style number, should be a value of NumberingListType type
22812
+ * @param listNumber List number, start from 1
22813
+ * @returns A string for this list item. For example, when pass in NumberingListType.LowerAlpha and 2, it returns "b"
22814
+ */
22815
+ function getOrderedListNumberStr(styleType, listNumber) {
22816
+ switch (styleType) {
22817
+ case NumberingListType_1.NumberingListType.LowerAlpha:
22818
+ case NumberingListType_1.NumberingListType.LowerAlphaDash:
22819
+ case NumberingListType_1.NumberingListType.LowerAlphaDoubleParenthesis:
22820
+ case NumberingListType_1.NumberingListType.LowerAlphaParenthesis:
22821
+ return convertDecimalsToAlpha(listNumber, true /*isLowerCase*/);
22822
+ case NumberingListType_1.NumberingListType.UpperAlpha:
22823
+ case NumberingListType_1.NumberingListType.UpperAlphaDash:
22824
+ case NumberingListType_1.NumberingListType.UpperAlphaDoubleParenthesis:
22825
+ case NumberingListType_1.NumberingListType.UpperAlphaParenthesis:
22826
+ return convertDecimalsToAlpha(listNumber, false /*isLowerCase*/);
22827
+ case NumberingListType_1.NumberingListType.LowerRoman:
22828
+ case NumberingListType_1.NumberingListType.LowerRomanDash:
22829
+ case NumberingListType_1.NumberingListType.LowerRomanDoubleParenthesis:
22830
+ case NumberingListType_1.NumberingListType.LowerRomanParenthesis:
22831
+ return convertDecimalsToRoman(listNumber, true /*isLowerCase*/);
22832
+ case NumberingListType_1.NumberingListType.UpperRoman:
22833
+ case NumberingListType_1.NumberingListType.UpperRomanDash:
22834
+ case NumberingListType_1.NumberingListType.UpperRomanDoubleParenthesis:
22835
+ case NumberingListType_1.NumberingListType.UpperRomanParenthesis:
22836
+ return convertDecimalsToRoman(listNumber, false /*isLowerCase*/);
22837
+ default:
22838
+ return listNumber + '';
22839
+ }
22840
+ }
22841
+ exports.getOrderedListNumberStr = getOrderedListNumberStr;
22842
+ function convertDecimalsToAlpha(decimal, isLowerCase) {
22843
+ var alpha = '';
22844
+ decimal--;
22845
+ while (decimal >= 0) {
22846
+ alpha = String.fromCharCode((decimal % 26) + CharCodeOfA) + alpha;
22847
+ decimal = Math.floor(decimal / 26) - 1;
22848
+ }
22849
+ return isLowerCase ? alpha.toLowerCase() : alpha;
22850
+ }
22851
+ function convertDecimalsToRoman(decimal, isLowerCase) {
22852
+ var e_1, _a;
22853
+ var romanValue = '';
22854
+ try {
22855
+ for (var _b = (0, tslib_1.__values)((0, getObjectKeys_1.getObjectKeys)(RomanValues)), _c = _b.next(); !_c.done; _c = _b.next()) {
22856
+ var i = _c.value;
22857
+ var timesRomanCharAppear = Math.floor(decimal / RomanValues[i]);
22858
+ decimal = decimal - timesRomanCharAppear * RomanValues[i];
22859
+ romanValue = romanValue + i.repeat(timesRomanCharAppear);
22860
+ }
22861
+ }
22862
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
22863
+ finally {
22864
+ try {
22865
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
22866
+ }
22867
+ finally { if (e_1) throw e_1.error; }
22868
+ }
22869
+ return isLowerCase ? romanValue.toLocaleLowerCase() : romanValue;
22870
+ }
22871
+
22872
+
22141
22873
  /***/ }),
22142
22874
 
22143
22875
  /***/ "./packages/roosterjs-content-model-dom/lib/modelApi/metadata/definitionCreators.ts":
@@ -22534,17 +23266,19 @@ var iterateSelections_1 = __webpack_require__(/*! ./iterateSelections */ "./pack
22534
23266
  * @param model The Content Model to get selection from
22535
23267
  * @param includingFormatHolder True means also include format holder as segment from list item, in that case paragraph will be null
22536
23268
  */
22537
- function getSelectedSegmentsAndParagraphs(model, includingFormatHolder) {
23269
+ function getSelectedSegmentsAndParagraphs(model, includingFormatHolder, includingEntity) {
22538
23270
  var selections = collectSelections(model, {
22539
23271
  includeListFormatHolder: includingFormatHolder ? 'allSegments' : 'never',
22540
23272
  });
22541
23273
  var result = [];
22542
23274
  selections.forEach(function (_a) {
22543
- var segments = _a.segments, block = _a.block;
23275
+ var segments = _a.segments, block = _a.block, path = _a.path;
22544
23276
  if (segments && ((includingFormatHolder && !block) || (block === null || block === void 0 ? void 0 : block.blockType) == 'Paragraph')) {
22545
23277
  segments.forEach(function (segment) {
22546
- if (segment.segmentType != 'Entity' || !segment.entityFormat.isReadonly) {
22547
- result.push([segment, (block === null || block === void 0 ? void 0 : block.blockType) == 'Paragraph' ? block : null]);
23278
+ if (includingEntity ||
23279
+ segment.segmentType != 'Entity' ||
23280
+ !segment.entityFormat.isReadonly) {
23281
+ result.push([segment, (block === null || block === void 0 ? void 0 : block.blockType) == 'Paragraph' ? block : null, path]);
22548
23282
  }
22549
23283
  });
22550
23284
  }
@@ -22580,15 +23314,15 @@ function getSelectedParagraphs(model) {
22580
23314
  exports.getSelectedParagraphs = getSelectedParagraphs;
22581
23315
  /**
22582
23316
  * Get an array of block group - block pair that is of the expected block group type from selection
22583
- * @param model The Content Model to get selection from
23317
+ * @param group The root block group to search
22584
23318
  * @param blockGroupTypes The expected block group types
22585
23319
  * @param stopTypes Block group types that will stop searching when hit
22586
23320
  * @param deepFirst True means search in deep first, otherwise wide first
22587
23321
  */
22588
- function getOperationalBlocks(model, blockGroupTypes, stopTypes, deepFirst) {
23322
+ function getOperationalBlocks(group, blockGroupTypes, stopTypes, deepFirst) {
22589
23323
  var result = [];
22590
23324
  var findSequence = deepFirst ? blockGroupTypes.map(function (type) { return [type]; }) : [blockGroupTypes];
22591
- var selections = collectSelections(model, {
23325
+ var selections = collectSelections(group, {
22592
23326
  includeListFormatHolder: 'never',
22593
23327
  contentUnderSelectedTableCell: 'ignoreForTable', // When whole table is selected, we treat the table as a single block
22594
23328
  });
@@ -22666,9 +23400,9 @@ function getFirstSelectedListItem(model) {
22666
23400
  return listItem;
22667
23401
  }
22668
23402
  exports.getFirstSelectedListItem = getFirstSelectedListItem;
22669
- function collectSelections(model, option) {
23403
+ function collectSelections(group, option) {
22670
23404
  var selections = [];
22671
- (0, iterateSelections_1.iterateSelections)(model, function (path, tableContext, block, segments) {
23405
+ (0, iterateSelections_1.iterateSelections)(group, function (path, tableContext, block, segments) {
22672
23406
  selections.push({
22673
23407
  path: path,
22674
23408
  tableContext: tableContext,
@@ -23209,6 +23943,9 @@ var toArray_1 = __webpack_require__(/*! ../domUtils/toArray */ "./packages/roost
23209
23943
  function contentModelToDom(doc, root, model, context) {
23210
23944
  context.modelHandlers.blockGroupChildren(doc, root, model, context);
23211
23945
  var range = extractSelectionRange(doc, context);
23946
+ if (model.hasRevertedRangeSelection && (range === null || range === void 0 ? void 0 : range.type) == 'range') {
23947
+ range.isReverted = true;
23948
+ }
23212
23949
  root.normalize();
23213
23950
  return range;
23214
23951
  }
@@ -24552,6 +25289,7 @@ exports.stackFormat = stackFormat;
24552
25289
 
24553
25290
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24554
25291
  exports.contentModelToText = void 0;
25292
+ var TextForHR = '________________________________________';
24555
25293
  /**
24556
25294
  * Convert Content Model to plain text
24557
25295
  * @param model The source Content Model
@@ -24589,9 +25327,13 @@ function contentModelToTextArray(group, textArray) {
24589
25327
  break;
24590
25328
  }
24591
25329
  });
24592
- textArray.push(text_1);
25330
+ if (text_1) {
25331
+ textArray.push(text_1);
25332
+ }
24593
25333
  break;
24594
25334
  case 'Divider':
25335
+ textArray.push(block.tagName == 'hr' ? TextForHR : '');
25336
+ break;
24595
25337
  case 'Entity':
24596
25338
  textArray.push('');
24597
25339
  break;
@@ -24622,9 +25364,14 @@ function contentModelToTextArray(group, textArray) {
24622
25364
 
24623
25365
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24624
25366
  exports.AutoFormatPlugin = void 0;
25367
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
24625
25368
  var createLink_1 = __webpack_require__(/*! ./link/createLink */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLink.ts");
24626
25369
  var createLinkAfterSpace_1 = __webpack_require__(/*! ./link/createLinkAfterSpace */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLinkAfterSpace.ts");
25370
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
24627
25371
  var keyboardListTrigger_1 = __webpack_require__(/*! ./list/keyboardListTrigger */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/list/keyboardListTrigger.ts");
25372
+ var transformFraction_1 = __webpack_require__(/*! ./numbers/transformFraction */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformFraction.ts");
25373
+ var transformHyphen_1 = __webpack_require__(/*! ./hyphen/transformHyphen */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/hyphen/transformHyphen.ts");
25374
+ var transformOrdinals_1 = __webpack_require__(/*! ./numbers/transformOrdinals */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformOrdinals.ts");
24628
25375
  var unlink_1 = __webpack_require__(/*! ./link/unlink */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/unlink.ts");
24629
25376
  /**
24630
25377
  * @internal
@@ -24634,6 +25381,9 @@ var DefaultOptions = {
24634
25381
  autoNumbering: false,
24635
25382
  autoUnlink: false,
24636
25383
  autoLink: false,
25384
+ autoHyphen: false,
25385
+ autoFraction: false,
25386
+ autoOrdinals: false,
24637
25387
  };
24638
25388
  /**
24639
25389
  * Auto Format plugin handles auto formatting, such as transforming * characters into a bullet list.
@@ -24646,6 +25396,9 @@ var AutoFormatPlugin = /** @class */ (function () {
24646
25396
  * - autoNumbering: A boolean that enables or disables automatic numbering formatting. Defaults to false.
24647
25397
  * - autoLink: A boolean that enables or disables automatic hyperlink creation when pasting or typing content. Defaults to false.
24648
25398
  * - autoUnlink: A boolean that enables or disables automatic hyperlink removal when pressing backspace. Defaults to false.
25399
+ * - autoHyphen: A boolean that enables or disables automatic hyphen transformation. Defaults to false.
25400
+ * - autoFraction: A boolean that enables or disables automatic fraction transformation. Defaults to false.
25401
+ * - autoOrdinals: A boolean that enables or disables automatic ordinal number transformation. Defaults to false.
24649
25402
  */
24650
25403
  function AutoFormatPlugin(options) {
24651
25404
  if (options === void 0) { options = DefaultOptions; }
@@ -24697,15 +25450,49 @@ var AutoFormatPlugin = /** @class */ (function () {
24697
25450
  }
24698
25451
  };
24699
25452
  AutoFormatPlugin.prototype.handleEditorInputEvent = function (editor, event) {
25453
+ var _this = this;
24700
25454
  var rawEvent = event.rawEvent;
24701
- if (rawEvent.inputType === 'insertText') {
25455
+ var selection = editor.getDOMSelection();
25456
+ if (rawEvent.inputType === 'insertText' &&
25457
+ selection &&
25458
+ selection.type === 'range' &&
25459
+ selection.range.collapsed) {
24702
25460
  switch (rawEvent.data) {
24703
25461
  case ' ':
24704
- var _a = this.options, autoBullet = _a.autoBullet, autoNumbering = _a.autoNumbering, autoLink = _a.autoLink;
24705
- (0, keyboardListTrigger_1.keyboardListTrigger)(editor, autoBullet, autoNumbering);
24706
- if (autoLink) {
24707
- (0, createLinkAfterSpace_1.createLinkAfterSpace)(editor);
24708
- }
25462
+ var formatOptions_1 = {
25463
+ changeSource: '',
25464
+ apiName: '',
25465
+ };
25466
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (model, previousSegment, paragraph, _markerFormat, context) {
25467
+ var _a = _this.options, autoBullet = _a.autoBullet, autoNumbering = _a.autoNumbering, autoLink = _a.autoLink, autoHyphen = _a.autoHyphen, autoFraction = _a.autoFraction, autoOrdinals = _a.autoOrdinals;
25468
+ var shouldHyphen = false;
25469
+ var shouldLink = false;
25470
+ var shouldList = false;
25471
+ var shouldFraction = false;
25472
+ var shouldOrdinals = false;
25473
+ if (autoBullet || autoNumbering) {
25474
+ shouldList = (0, keyboardListTrigger_1.keyboardListTrigger)(model, paragraph, context, autoBullet, autoNumbering);
25475
+ }
25476
+ if (autoLink) {
25477
+ shouldLink = (0, createLinkAfterSpace_1.createLinkAfterSpace)(previousSegment, paragraph, context);
25478
+ }
25479
+ if (autoHyphen) {
25480
+ shouldHyphen = (0, transformHyphen_1.transformHyphen)(previousSegment, paragraph, context);
25481
+ }
25482
+ if (autoFraction) {
25483
+ shouldFraction = (0, transformFraction_1.transformFraction)(previousSegment, paragraph, context);
25484
+ }
25485
+ if (autoOrdinals) {
25486
+ shouldOrdinals = (0, transformOrdinals_1.transformOrdinals)(previousSegment, paragraph, context);
25487
+ }
25488
+ formatOptions_1.apiName = getApiName(shouldList, shouldHyphen);
25489
+ formatOptions_1.changeSource = getChangeSource(shouldList, shouldHyphen, shouldLink);
25490
+ return (shouldList ||
25491
+ shouldHyphen ||
25492
+ shouldLink ||
25493
+ shouldFraction ||
25494
+ shouldOrdinals);
25495
+ }, formatOptions_1);
24709
25496
  break;
24710
25497
  }
24711
25498
  }
@@ -24731,134 +25518,137 @@ var AutoFormatPlugin = /** @class */ (function () {
24731
25518
  return AutoFormatPlugin;
24732
25519
  }());
24733
25520
  exports.AutoFormatPlugin = AutoFormatPlugin;
25521
+ var getApiName = function (shouldList, shouldHyphen) {
25522
+ return shouldList ? 'autoToggleList' : shouldHyphen ? 'autoHyphen' : '';
25523
+ };
25524
+ var getChangeSource = function (shouldList, shouldHyphen, shouldLink) {
25525
+ return shouldList || shouldHyphen
25526
+ ? roosterjs_content_model_dom_1.ChangeSource.AutoFormat
25527
+ : shouldLink
25528
+ ? roosterjs_content_model_dom_1.ChangeSource.AutoLink
25529
+ : '';
25530
+ };
24734
25531
 
24735
25532
 
24736
25533
  /***/ }),
24737
25534
 
24738
- /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLink.ts":
24739
- /*!************************************************************************************!*\
24740
- !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLink.ts ***!
24741
- \************************************************************************************/
25535
+ /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/hyphen/transformHyphen.ts":
25536
+ /*!*******************************************************************************************!*\
25537
+ !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/hyphen/transformHyphen.ts ***!
25538
+ \*******************************************************************************************/
24742
25539
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
24743
25540
 
24744
25541
  "use strict";
24745
25542
 
24746
25543
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24747
- exports.createLink = void 0;
24748
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
24749
- var getLinkSegment_1 = __webpack_require__(/*! ./getLinkSegment */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/getLinkSegment.ts");
25544
+ exports.transformHyphen = void 0;
25545
+ var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
24750
25546
  /**
24751
25547
  * @internal
24752
25548
  */
24753
- function createLink(editor) {
24754
- editor.formatContentModel(function (model) {
24755
- var link = (0, getLinkSegment_1.getLinkSegment)(model);
24756
- if (link && !link.link) {
24757
- (0, roosterjs_content_model_dom_1.addLink)(link, {
24758
- format: {
24759
- href: link.text,
24760
- underline: true,
24761
- },
24762
- dataset: {},
24763
- });
24764
- return true;
25549
+ function transformHyphen(previousSegment, paragraph, context) {
25550
+ var segments = previousSegment.text.split(' ');
25551
+ var dashes = segments[segments.length - 2];
25552
+ if (dashes === '--') {
25553
+ var textIndex = previousSegment.text.lastIndexOf('--');
25554
+ var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + 2);
25555
+ textSegment.text = textSegment.text.replace('--', '—');
25556
+ context.canUndoByBackspace = true;
25557
+ return true;
25558
+ }
25559
+ else {
25560
+ var text = segments.pop();
25561
+ var hasDashes = text && (text === null || text === void 0 ? void 0 : text.indexOf('--')) > -1;
25562
+ if (hasDashes && text.trim() !== '--') {
25563
+ var textIndex = previousSegment.text.indexOf(text);
25564
+ var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + text.length - 1);
25565
+ var textLength = textSegment.text.length;
25566
+ if (textSegment.text[0] !== '-' && textSegment.text[textLength - 1] !== '-') {
25567
+ textSegment.text = textSegment.text.replace('--', '—');
25568
+ context.canUndoByBackspace = true;
25569
+ return true;
25570
+ }
24765
25571
  }
24766
- return false;
24767
- });
25572
+ }
25573
+ return false;
24768
25574
  }
24769
- exports.createLink = createLink;
25575
+ exports.transformHyphen = transformHyphen;
24770
25576
 
24771
25577
 
24772
25578
  /***/ }),
24773
25579
 
24774
- /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLinkAfterSpace.ts":
24775
- /*!**********************************************************************************************!*\
24776
- !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLinkAfterSpace.ts ***!
24777
- \**********************************************************************************************/
25580
+ /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLink.ts":
25581
+ /*!************************************************************************************!*\
25582
+ !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLink.ts ***!
25583
+ \************************************************************************************/
24778
25584
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
24779
25585
 
24780
25586
  "use strict";
24781
25587
 
24782
25588
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24783
- exports.createLinkAfterSpace = void 0;
25589
+ exports.createLink = void 0;
24784
25590
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
24785
25591
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
24786
- var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
24787
25592
  /**
24788
25593
  * @internal
24789
25594
  */
24790
- function createLinkAfterSpace(editor) {
24791
- editor.formatContentModel(function (model, context) {
24792
- var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /* includingFormatHolder */);
24793
- if (selectedSegmentsAndParagraphs.length > 0 && selectedSegmentsAndParagraphs[0][1]) {
24794
- var markerIndex = selectedSegmentsAndParagraphs[0][1].segments.findIndex(function (segment) { return segment.segmentType == 'SelectionMarker'; });
24795
- var paragraph = selectedSegmentsAndParagraphs[0][1];
24796
- if (markerIndex > 0) {
24797
- var textSegment = paragraph.segments[markerIndex - 1];
24798
- var marker = paragraph.segments[markerIndex];
24799
- if (marker.segmentType == 'SelectionMarker' &&
24800
- textSegment &&
24801
- textSegment.segmentType == 'Text' &&
24802
- !textSegment.link) {
24803
- var link = textSegment.text.split(' ').pop();
24804
- var url = link === null || link === void 0 ? void 0 : link.trim();
24805
- var linkData = null;
24806
- if (url && link && (linkData = (0, roosterjs_content_model_api_1.matchLink)(url))) {
24807
- var linkSegment = (0, splitTextSegment_1.splitTextSegment)(textSegment, paragraph, textSegment.text.length - link.trimLeft().length, textSegment.text.trimRight().length);
24808
- linkSegment.link = {
24809
- format: {
24810
- href: linkData.normalizedUrl,
24811
- underline: true,
24812
- },
24813
- dataset: {},
24814
- };
24815
- context.canUndoByBackspace = true;
24816
- return true;
24817
- }
24818
- }
24819
- }
25595
+ function createLink(editor) {
25596
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (_model, linkSegment, _paragraph) {
25597
+ var linkData = null;
25598
+ if (!linkSegment.link && (linkData = (0, roosterjs_content_model_api_1.matchLink)(linkSegment.text))) {
25599
+ (0, roosterjs_content_model_dom_1.addLink)(linkSegment, {
25600
+ format: {
25601
+ href: linkData.normalizedUrl,
25602
+ underline: true,
25603
+ },
25604
+ dataset: {},
25605
+ });
25606
+ return true;
24820
25607
  }
24821
25608
  return false;
25609
+ }, {
25610
+ changeSource: roosterjs_content_model_dom_1.ChangeSource.AutoLink,
24822
25611
  });
24823
25612
  }
24824
- exports.createLinkAfterSpace = createLinkAfterSpace;
25613
+ exports.createLink = createLink;
24825
25614
 
24826
25615
 
24827
25616
  /***/ }),
24828
25617
 
24829
- /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/getLinkSegment.ts":
24830
- /*!****************************************************************************************!*\
24831
- !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/link/getLinkSegment.ts ***!
24832
- \****************************************************************************************/
25618
+ /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLinkAfterSpace.ts":
25619
+ /*!**********************************************************************************************!*\
25620
+ !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLinkAfterSpace.ts ***!
25621
+ \**********************************************************************************************/
24833
25622
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
24834
25623
 
24835
25624
  "use strict";
24836
25625
 
24837
25626
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24838
- exports.getLinkSegment = void 0;
24839
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
25627
+ exports.createLinkAfterSpace = void 0;
24840
25628
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
25629
+ var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
24841
25630
  /**
24842
25631
  * @internal
24843
25632
  */
24844
- function getLinkSegment(model) {
24845
- var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /* includingFormatHolder */);
24846
- if (selectedSegmentsAndParagraphs.length == 1 && selectedSegmentsAndParagraphs[0][1]) {
24847
- var selectedParagraph = selectedSegmentsAndParagraphs[0][1];
24848
- var marker = selectedParagraph.segments[selectedParagraph.segments.length - 1];
24849
- var link = selectedParagraph.segments[selectedParagraph.segments.length - 2];
24850
- if (marker &&
24851
- link &&
24852
- marker.segmentType === 'SelectionMarker' &&
24853
- marker.isSelected &&
24854
- link.segmentType === 'Text' &&
24855
- ((0, roosterjs_content_model_api_1.matchLink)(link.text) || link.link)) {
24856
- return link;
24857
- }
25633
+ function createLinkAfterSpace(previousSegment, paragraph, context) {
25634
+ var link = previousSegment.text.split(' ').pop();
25635
+ var url = link === null || link === void 0 ? void 0 : link.trim();
25636
+ var linkData = null;
25637
+ if (url && link && (linkData = (0, roosterjs_content_model_api_1.matchLink)(url))) {
25638
+ var linkSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - link.trimLeft().length, previousSegment.text.trimRight().length);
25639
+ linkSegment.link = {
25640
+ format: {
25641
+ href: linkData.normalizedUrl,
25642
+ underline: true,
25643
+ },
25644
+ dataset: {},
25645
+ };
25646
+ context.canUndoByBackspace = true;
25647
+ return true;
24858
25648
  }
24859
- return undefined;
25649
+ return false;
24860
25650
  }
24861
- exports.getLinkSegment = getLinkSegment;
25651
+ exports.createLinkAfterSpace = createLinkAfterSpace;
24862
25652
 
24863
25653
 
24864
25654
  /***/ }),
@@ -24873,15 +25663,14 @@ exports.getLinkSegment = getLinkSegment;
24873
25663
 
24874
25664
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24875
25665
  exports.unlink = void 0;
24876
- var getLinkSegment_1 = __webpack_require__(/*! ./getLinkSegment */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/getLinkSegment.ts");
25666
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
24877
25667
  /**
24878
25668
  * @internal
24879
25669
  */
24880
25670
  function unlink(editor, rawEvent) {
24881
- editor.formatContentModel(function (model) {
24882
- var link = (0, getLinkSegment_1.getLinkSegment)(model);
24883
- if (link === null || link === void 0 ? void 0 : link.link) {
24884
- link.link = undefined;
25671
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (_model, linkSegment, _paragraph) {
25672
+ if (linkSegment === null || linkSegment === void 0 ? void 0 : linkSegment.link) {
25673
+ linkSegment.link = undefined;
24885
25674
  rawEvent.preventDefault();
24886
25675
  return true;
24887
25676
  }
@@ -24980,7 +25769,7 @@ function getListTypeStyle(model, shouldSearchForBullet, shouldSearchForNumbering
24980
25769
  marker.segmentType == 'SelectionMarker' &&
24981
25770
  listMarkerSegment &&
24982
25771
  listMarkerSegment.segmentType == 'Text') {
24983
- var listMarker = listMarkerSegment.text;
25772
+ var listMarker = listMarkerSegment.text.trim();
24984
25773
  var bulletType = bulletListType[listMarker];
24985
25774
  if (bulletType && shouldSearchForBullet) {
24986
25775
  return { listType: 'UL', styleType: bulletType };
@@ -25043,7 +25832,7 @@ var bulletListType = {
25043
25832
  '—': roosterjs_content_model_dom_1.BulletListType.Hyphen,
25044
25833
  };
25045
25834
  var isNewList = function (listMarker) {
25046
- var marker = listMarker.replace(/[^\w\s]/g, '').trim();
25835
+ var marker = listMarker.replace(/[^\w\s]/g, '');
25047
25836
  var pattern = /^[1aAiI]$/;
25048
25837
  return pattern.test(marker);
25049
25838
  };
@@ -25226,32 +26015,22 @@ function canAppendList(index, previousListIndex) {
25226
26015
  Object.defineProperty(exports, "__esModule", ({ value: true }));
25227
26016
  exports.keyboardListTrigger = void 0;
25228
26017
  var getListTypeStyle_1 = __webpack_require__(/*! ./getListTypeStyle */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/list/getListTypeStyle.ts");
25229
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
25230
26018
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
25231
26019
  /**
25232
26020
  * @internal
25233
26021
  */
25234
- function keyboardListTrigger(editor, shouldSearchForBullet, shouldSearchForNumbering) {
26022
+ function keyboardListTrigger(model, paragraph, context, shouldSearchForBullet, shouldSearchForNumbering) {
25235
26023
  if (shouldSearchForBullet === void 0) { shouldSearchForBullet = true; }
25236
26024
  if (shouldSearchForNumbering === void 0) { shouldSearchForNumbering = true; }
25237
- if (shouldSearchForBullet || shouldSearchForNumbering) {
25238
- editor.formatContentModel(function (model, context) {
25239
- var listStyleType = (0, getListTypeStyle_1.getListTypeStyle)(model, shouldSearchForBullet, shouldSearchForNumbering);
25240
- if (listStyleType) {
25241
- var segmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false);
25242
- if (segmentsAndParagraphs[0] && segmentsAndParagraphs[0][1]) {
25243
- segmentsAndParagraphs[0][1].segments.splice(0, 1);
25244
- }
25245
- var listType = listStyleType.listType, styleType = listStyleType.styleType, index = listStyleType.index;
25246
- triggerList(model, listType, styleType, index);
25247
- context.canUndoByBackspace = true;
25248
- return true;
25249
- }
25250
- return false;
25251
- }, {
25252
- apiName: 'autoToggleList',
25253
- });
26025
+ var listStyleType = (0, getListTypeStyle_1.getListTypeStyle)(model, shouldSearchForBullet, shouldSearchForNumbering);
26026
+ if (listStyleType) {
26027
+ paragraph.segments.splice(0, 1);
26028
+ var listType = listStyleType.listType, styleType = listStyleType.styleType, index = listStyleType.index;
26029
+ triggerList(model, listType, styleType, index);
26030
+ context.canUndoByBackspace = true;
26031
+ return true;
25254
26032
  }
26033
+ return false;
25255
26034
  }
25256
26035
  exports.keyboardListTrigger = keyboardListTrigger;
25257
26036
  var triggerList = function (model, listType, styleType, index) {
@@ -25270,6 +26049,85 @@ var triggerList = function (model, listType, styleType, index) {
25270
26049
  };
25271
26050
 
25272
26051
 
26052
+ /***/ }),
26053
+
26054
+ /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformFraction.ts":
26055
+ /*!**********************************************************************************************!*\
26056
+ !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformFraction.ts ***!
26057
+ \**********************************************************************************************/
26058
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26059
+
26060
+ "use strict";
26061
+
26062
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26063
+ exports.transformFraction = void 0;
26064
+ var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26065
+ var FRACTIONS = {
26066
+ '1/2': '½',
26067
+ '1/4': '¼',
26068
+ '3/4': '¾',
26069
+ };
26070
+ /**
26071
+ * @internal
26072
+ */
26073
+ function transformFraction(previousSegment, paragraph, context) {
26074
+ var _a;
26075
+ var fraction = (_a = previousSegment.text.split(' ').pop()) === null || _a === void 0 ? void 0 : _a.trim();
26076
+ if (fraction && FRACTIONS[fraction]) {
26077
+ var textLength = previousSegment.text.length - 1;
26078
+ var textIndex = textLength - fraction.length;
26079
+ var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textLength);
26080
+ textSegment.text = FRACTIONS[fraction];
26081
+ context.canUndoByBackspace = true;
26082
+ return true;
26083
+ }
26084
+ return false;
26085
+ }
26086
+ exports.transformFraction = transformFraction;
26087
+
26088
+
26089
+ /***/ }),
26090
+
26091
+ /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformOrdinals.ts":
26092
+ /*!**********************************************************************************************!*\
26093
+ !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformOrdinals.ts ***!
26094
+ \**********************************************************************************************/
26095
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26096
+
26097
+ "use strict";
26098
+
26099
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26100
+ exports.transformOrdinals = void 0;
26101
+ var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26102
+ var getOrdinal = function (value) {
26103
+ var ORDINALS = {
26104
+ 1: 'st',
26105
+ 2: 'nd',
26106
+ 3: 'rd',
26107
+ };
26108
+ return ORDINALS[value] || 'th';
26109
+ };
26110
+ /**
26111
+ * @internal
26112
+ */
26113
+ function transformOrdinals(previousSegment, paragraph, context) {
26114
+ var _a;
26115
+ var value = (_a = previousSegment.text.split(' ').pop()) === null || _a === void 0 ? void 0 : _a.trim();
26116
+ if (value) {
26117
+ var ordinal = value.substring(value.length - 2);
26118
+ var ordinalValue = parseInt(value);
26119
+ if (ordinalValue && getOrdinal(ordinalValue) === ordinal) {
26120
+ var ordinalSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - 3, previousSegment.text.length - 1);
26121
+ ordinalSegment.format.superOrSubScriptSequence = 'super';
26122
+ context.canUndoByBackspace = true;
26123
+ return true;
26124
+ }
26125
+ }
26126
+ return false;
26127
+ }
26128
+ exports.transformOrdinals = transformOrdinals;
26129
+
26130
+
25273
26131
  /***/ }),
25274
26132
 
25275
26133
  /***/ "./packages/roosterjs-content-model-plugins/lib/contextMenuBase/ContextMenuPluginBase.ts":
@@ -25364,6 +26222,103 @@ var ContextMenuPluginBase = /** @class */ (function () {
25364
26222
  exports.ContextMenuPluginBase = ContextMenuPluginBase;
25365
26223
 
25366
26224
 
26225
+ /***/ }),
26226
+
26227
+ /***/ "./packages/roosterjs-content-model-plugins/lib/customReplace/CustomReplacePlugin.ts":
26228
+ /*!*******************************************************************************************!*\
26229
+ !*** ./packages/roosterjs-content-model-plugins/lib/customReplace/CustomReplacePlugin.ts ***!
26230
+ \*******************************************************************************************/
26231
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26232
+
26233
+ "use strict";
26234
+
26235
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26236
+ exports.CustomReplacePlugin = void 0;
26237
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26238
+ /**
26239
+ * CustomReplacePlugin is a plugin that allows you to replace a string with another string in the editor.
26240
+ */
26241
+ var CustomReplacePlugin = /** @class */ (function () {
26242
+ /**
26243
+ * @param customReplacements Custom replacement rules.
26244
+ * Ex: [{ stringToReplace: ':)', replacementString: '🙂', replacementHandler: replaceEmojis }]
26245
+ */
26246
+ function CustomReplacePlugin(customReplacements) {
26247
+ this.customReplacements = customReplacements;
26248
+ this.editor = null;
26249
+ this.triggerKeys = [];
26250
+ }
26251
+ /**
26252
+ * Get name of this plugin
26253
+ */
26254
+ CustomReplacePlugin.prototype.getName = function () {
26255
+ return 'CustomReplace';
26256
+ };
26257
+ /**
26258
+ * The first method that editor will call to a plugin when editor is initializing.
26259
+ * It will pass in the editor instance, plugin should take this chance to save the
26260
+ * editor reference so that it can call to any editor method or format API later.
26261
+ * @param editor The editor object
26262
+ */
26263
+ CustomReplacePlugin.prototype.initialize = function (editor) {
26264
+ this.editor = editor;
26265
+ this.triggerKeys = this.customReplacements.map(function (replacement) {
26266
+ return replacement.stringToReplace.slice(-1);
26267
+ });
26268
+ };
26269
+ /**
26270
+ * The last method that editor will call to a plugin before it is disposed.
26271
+ * Plugin can take this chance to clear the reference to editor. After this method is
26272
+ * called, plugin should not call to any editor method since it will result in error.
26273
+ */
26274
+ CustomReplacePlugin.prototype.dispose = function () {
26275
+ this.editor = null;
26276
+ };
26277
+ /**
26278
+ * Core method for a plugin. Once an event happens in editor, editor will call this
26279
+ * method of each plugin to handle the event as long as the event is not handled
26280
+ * exclusively by another plugin.
26281
+ * @param event The event to handle:
26282
+ */
26283
+ CustomReplacePlugin.prototype.onPluginEvent = function (event) {
26284
+ if (this.editor) {
26285
+ switch (event.eventType) {
26286
+ case 'input':
26287
+ this.handleEditorInputEvent(this.editor, event);
26288
+ break;
26289
+ }
26290
+ }
26291
+ };
26292
+ CustomReplacePlugin.prototype.handleEditorInputEvent = function (editor, event) {
26293
+ var _this = this;
26294
+ var rawEvent = event.rawEvent;
26295
+ var selection = editor.getDOMSelection();
26296
+ var key = rawEvent.data;
26297
+ if (this.customReplacements.length > 0 &&
26298
+ rawEvent.inputType === 'insertText' &&
26299
+ selection &&
26300
+ selection.type === 'range' &&
26301
+ selection.range.collapsed &&
26302
+ key &&
26303
+ this.triggerKeys.indexOf(key) > -1) {
26304
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (_model, previousSegment, paragraph, _markerFormat, context) {
26305
+ var replaced = _this.customReplacements.some(function (_a) {
26306
+ var stringToReplace = _a.stringToReplace, replacementString = _a.replacementString, replacementHandler = _a.replacementHandler;
26307
+ return replacementHandler(previousSegment, stringToReplace, replacementString, paragraph);
26308
+ });
26309
+ if (replaced) {
26310
+ context.canUndoByBackspace = true;
26311
+ return true;
26312
+ }
26313
+ return false;
26314
+ });
26315
+ }
26316
+ };
26317
+ return CustomReplacePlugin;
26318
+ }());
26319
+ exports.CustomReplacePlugin = CustomReplacePlugin;
26320
+
26321
+
25367
26322
  /***/ }),
25368
26323
 
25369
26324
  /***/ "./packages/roosterjs-content-model-plugins/lib/edit/EditPlugin.ts":
@@ -25448,11 +26403,18 @@ var EditPlugin = /** @class */ (function () {
25448
26403
  if (!rawEvent.defaultPrevented && !event.handledByEditFeature) {
25449
26404
  switch (rawEvent.key) {
25450
26405
  case 'Backspace':
25451
- case 'Delete':
25452
26406
  // Use our API to handle BACKSPACE/DELETE key.
25453
26407
  // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache
25454
26408
  (0, keyboardDelete_1.keyboardDelete)(editor, rawEvent);
25455
26409
  break;
26410
+ case 'Delete':
26411
+ // Use our API to handle BACKSPACE/DELETE key.
26412
+ // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache
26413
+ // And leave it to browser when shift key is pressed so that browser will trigger cut event
26414
+ if (!event.rawEvent.shiftKey) {
26415
+ (0, keyboardDelete_1.keyboardDelete)(editor, rawEvent);
26416
+ }
26417
+ break;
25456
26418
  case 'Tab':
25457
26419
  (0, keyboardTab_1.keyboardTab)(editor, rawEvent);
25458
26420
  break;
@@ -25469,6 +26431,8 @@ var EditPlugin = /** @class */ (function () {
25469
26431
  }
25470
26432
  };
25471
26433
  EditPlugin.prototype.handleBeforeInputEvent = function (editor, rawEvent) {
26434
+ var _this = this;
26435
+ var _a, _b;
25472
26436
  // Some Android IMEs doesn't fire correct keydown event for BACKSPACE/DELETE key
25473
26437
  // Here we translate input event to BACKSPACE/DELETE keydown event to be compatible with existing logic
25474
26438
  if (!this.shouldHandleNextInputEvent ||
@@ -25496,6 +26460,15 @@ var EditPlugin = /** @class */ (function () {
25496
26460
  }
25497
26461
  if (handled) {
25498
26462
  rawEvent.preventDefault();
26463
+ // Restore the selection to avoid the cursor jump issue
26464
+ // See: https://issues.chromium.org/issues/330596261
26465
+ var selection_1 = editor.getDOMSelection();
26466
+ var doc = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDocument();
26467
+ (_b = doc === null || doc === void 0 ? void 0 : doc.defaultView) === null || _b === void 0 ? void 0 : _b.requestAnimationFrame(function () {
26468
+ if (_this.editor) {
26469
+ _this.editor.setDOMSelection(selection_1);
26470
+ }
26471
+ });
25499
26472
  }
25500
26473
  };
25501
26474
  return EditPlugin;
@@ -25744,15 +26717,21 @@ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-mo
25744
26717
  * @internal
25745
26718
  */
25746
26719
  var deleteList = function (context) {
26720
+ if (context.deleteResult != 'notDeleted') {
26721
+ return;
26722
+ }
25747
26723
  var _a = context.insertPoint, paragraph = _a.paragraph, marker = _a.marker, path = _a.path;
25748
- if (context.deleteResult == 'nothingToDelete' || context.deleteResult == 'notDeleted') {
25749
- var index = (0, roosterjs_content_model_dom_1.getClosestAncestorBlockGroupIndex)(path, ['ListItem', 'TableCell']);
26724
+ if (paragraph.segments[0] == marker) {
26725
+ var index = (0, roosterjs_content_model_dom_1.getClosestAncestorBlockGroupIndex)(path, ['ListItem'], ['TableCell', 'FormatContainer']);
25750
26726
  var item = path[index];
25751
- if (item &&
25752
- index >= 0 &&
25753
- paragraph.segments[0] == marker &&
25754
- item.blockGroupType == 'ListItem') {
25755
- item.levels = [];
26727
+ var lastLevel = item === null || item === void 0 ? void 0 : item.levels[item.levels.length - 1];
26728
+ if (lastLevel && (item === null || item === void 0 ? void 0 : item.blocks[0]) == paragraph) {
26729
+ if (lastLevel.format.displayForDummyItem == 'block') {
26730
+ item.levels.pop();
26731
+ }
26732
+ else {
26733
+ lastLevel.format.displayForDummyItem = 'block';
26734
+ }
25756
26735
  context.deleteResult = 'range';
25757
26736
  }
25758
26737
  }
@@ -26021,6 +27000,7 @@ exports.shouldDeleteAllSegmentsBefore = shouldDeleteAllSegmentsBefore;
26021
27000
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26022
27001
  exports.handleEnterOnList = void 0;
26023
27002
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
27003
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26024
27004
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26025
27005
  /**
26026
27006
  * @internal
@@ -26067,7 +27047,12 @@ var handleEnterOnList = function (context) {
26067
27047
  listItem_1.levels.pop();
26068
27048
  }
26069
27049
  else {
26070
- createNewListItem(context, listItem_1, listParent);
27050
+ var newListItem = createNewListItem(context, listItem_1, listParent);
27051
+ if (context.formatContext) {
27052
+ context.formatContext.announceData = (0, roosterjs_content_model_api_1.getListAnnounceData)((0, tslib_1.__spreadArray)([
27053
+ newListItem
27054
+ ], (0, tslib_1.__read)(path.slice(index + 1)), false));
27055
+ }
26071
27056
  }
26072
27057
  }
26073
27058
  rawEvent === null || rawEvent === void 0 ? void 0 : rawEvent.preventDefault();
@@ -26093,10 +27078,11 @@ var createNewListItem = function (context, listItem, listParent) {
26093
27078
  insertPoint.paragraph = newParagraph;
26094
27079
  context.lastParagraph = newParagraph;
26095
27080
  listParent.blocks.splice(listIndex + 1, 0, newListItem);
27081
+ return newListItem;
26096
27082
  };
26097
27083
  var createNewListLevel = function (listItem) {
26098
27084
  return listItem.levels.map(function (level) {
26099
- return (0, roosterjs_content_model_dom_1.createListLevel)(level.listType, (0, tslib_1.__assign)((0, tslib_1.__assign)({}, level.format), { startNumberOverride: undefined }), level.dataset);
27085
+ return (0, roosterjs_content_model_dom_1.createListLevel)(level.listType, (0, tslib_1.__assign)((0, tslib_1.__assign)({}, level.format), { startNumberOverride: undefined, displayForDummyItem: undefined }), level.dataset);
26100
27086
  });
26101
27087
  };
26102
27088
  var createNewParagraph = function (insertPoint) {
@@ -26127,10 +27113,10 @@ var createNewParagraph = function (insertPoint) {
26127
27113
 
26128
27114
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26129
27115
  exports.keyboardDelete = void 0;
26130
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26131
27116
  var deleteAllSegmentBefore_1 = __webpack_require__(/*! ./deleteSteps/deleteAllSegmentBefore */ "./packages/roosterjs-content-model-plugins/lib/edit/deleteSteps/deleteAllSegmentBefore.ts");
26132
27117
  var deleteEmptyQuote_1 = __webpack_require__(/*! ./deleteSteps/deleteEmptyQuote */ "./packages/roosterjs-content-model-plugins/lib/edit/deleteSteps/deleteEmptyQuote.ts");
26133
27118
  var deleteList_1 = __webpack_require__(/*! ./deleteSteps/deleteList */ "./packages/roosterjs-content-model-plugins/lib/edit/deleteSteps/deleteList.ts");
27119
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26134
27120
  var handleKeyboardEventCommon_1 = __webpack_require__(/*! ./handleKeyboardEventCommon */ "./packages/roosterjs-content-model-plugins/lib/edit/handleKeyboardEventCommon.ts");
26135
27121
  var deleteWordSelection_1 = __webpack_require__(/*! ./deleteSteps/deleteWordSelection */ "./packages/roosterjs-content-model-plugins/lib/edit/deleteSteps/deleteWordSelection.ts");
26136
27122
  var deleteCollapsedSelection_1 = __webpack_require__(/*! ./deleteSteps/deleteCollapsedSelection */ "./packages/roosterjs-content-model-plugins/lib/edit/deleteSteps/deleteCollapsedSelection.ts");
@@ -26174,8 +27160,8 @@ function getDeleteSteps(rawEvent, isMac) {
26174
27160
  return [
26175
27161
  deleteAllSegmentBeforeStep,
26176
27162
  deleteWordSelection,
27163
+ isForward ? null : deleteList_1.deleteList,
26177
27164
  deleteCollapsedSelection,
26178
- deleteList_1.deleteList,
26179
27165
  deleteQuote,
26180
27166
  ];
26181
27167
  }
@@ -26288,39 +27274,55 @@ exports.keyboardTab = void 0;
26288
27274
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26289
27275
  var handleTabOnList_1 = __webpack_require__(/*! ./tabUtils/handleTabOnList */ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnList.ts");
26290
27276
  var handleTabOnParagraph_1 = __webpack_require__(/*! ./tabUtils/handleTabOnParagraph */ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnParagraph.ts");
27277
+ var handleTabOnTable_1 = __webpack_require__(/*! ./tabUtils/handleTabOnTable */ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTable.ts");
27278
+ var handleTabOnTableCell_1 = __webpack_require__(/*! ./tabUtils/handleTabOnTableCell */ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTableCell.ts");
26291
27279
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26292
27280
  /**
26293
27281
  * @internal
26294
27282
  */
26295
27283
  function keyboardTab(editor, rawEvent) {
26296
27284
  var selection = editor.getDOMSelection();
26297
- if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'range') {
26298
- editor.formatContentModel(function (model) {
26299
- return handleTab(model, rawEvent);
26300
- }, {
26301
- apiName: 'handleTabKey',
26302
- });
26303
- return true;
27285
+ switch (selection === null || selection === void 0 ? void 0 : selection.type) {
27286
+ case 'range':
27287
+ editor.formatContentModel(function (model, context) {
27288
+ return handleTab(model, rawEvent, context);
27289
+ }, {
27290
+ apiName: 'handleTabKey',
27291
+ });
27292
+ return true;
27293
+ case 'table':
27294
+ editor.formatContentModel(function (model) {
27295
+ return (0, handleTabOnTable_1.handleTabOnTable)(model, rawEvent);
27296
+ }, {
27297
+ apiName: 'handleTabKey',
27298
+ });
27299
+ return true;
26304
27300
  }
26305
27301
  }
26306
27302
  exports.keyboardTab = keyboardTab;
26307
27303
  /**
26308
27304
  * If multiple blocks are selected, indent or outdent the selected blocks with setModelIndentation.
26309
- * If only one block is selected, call handleTabOnParagraph or handleTabOnList to handle the tab key.
27305
+ * If only one block is selected:
27306
+ * - If it is a table cell, call handleTabOnTableCell to handle the tab key.
27307
+ * - If it is a paragraph, call handleTabOnParagraph to handle the tab key.
27308
+ * - If it is a list item, call handleTabOnList to handle the tab key.
26310
27309
  */
26311
- function handleTab(model, rawEvent) {
26312
- var blocks = (0, roosterjs_content_model_dom_1.getOperationalBlocks)(model, ['ListItem'], ['TableCell']);
27310
+ function handleTab(model, rawEvent, context) {
27311
+ var blocks = (0, roosterjs_content_model_dom_1.getOperationalBlocks)(model, ['ListItem', 'TableCell'], []);
26313
27312
  var block = blocks.length > 0 ? blocks[0].block : undefined;
26314
27313
  if (blocks.length > 1) {
26315
27314
  (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
26316
27315
  rawEvent.preventDefault();
26317
27316
  return true;
26318
27317
  }
27318
+ else if ((0, roosterjs_content_model_dom_1.isBlockGroupOfType)(block, 'TableCell')) {
27319
+ return (0, handleTabOnTableCell_1.handleTabOnTableCell)(model, block, rawEvent);
27320
+ }
26319
27321
  else if ((block === null || block === void 0 ? void 0 : block.blockType) === 'Paragraph') {
26320
- return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, block, rawEvent);
27322
+ return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, block, rawEvent, context);
26321
27323
  }
26322
27324
  else if ((0, roosterjs_content_model_dom_1.isBlockGroupOfType)(block, 'ListItem')) {
26323
- return (0, handleTabOnList_1.handleTabOnList)(model, block, rawEvent);
27325
+ return (0, handleTabOnList_1.handleTabOnList)(model, block, rawEvent, context);
26324
27326
  }
26325
27327
  return false;
26326
27328
  }
@@ -26345,15 +27347,15 @@ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-mo
26345
27347
  * 2. Otherwise call handleTabOnParagraph.
26346
27348
  * @internal
26347
27349
  */
26348
- function handleTabOnList(model, listItem, rawEvent) {
27350
+ function handleTabOnList(model, listItem, rawEvent, context) {
26349
27351
  var selectedParagraph = findSelectedParagraph(listItem);
26350
27352
  if (!isMarkerAtStartOfBlock(listItem) &&
26351
27353
  selectedParagraph.length == 1 &&
26352
27354
  selectedParagraph[0].blockType === 'Paragraph') {
26353
- return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, selectedParagraph[0], rawEvent);
27355
+ return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, selectedParagraph[0], rawEvent, context);
26354
27356
  }
26355
27357
  else {
26356
- (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
27358
+ (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent', undefined /*length*/, context);
26357
27359
  rawEvent.preventDefault();
26358
27360
  return true;
26359
27361
  }
@@ -26401,7 +27403,7 @@ var space = ' ';
26401
27403
  * 4. When the selection is not collapsed, replace the selected range with a 4 space.
26402
27404
  * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to outdent the whole paragraph
26403
27405
  */
26404
- function handleTabOnParagraph(model, paragraph, rawEvent) {
27406
+ function handleTabOnParagraph(model, paragraph, rawEvent, context) {
26405
27407
  var selectedSegments = paragraph.segments.filter(function (segment) { return segment.isSelected; });
26406
27408
  var isCollapsed = selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';
26407
27409
  var isAllSelected = paragraph.segments.every(function (segment) { return segment.isSelected; });
@@ -26413,7 +27415,7 @@ function handleTabOnParagraph(model, paragraph, rawEvent) {
26413
27415
  (isRtl && (!marginRight || marginRight == '0px')))) {
26414
27416
  return false;
26415
27417
  }
26416
- (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
27418
+ (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent', undefined /*length*/, context);
26417
27419
  }
26418
27420
  else {
26419
27421
  if (!isCollapsed) {
@@ -26468,6 +27470,91 @@ function handleTabOnParagraph(model, paragraph, rawEvent) {
26468
27470
  exports.handleTabOnParagraph = handleTabOnParagraph;
26469
27471
 
26470
27472
 
27473
+ /***/ }),
27474
+
27475
+ /***/ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTable.ts":
27476
+ /*!****************************************************************************************!*\
27477
+ !*** ./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTable.ts ***!
27478
+ \****************************************************************************************/
27479
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
27480
+
27481
+ "use strict";
27482
+
27483
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
27484
+ exports.handleTabOnTable = void 0;
27485
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
27486
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
27487
+ /**
27488
+ * When the whole table is selected, indent or outdent the whole table with setModelIndentation.
27489
+ * @internal
27490
+ */
27491
+ function handleTabOnTable(model, rawEvent) {
27492
+ var tableModel = (0, roosterjs_content_model_dom_1.getFirstSelectedTable)(model)[0];
27493
+ if (tableModel && isWholeTableSelected(tableModel)) {
27494
+ (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
27495
+ rawEvent.preventDefault();
27496
+ return true;
27497
+ }
27498
+ return false;
27499
+ }
27500
+ exports.handleTabOnTable = handleTabOnTable;
27501
+ function isWholeTableSelected(tableModel) {
27502
+ var _a, _b, _c, _d;
27503
+ return (((_b = (_a = tableModel.rows[0]) === null || _a === void 0 ? void 0 : _a.cells[0]) === null || _b === void 0 ? void 0 : _b.isSelected) &&
27504
+ ((_d = (_c = tableModel.rows[tableModel.rows.length - 1]) === null || _c === void 0 ? void 0 : _c.cells[tableModel.widths.length - 1]) === null || _d === void 0 ? void 0 : _d.isSelected));
27505
+ }
27506
+
27507
+
27508
+ /***/ }),
27509
+
27510
+ /***/ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTableCell.ts":
27511
+ /*!********************************************************************************************!*\
27512
+ !*** ./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTableCell.ts ***!
27513
+ \********************************************************************************************/
27514
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
27515
+
27516
+ "use strict";
27517
+
27518
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
27519
+ exports.handleTabOnTableCell = void 0;
27520
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
27521
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
27522
+ /**
27523
+ * When the cursor is on the last cell of a table, add new row and focus first new cell.
27524
+ * @internal
27525
+ */
27526
+ function handleTabOnTableCell(model, cell, rawEvent) {
27527
+ var _a, _b, _c;
27528
+ var tableModel = (0, roosterjs_content_model_dom_1.getFirstSelectedTable)(model)[0];
27529
+ // Check if cursor is on last cell of the table
27530
+ if (!rawEvent.shiftKey &&
27531
+ tableModel &&
27532
+ ((_a = tableModel.rows[tableModel.rows.length - 1]) === null || _a === void 0 ? void 0 : _a.cells[tableModel.widths.length - 1]) === cell) {
27533
+ (0, roosterjs_content_model_api_1.insertTableRow)(tableModel, 'insertBelow');
27534
+ // Clear Table selection
27535
+ (0, roosterjs_content_model_api_1.clearSelectedCells)(tableModel, {
27536
+ firstRow: tableModel.rows.length - 1,
27537
+ firstColumn: 0,
27538
+ lastRow: tableModel.rows.length - 1,
27539
+ lastColumn: tableModel.widths.length - 1,
27540
+ });
27541
+ (0, roosterjs_content_model_dom_1.normalizeTable)(tableModel, model.format);
27542
+ // Add selection marker to the first cell of the new row
27543
+ var markerParagraph = (_c = (_b = tableModel.rows[tableModel.rows.length - 1]) === null || _b === void 0 ? void 0 : _b.cells[0]) === null || _c === void 0 ? void 0 : _c.blocks[0];
27544
+ if (markerParagraph.blockType == 'Paragraph') {
27545
+ var marker = (0, roosterjs_content_model_dom_1.createSelectionMarker)(model.format);
27546
+ markerParagraph.segments.unshift(marker);
27547
+ (0, roosterjs_content_model_dom_1.setParagraphNotImplicit)(markerParagraph);
27548
+ (0, roosterjs_content_model_dom_1.setSelection)(tableModel.rows[tableModel.rows.length - 1].cells[0], marker);
27549
+ }
27550
+ rawEvent.preventDefault();
27551
+ return true;
27552
+ }
27553
+ return false;
27554
+ }
27555
+ exports.handleTabOnTableCell = handleTabOnTableCell;
27556
+
27557
+
26471
27558
  /***/ }),
26472
27559
 
26473
27560
  /***/ "./packages/roosterjs-content-model-plugins/lib/edit/utils/getLeafSiblingBlock.ts":
@@ -26554,6 +27641,157 @@ function getLeafSiblingBlock(path, block, isNext) {
26554
27641
  exports.getLeafSiblingBlock = getLeafSiblingBlock;
26555
27642
 
26556
27643
 
27644
+ /***/ }),
27645
+
27646
+ /***/ "./packages/roosterjs-content-model-plugins/lib/hyperlink/HyperlinkPlugin.ts":
27647
+ /*!***********************************************************************************!*\
27648
+ !*** ./packages/roosterjs-content-model-plugins/lib/hyperlink/HyperlinkPlugin.ts ***!
27649
+ \***********************************************************************************/
27650
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
27651
+
27652
+ "use strict";
27653
+
27654
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
27655
+ exports.HyperlinkPlugin = void 0;
27656
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
27657
+ var defaultToolTipCallback = function (url) { return url; };
27658
+ /**
27659
+ * Hyperlink plugin does the following jobs for a hyperlink in editor:
27660
+ * 1. When hover on a link, show a tool tip
27661
+ * 2. When Ctrl+Click on a link, open a new window with the link
27662
+ * 3. When type directly on a link whose text matches its link url, update the link url with the link text
27663
+ */
27664
+ var HyperlinkPlugin = /** @class */ (function () {
27665
+ /**
27666
+ * Create a new instance of HyperLink class
27667
+ * @param tooltip Tooltip to show when mouse hover over a link
27668
+ * Default value is to return the href itself. If null, there will be no tooltip text.
27669
+ * @param target (Optional) Target window name for hyperlink. If null, will use "_blank"
27670
+ * @param onLinkClick (Optional) Open link callback (return false to use default behavior)
27671
+ */
27672
+ function HyperlinkPlugin(tooltip, target, onLinkClick) {
27673
+ var _this = this;
27674
+ if (tooltip === void 0) { tooltip = defaultToolTipCallback; }
27675
+ this.tooltip = tooltip;
27676
+ this.target = target;
27677
+ this.onLinkClick = onLinkClick;
27678
+ this.editor = null;
27679
+ this.domHelper = null;
27680
+ this.isMac = false;
27681
+ this.disposer = null;
27682
+ this.currentNode = null;
27683
+ this.currentLink = null;
27684
+ this.onMouse = function (e) {
27685
+ _this.runWithHyperlink(e.target, function (href, a) {
27686
+ var _a;
27687
+ var tooltip = e.type == 'mouseover'
27688
+ ? typeof _this.tooltip == 'function'
27689
+ ? _this.tooltip(href, a)
27690
+ : _this.tooltip
27691
+ : null;
27692
+ (_a = _this.domHelper) === null || _a === void 0 ? void 0 : _a.setDomAttribute('title', tooltip);
27693
+ });
27694
+ };
27695
+ }
27696
+ /**
27697
+ * Get a friendly name of this plugin
27698
+ */
27699
+ HyperlinkPlugin.prototype.getName = function () {
27700
+ return 'Hyperlink';
27701
+ };
27702
+ /**
27703
+ * Initialize this plugin
27704
+ * @param editor The editor instance
27705
+ */
27706
+ HyperlinkPlugin.prototype.initialize = function (editor) {
27707
+ this.editor = editor;
27708
+ this.domHelper = editor.getDOMHelper();
27709
+ this.isMac = !!editor.getEnvironment().isMac;
27710
+ this.disposer = editor.attachDomEvent({
27711
+ mouseover: { beforeDispatch: this.onMouse },
27712
+ mouseout: { beforeDispatch: this.onMouse },
27713
+ });
27714
+ };
27715
+ /**
27716
+ * Dispose this plugin
27717
+ */
27718
+ HyperlinkPlugin.prototype.dispose = function () {
27719
+ if (this.disposer) {
27720
+ this.disposer();
27721
+ this.disposer = null;
27722
+ }
27723
+ this.currentNode = null;
27724
+ this.currentLink = null;
27725
+ this.editor = null;
27726
+ };
27727
+ /**
27728
+ * Handle events triggered from editor
27729
+ * @param event PluginEvent object
27730
+ */
27731
+ HyperlinkPlugin.prototype.onPluginEvent = function (event) {
27732
+ var _this = this;
27733
+ var _a, _b;
27734
+ var matchedLink;
27735
+ if (event.eventType == 'keyDown') {
27736
+ var selection = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDOMSelection();
27737
+ var node_1 = (selection === null || selection === void 0 ? void 0 : selection.type) == 'range' ? selection.range.commonAncestorContainer : null;
27738
+ if (node_1 && node_1 != this.currentNode) {
27739
+ this.currentNode = node_1;
27740
+ this.currentLink = null;
27741
+ this.runWithHyperlink(node_1, function (href, a) {
27742
+ if (node_1.textContent &&
27743
+ (matchedLink = (0, roosterjs_content_model_api_1.matchLink)(node_1.textContent)) &&
27744
+ matchedLink.normalizedUrl == href) {
27745
+ _this.currentLink = a;
27746
+ }
27747
+ });
27748
+ }
27749
+ }
27750
+ else if (event.eventType == 'keyUp') {
27751
+ var selection = (_b = this.editor) === null || _b === void 0 ? void 0 : _b.getDOMSelection();
27752
+ var node = (selection === null || selection === void 0 ? void 0 : selection.type) == 'range' ? selection.range.commonAncestorContainer : null;
27753
+ if (node &&
27754
+ node == this.currentNode &&
27755
+ this.currentLink &&
27756
+ this.currentLink.contains(node) &&
27757
+ node.textContent &&
27758
+ (matchedLink = (0, roosterjs_content_model_api_1.matchLink)(node.textContent))) {
27759
+ this.currentLink.setAttribute('href', matchedLink.normalizedUrl);
27760
+ }
27761
+ }
27762
+ else if (event.eventType == 'mouseUp' && event.isClicking) {
27763
+ this.runWithHyperlink(event.rawEvent.target, function (href, anchor) {
27764
+ var _a, _b;
27765
+ if (!((_a = _this.onLinkClick) === null || _a === void 0 ? void 0 : _a.call(_this, anchor, event.rawEvent)) &&
27766
+ _this.isCtrlOrMetaPressed(event.rawEvent) &&
27767
+ event.rawEvent.button === 0) {
27768
+ event.rawEvent.preventDefault();
27769
+ var target = _this.target || '_blank';
27770
+ var window_1 = (_b = _this.editor) === null || _b === void 0 ? void 0 : _b.getDocument().defaultView;
27771
+ try {
27772
+ window_1 === null || window_1 === void 0 ? void 0 : window_1.open(href, target);
27773
+ }
27774
+ catch (_c) { }
27775
+ }
27776
+ });
27777
+ }
27778
+ };
27779
+ HyperlinkPlugin.prototype.runWithHyperlink = function (node, callback) {
27780
+ var _a;
27781
+ var a = (_a = this.domHelper) === null || _a === void 0 ? void 0 : _a.findClosestElementAncestor(node, 'a[href]');
27782
+ var href = a === null || a === void 0 ? void 0 : a.getAttribute('href');
27783
+ if (href && a) {
27784
+ callback(href, a);
27785
+ }
27786
+ };
27787
+ HyperlinkPlugin.prototype.isCtrlOrMetaPressed = function (event) {
27788
+ return this.isMac ? event.metaKey : event.ctrlKey;
27789
+ };
27790
+ return HyperlinkPlugin;
27791
+ }());
27792
+ exports.HyperlinkPlugin = HyperlinkPlugin;
27793
+
27794
+
26557
27795
  /***/ }),
26558
27796
 
26559
27797
  /***/ "./packages/roosterjs-content-model-plugins/lib/index.ts":
@@ -26565,7 +27803,7 @@ exports.getLeafSiblingBlock = getLeafSiblingBlock;
26565
27803
  "use strict";
26566
27804
 
26567
27805
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26568
- exports.MarkdownPlugin = exports.WatermarkPlugin = exports.ContextMenuPluginBase = exports.ShortcutPlugin = exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoMacOS = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = exports.AutoFormatPlugin = exports.EditPlugin = exports.PastePlugin = exports.TableEditPlugin = void 0;
27806
+ exports.getDOMInsertPointRect = exports.CustomReplacePlugin = exports.PickerPlugin = exports.HyperlinkPlugin = exports.MarkdownPlugin = exports.WatermarkPlugin = exports.ContextMenuPluginBase = exports.ShortcutPlugin = exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoMacOS = exports.ShortcutRedoAlt = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = exports.AutoFormatPlugin = exports.EditPlugin = exports.PastePlugin = exports.TableEditPlugin = void 0;
26569
27807
  var TableEditPlugin_1 = __webpack_require__(/*! ./tableEdit/TableEditPlugin */ "./packages/roosterjs-content-model-plugins/lib/tableEdit/TableEditPlugin.ts");
26570
27808
  Object.defineProperty(exports, "TableEditPlugin", ({ enumerable: true, get: function () { return TableEditPlugin_1.TableEditPlugin; } }));
26571
27809
  var PastePlugin_1 = __webpack_require__(/*! ./paste/PastePlugin */ "./packages/roosterjs-content-model-plugins/lib/paste/PastePlugin.ts");
@@ -26582,6 +27820,7 @@ Object.defineProperty(exports, "ShortcutClearFormat", ({ enumerable: true, get:
26582
27820
  Object.defineProperty(exports, "ShortcutUndo", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutUndo; } }));
26583
27821
  Object.defineProperty(exports, "ShortcutUndo2", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutUndo2; } }));
26584
27822
  Object.defineProperty(exports, "ShortcutRedo", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutRedo; } }));
27823
+ Object.defineProperty(exports, "ShortcutRedoAlt", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutRedoAlt; } }));
26585
27824
  Object.defineProperty(exports, "ShortcutRedoMacOS", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutRedoMacOS; } }));
26586
27825
  Object.defineProperty(exports, "ShortcutBullet", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutBullet; } }));
26587
27826
  Object.defineProperty(exports, "ShortcutNumbering", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutNumbering; } }));
@@ -26597,6 +27836,14 @@ var WatermarkPlugin_1 = __webpack_require__(/*! ./watermark/WatermarkPlugin */ "
26597
27836
  Object.defineProperty(exports, "WatermarkPlugin", ({ enumerable: true, get: function () { return WatermarkPlugin_1.WatermarkPlugin; } }));
26598
27837
  var MarkdownPlugin_1 = __webpack_require__(/*! ./markdown/MarkdownPlugin */ "./packages/roosterjs-content-model-plugins/lib/markdown/MarkdownPlugin.ts");
26599
27838
  Object.defineProperty(exports, "MarkdownPlugin", ({ enumerable: true, get: function () { return MarkdownPlugin_1.MarkdownPlugin; } }));
27839
+ var HyperlinkPlugin_1 = __webpack_require__(/*! ./hyperlink/HyperlinkPlugin */ "./packages/roosterjs-content-model-plugins/lib/hyperlink/HyperlinkPlugin.ts");
27840
+ Object.defineProperty(exports, "HyperlinkPlugin", ({ enumerable: true, get: function () { return HyperlinkPlugin_1.HyperlinkPlugin; } }));
27841
+ var PickerPlugin_1 = __webpack_require__(/*! ./picker/PickerPlugin */ "./packages/roosterjs-content-model-plugins/lib/picker/PickerPlugin.ts");
27842
+ Object.defineProperty(exports, "PickerPlugin", ({ enumerable: true, get: function () { return PickerPlugin_1.PickerPlugin; } }));
27843
+ var CustomReplacePlugin_1 = __webpack_require__(/*! ./customReplace/CustomReplacePlugin */ "./packages/roosterjs-content-model-plugins/lib/customReplace/CustomReplacePlugin.ts");
27844
+ Object.defineProperty(exports, "CustomReplacePlugin", ({ enumerable: true, get: function () { return CustomReplacePlugin_1.CustomReplacePlugin; } }));
27845
+ var getDOMInsertPointRect_1 = __webpack_require__(/*! ./pluginUtils/Rect/getDOMInsertPointRect */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getDOMInsertPointRect.ts");
27846
+ Object.defineProperty(exports, "getDOMInsertPointRect", ({ enumerable: true, get: function () { return getDOMInsertPointRect_1.getDOMInsertPointRect; } }));
26600
27847
 
26601
27848
 
26602
27849
  /***/ }),
@@ -26626,9 +27873,10 @@ var DefaultOptions = {
26626
27873
  var MarkdownPlugin = /** @class */ (function () {
26627
27874
  /**
26628
27875
  * @param options An optional parameter that takes in an object of type MarkdownOptions, which includes the following properties:
26629
- * - strikethrough: If true text between ~ will receive strikethrough format. Defaults to true.
26630
- * - bold: If true text between * will receive bold format. Defaults to true.
26631
- * - italic: If true text between _ will receive italic format. Defaults to true.
27876
+ * - strikethrough: If true text between ~ will receive strikethrough format. Defaults to false.
27877
+ * - bold: If true text between * will receive bold format. Defaults to false.
27878
+ * - italic: If true text between _ will receive italic format. Defaults to false.
27879
+ * - codeFormat: If provided, text between ` will receive code format. Defaults to undefined.
26632
27880
  */
26633
27881
  function MarkdownPlugin(options) {
26634
27882
  if (options === void 0) { options = DefaultOptions; }
@@ -26637,6 +27885,7 @@ var MarkdownPlugin = /** @class */ (function () {
26637
27885
  this.shouldBold = false;
26638
27886
  this.shouldItalic = false;
26639
27887
  this.shouldStrikethrough = false;
27888
+ this.shouldCode = false;
26640
27889
  this.lastKeyTyped = null;
26641
27890
  }
26642
27891
  /**
@@ -26660,10 +27909,8 @@ var MarkdownPlugin = /** @class */ (function () {
26660
27909
  * called, plugin should not call to any editor method since it will result in error.
26661
27910
  */
26662
27911
  MarkdownPlugin.prototype.dispose = function () {
26663
- this.editor = null;
26664
- this.shouldBold = false;
26665
- this.shouldItalic = false;
26666
- this.shouldStrikethrough = false;
27912
+ this.editor = null;
27913
+ this.disableAllFeatures();
26667
27914
  this.lastKeyTyped = null;
26668
27915
  };
26669
27916
  /**
@@ -26729,6 +27976,17 @@ var MarkdownPlugin = /** @class */ (function () {
26729
27976
  }
26730
27977
  }
26731
27978
  break;
27979
+ case '`':
27980
+ if (this.options.codeFormat) {
27981
+ if (this.shouldCode) {
27982
+ (0, setFormat_1.setFormat)(editor, '`', {} /* format */, this.options.codeFormat);
27983
+ this.shouldCode = false;
27984
+ }
27985
+ else {
27986
+ this.shouldCode = true;
27987
+ }
27988
+ }
27989
+ break;
26732
27990
  }
26733
27991
  }
26734
27992
  };
@@ -26737,9 +27995,7 @@ var MarkdownPlugin = /** @class */ (function () {
26737
27995
  if (!event.handledByEditFeature && !rawEvent.defaultPrevented) {
26738
27996
  switch (rawEvent.key) {
26739
27997
  case 'Enter':
26740
- this.shouldBold = false;
26741
- this.shouldItalic = false;
26742
- this.shouldStrikethrough = false;
27998
+ this.disableAllFeatures();
26743
27999
  this.lastKeyTyped = null;
26744
28000
  break;
26745
28001
  case ' ':
@@ -26752,6 +28008,9 @@ var MarkdownPlugin = /** @class */ (function () {
26752
28008
  else if (this.lastKeyTyped === '_' && this.shouldItalic) {
26753
28009
  this.shouldItalic = false;
26754
28010
  }
28011
+ else if (this.lastKeyTyped === '`' && this.shouldCode) {
28012
+ this.shouldCode = false;
28013
+ }
26755
28014
  this.lastKeyTyped = null;
26756
28015
  break;
26757
28016
  default:
@@ -26771,16 +28030,23 @@ var MarkdownPlugin = /** @class */ (function () {
26771
28030
  else if (this.lastKeyTyped === '_' && this.shouldItalic) {
26772
28031
  this.shouldItalic = false;
26773
28032
  }
28033
+ else if (this.lastKeyTyped === '`' && this.shouldCode) {
28034
+ this.shouldCode = false;
28035
+ }
26774
28036
  this.lastKeyTyped = null;
26775
28037
  }
26776
28038
  };
26777
28039
  MarkdownPlugin.prototype.handleContentChangedEvent = function (event) {
26778
28040
  if (event.source == 'Format') {
26779
- this.shouldBold = false;
26780
- this.shouldItalic = false;
26781
- this.shouldStrikethrough = false;
28041
+ this.disableAllFeatures();
26782
28042
  }
26783
28043
  };
28044
+ MarkdownPlugin.prototype.disableAllFeatures = function () {
28045
+ this.shouldBold = false;
28046
+ this.shouldItalic = false;
28047
+ this.shouldStrikethrough = false;
28048
+ this.shouldCode = false;
28049
+ };
26784
28050
  return MarkdownPlugin;
26785
28051
  }());
26786
28052
  exports.MarkdownPlugin = MarkdownPlugin;
@@ -26799,40 +28065,32 @@ exports.MarkdownPlugin = MarkdownPlugin;
26799
28065
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26800
28066
  exports.setFormat = void 0;
26801
28067
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
26802
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
28068
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26803
28069
  var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26804
28070
  /**
26805
28071
  * @internal
26806
28072
  */
26807
- function setFormat(editor, character, format) {
26808
- editor.formatContentModel(function (model, context) {
26809
- var _a;
26810
- var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /*includeFormatHolder*/);
26811
- if (selectedSegmentsAndParagraphs.length > 0 && selectedSegmentsAndParagraphs[0][1]) {
26812
- var marker = selectedSegmentsAndParagraphs[0][0];
26813
- context.newPendingFormat = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, marker.format), { strikethrough: !!marker.format.strikethrough, italic: !!marker.format.italic, fontWeight: ((_a = marker.format) === null || _a === void 0 ? void 0 : _a.fontWeight) ? 'bold' : undefined });
26814
- var paragraph = selectedSegmentsAndParagraphs[0][1];
26815
- if (marker.segmentType == 'SelectionMarker') {
26816
- var markerIndex = paragraph.segments.indexOf(marker);
26817
- if (markerIndex > 0 && paragraph.segments[markerIndex - 1]) {
26818
- var segmentBeforeMarker = paragraph.segments[markerIndex - 1];
26819
- if (segmentBeforeMarker.segmentType == 'Text' &&
26820
- segmentBeforeMarker.text[segmentBeforeMarker.text.length - 1] == character) {
26821
- var textBeforeMarker = segmentBeforeMarker.text.slice(0, -1);
26822
- if (textBeforeMarker.indexOf(character) > -1) {
26823
- var lastCharIndex = segmentBeforeMarker.text.length;
26824
- var firstCharIndex = segmentBeforeMarker.text
26825
- .substring(0, lastCharIndex - 1)
26826
- .lastIndexOf(character);
26827
- var formattedText = (0, splitTextSegment_1.splitTextSegment)(segmentBeforeMarker, paragraph, firstCharIndex, lastCharIndex);
26828
- formattedText.text = formattedText.text
26829
- .replace(character, '')
26830
- .slice(0, -1);
26831
- formattedText.format = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, formattedText.format), format);
26832
- context.canUndoByBackspace = true;
26833
- return true;
26834
- }
28073
+ function setFormat(editor, character, format, codeFormat) {
28074
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (_model, previousSegment, paragraph, markerFormat, context) {
28075
+ if (previousSegment.text[previousSegment.text.length - 1] == character) {
28076
+ var textBeforeMarker = previousSegment.text.slice(0, -1);
28077
+ context.newPendingFormat = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, markerFormat), { strikethrough: !!markerFormat.strikethrough, italic: !!markerFormat.italic, fontWeight: (markerFormat === null || markerFormat === void 0 ? void 0 : markerFormat.fontWeight) ? 'bold' : undefined });
28078
+ if (textBeforeMarker.indexOf(character) > -1) {
28079
+ var lastCharIndex = previousSegment.text.length;
28080
+ var firstCharIndex = previousSegment.text
28081
+ .substring(0, lastCharIndex - 1)
28082
+ .lastIndexOf(character);
28083
+ if (lastCharIndex - firstCharIndex > 2) {
28084
+ var formattedText = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, firstCharIndex, lastCharIndex);
28085
+ formattedText.text = formattedText.text.replace(character, '').slice(0, -1);
28086
+ formattedText.format = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, formattedText.format), format);
28087
+ if (codeFormat) {
28088
+ formattedText.code = {
28089
+ format: codeFormat,
28090
+ };
26835
28091
  }
28092
+ context.canUndoByBackspace = true;
28093
+ return true;
26836
28094
  }
26837
28095
  }
26838
28096
  }
@@ -28210,6 +29468,343 @@ function setProcessor(domToModelOption, entry, processorOverride) {
28210
29468
  exports.setProcessor = setProcessor;
28211
29469
 
28212
29470
 
29471
+ /***/ }),
29472
+
29473
+ /***/ "./packages/roosterjs-content-model-plugins/lib/picker/PickerHelperImpl.ts":
29474
+ /*!*********************************************************************************!*\
29475
+ !*** ./packages/roosterjs-content-model-plugins/lib/picker/PickerHelperImpl.ts ***!
29476
+ \*********************************************************************************/
29477
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
29478
+
29479
+ "use strict";
29480
+
29481
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
29482
+ exports.PickerHelperImpl = void 0;
29483
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
29484
+ var getQueryString_1 = __webpack_require__(/*! ./getQueryString */ "./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts");
29485
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
29486
+ /**
29487
+ * @internal
29488
+ */
29489
+ var PickerHelperImpl = /** @class */ (function () {
29490
+ function PickerHelperImpl(editor, handler, triggerCharacter) {
29491
+ this.editor = editor;
29492
+ this.handler = handler;
29493
+ this.triggerCharacter = triggerCharacter;
29494
+ this.direction = null;
29495
+ }
29496
+ /**
29497
+ * Replace the query string with a given Content Model.
29498
+ * This is used for commit a change from picker and insert the committed content into editor.
29499
+ * @param model The Content Model to insert
29500
+ * @param options Options for formatting content model
29501
+ * @param canUndoByBackspace Whether this change can be undone using Backspace key
29502
+ */
29503
+ PickerHelperImpl.prototype.replaceQueryString = function (model, options, canUndoByBackspace) {
29504
+ var _this = this;
29505
+ this.editor.focus();
29506
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(this.editor, function (target, previousSegment, paragraph, _, context) {
29507
+ var potentialSegments = [];
29508
+ var queryString = (0, getQueryString_1.getQueryString)(_this.triggerCharacter, paragraph, previousSegment, potentialSegments);
29509
+ if (queryString) {
29510
+ potentialSegments.forEach(function (x) { return (x.isSelected = true); });
29511
+ (0, roosterjs_content_model_dom_1.mergeModel)(target, model, context);
29512
+ context.canUndoByBackspace = canUndoByBackspace;
29513
+ return true;
29514
+ }
29515
+ else {
29516
+ return false;
29517
+ }
29518
+ }, options);
29519
+ };
29520
+ /**
29521
+ * Notify Picker Plugin that picker is closed from the handler code, so picker plugin can quit the suggesting state
29522
+ */
29523
+ PickerHelperImpl.prototype.closePicker = function () {
29524
+ var _a, _b;
29525
+ if (this.direction) {
29526
+ this.direction = null;
29527
+ (_b = (_a = this.handler).onClosePicker) === null || _b === void 0 ? void 0 : _b.call(_a);
29528
+ }
29529
+ };
29530
+ return PickerHelperImpl;
29531
+ }());
29532
+ exports.PickerHelperImpl = PickerHelperImpl;
29533
+
29534
+
29535
+ /***/ }),
29536
+
29537
+ /***/ "./packages/roosterjs-content-model-plugins/lib/picker/PickerPlugin.ts":
29538
+ /*!*****************************************************************************!*\
29539
+ !*** ./packages/roosterjs-content-model-plugins/lib/picker/PickerPlugin.ts ***!
29540
+ \*****************************************************************************/
29541
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
29542
+
29543
+ "use strict";
29544
+
29545
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
29546
+ exports.PickerPlugin = void 0;
29547
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
29548
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
29549
+ var getQueryString_1 = __webpack_require__(/*! ./getQueryString */ "./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts");
29550
+ var PickerHelperImpl_1 = __webpack_require__(/*! ./PickerHelperImpl */ "./packages/roosterjs-content-model-plugins/lib/picker/PickerHelperImpl.ts");
29551
+ /**
29552
+ * PickerPlugin represents a plugin of editor which can handle picker related behaviors, including
29553
+ * - Show picker when special trigger key is pressed
29554
+ * - Hide picker
29555
+ * - Change selection in picker by Up/Down/Left/Right
29556
+ * - Apply selected item in picker
29557
+ *
29558
+ * PickerPlugin doesn't provide any UI, it just wraps related DOM events and invoke callback functions.
29559
+ */
29560
+ var PickerPlugin = /** @class */ (function () {
29561
+ /**
29562
+ * Construct a new instance of PickerPlugin class
29563
+ * @param triggerCharacter The character to trigger a picker to be shown
29564
+ * @param handler Picker handler for receiving picker state change events
29565
+ */
29566
+ function PickerPlugin(triggerCharacter, handler) {
29567
+ this.triggerCharacter = triggerCharacter;
29568
+ this.handler = handler;
29569
+ this.isMac = false;
29570
+ this.lastQueryString = '';
29571
+ this.helper = null;
29572
+ }
29573
+ /**
29574
+ * Get a friendly name
29575
+ */
29576
+ PickerPlugin.prototype.getName = function () {
29577
+ return 'Picker';
29578
+ };
29579
+ /**
29580
+ * Initialize this plugin. This should only be called from Editor
29581
+ * @param editor Editor instance
29582
+ */
29583
+ PickerPlugin.prototype.initialize = function (editor) {
29584
+ this.isMac = !!editor.getEnvironment().isMac;
29585
+ this.helper = new PickerHelperImpl_1.PickerHelperImpl(editor, this.handler, this.triggerCharacter);
29586
+ this.handler.onInitialize(this.helper);
29587
+ };
29588
+ /**
29589
+ * Dispose this plugin
29590
+ */
29591
+ PickerPlugin.prototype.dispose = function () {
29592
+ this.handler.onDispose();
29593
+ this.helper = null;
29594
+ };
29595
+ /**
29596
+ * Check if the plugin should handle the given event exclusively.
29597
+ * Handle an event exclusively means other plugin will not receive this event in
29598
+ * onPluginEvent method.
29599
+ * If two plugins will return true in willHandleEventExclusively() for the same event,
29600
+ * the final result depends on the order of the plugins are added into editor
29601
+ * @param event The event to check
29602
+ */
29603
+ PickerPlugin.prototype.willHandleEventExclusively = function (event) {
29604
+ var _a;
29605
+ return (!!((_a = this.helper) === null || _a === void 0 ? void 0 : _a.direction) &&
29606
+ event.eventType == 'keyDown' &&
29607
+ ((0, roosterjs_content_model_dom_1.isCursorMovingKey)(event.rawEvent) ||
29608
+ event.rawEvent.key == 'Enter' ||
29609
+ event.rawEvent.key == 'Tab' ||
29610
+ event.rawEvent.key == 'Escape'));
29611
+ };
29612
+ /**
29613
+ * Handle events triggered from editor
29614
+ * @param event PluginEvent object
29615
+ */
29616
+ PickerPlugin.prototype.onPluginEvent = function (event) {
29617
+ if (!this.helper) {
29618
+ return;
29619
+ }
29620
+ switch (event.eventType) {
29621
+ case 'contentChanged':
29622
+ if (this.helper.direction) {
29623
+ if (event.source == roosterjs_content_model_dom_1.ChangeSource.SetContent) {
29624
+ this.helper.closePicker();
29625
+ }
29626
+ else {
29627
+ this.onSuggestingInput(this.helper);
29628
+ }
29629
+ }
29630
+ break;
29631
+ case 'keyDown':
29632
+ if (this.helper.direction) {
29633
+ this.onSuggestingKeyDown(this.helper, event.rawEvent);
29634
+ }
29635
+ break;
29636
+ case 'input':
29637
+ if (this.helper.direction) {
29638
+ this.onSuggestingInput(this.helper);
29639
+ }
29640
+ else {
29641
+ this.onInput(this.helper, event.rawEvent);
29642
+ }
29643
+ break;
29644
+ case 'mouseUp':
29645
+ if (this.helper.direction) {
29646
+ this.helper.closePicker();
29647
+ }
29648
+ break;
29649
+ }
29650
+ };
29651
+ PickerPlugin.prototype.onSuggestingKeyDown = function (helper, event) {
29652
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
29653
+ switch (event.key) {
29654
+ case 'ArrowLeft':
29655
+ case 'ArrowRight':
29656
+ if (helper.direction == 'horizontal' || helper.direction == 'both') {
29657
+ var isIncrement = event.key == 'ArrowRight';
29658
+ if (helper.editor.getDOMHelper().isRightToLeft()) {
29659
+ isIncrement = !isIncrement;
29660
+ }
29661
+ (_b = (_a = this.handler).onSelectionChanged) === null || _b === void 0 ? void 0 : _b.call(_a, isIncrement ? 'next' : 'previous');
29662
+ }
29663
+ event.preventDefault();
29664
+ break;
29665
+ case 'ArrowUp':
29666
+ case 'ArrowDown':
29667
+ {
29668
+ var isIncrement = event.key == 'ArrowDown';
29669
+ if (helper.direction != 'horizontal') {
29670
+ (_d = (_c = this.handler).onSelectionChanged) === null || _d === void 0 ? void 0 : _d.call(_c, helper.direction == 'both'
29671
+ ? isIncrement
29672
+ ? 'nextRow'
29673
+ : 'previousRow'
29674
+ : isIncrement
29675
+ ? 'next'
29676
+ : 'previous');
29677
+ }
29678
+ }
29679
+ event.preventDefault();
29680
+ break;
29681
+ case 'PageUp':
29682
+ case 'PageDown':
29683
+ (_f = (_e = this.handler).onSelectionChanged) === null || _f === void 0 ? void 0 : _f.call(_e, event.key == 'PageDown' ? 'nextPage' : 'previousPage');
29684
+ event.preventDefault();
29685
+ break;
29686
+ case 'Home':
29687
+ case 'End':
29688
+ var hasCtrl = this.isMac ? event.metaKey : event.ctrlKey;
29689
+ (_h = (_g = this.handler).onSelectionChanged) === null || _h === void 0 ? void 0 : _h.call(_g, event.key == 'Home'
29690
+ ? hasCtrl
29691
+ ? 'first'
29692
+ : 'firstInRow'
29693
+ : hasCtrl
29694
+ ? 'last'
29695
+ : 'lastInRow');
29696
+ event.preventDefault();
29697
+ break;
29698
+ case 'Escape':
29699
+ helper.closePicker();
29700
+ event.preventDefault();
29701
+ break;
29702
+ case 'Enter':
29703
+ case 'Tab':
29704
+ (_k = (_j = this.handler).onSelect) === null || _k === void 0 ? void 0 : _k.call(_j);
29705
+ event.preventDefault();
29706
+ break;
29707
+ }
29708
+ };
29709
+ PickerPlugin.prototype.onSuggestingInput = function (helper) {
29710
+ var _this = this;
29711
+ if (!(0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(helper.editor, function (_, segment, paragraph) {
29712
+ var _a, _b;
29713
+ var newQueryString = (0, getQueryString_1.getQueryString)(_this.triggerCharacter, paragraph, segment).replace(/[\u0020\u00A0]/g, ' ');
29714
+ var oldQueryString = _this.lastQueryString;
29715
+ if (newQueryString &&
29716
+ ((newQueryString.length >= oldQueryString.length &&
29717
+ newQueryString.indexOf(oldQueryString) == 0) ||
29718
+ (newQueryString.length < oldQueryString.length &&
29719
+ oldQueryString.indexOf(newQueryString) == 0))) {
29720
+ _this.lastQueryString = newQueryString;
29721
+ (_b = (_a = _this.handler).onQueryStringChanged) === null || _b === void 0 ? void 0 : _b.call(_a, newQueryString);
29722
+ }
29723
+ else {
29724
+ helper.closePicker();
29725
+ }
29726
+ return false;
29727
+ })) {
29728
+ helper.closePicker();
29729
+ }
29730
+ };
29731
+ PickerPlugin.prototype.onInput = function (helper, event) {
29732
+ var _this = this;
29733
+ if (event.inputType == 'insertText' && event.data == this.triggerCharacter) {
29734
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(helper.editor, function (_, segment) {
29735
+ if (segment.text.endsWith(_this.triggerCharacter)) {
29736
+ var charBeforeTrigger = segment.text[segment.text.length - 2];
29737
+ if (!charBeforeTrigger ||
29738
+ !charBeforeTrigger.trim() ||
29739
+ (0, roosterjs_content_model_dom_1.isPunctuation)(charBeforeTrigger)) {
29740
+ var selection = helper.editor.getDOMSelection();
29741
+ var pos = (selection === null || selection === void 0 ? void 0 : selection.type) == 'range' && selection.range.collapsed
29742
+ ? {
29743
+ node: selection.range.startContainer,
29744
+ offset: selection.range.startOffset,
29745
+ }
29746
+ : null;
29747
+ if (pos) {
29748
+ _this.lastQueryString = _this.triggerCharacter;
29749
+ helper.direction = _this.handler.onTrigger(_this.lastQueryString, pos);
29750
+ }
29751
+ }
29752
+ }
29753
+ return false;
29754
+ });
29755
+ }
29756
+ };
29757
+ return PickerPlugin;
29758
+ }());
29759
+ exports.PickerPlugin = PickerPlugin;
29760
+
29761
+
29762
+ /***/ }),
29763
+
29764
+ /***/ "./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts":
29765
+ /*!*******************************************************************************!*\
29766
+ !*** ./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts ***!
29767
+ \*******************************************************************************/
29768
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
29769
+
29770
+ "use strict";
29771
+
29772
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
29773
+ exports.getQueryString = void 0;
29774
+ var splitTextSegment_1 = __webpack_require__(/*! ../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
29775
+ /**
29776
+ * @internal
29777
+ */
29778
+ function getQueryString(triggerCharacter, paragraph, previousSegment, splittedSegmentResult) {
29779
+ var result = '';
29780
+ var i = paragraph.segments.indexOf(previousSegment);
29781
+ for (; i >= 0; i--) {
29782
+ var segment = paragraph.segments[i];
29783
+ if (segment.segmentType != 'Text') {
29784
+ result = '';
29785
+ break;
29786
+ }
29787
+ var index = segment.text.lastIndexOf(triggerCharacter);
29788
+ if (index >= 0) {
29789
+ result = segment.text.substring(index) + result;
29790
+ splittedSegmentResult === null || splittedSegmentResult === void 0 ? void 0 : splittedSegmentResult.unshift(index > 0
29791
+ ? (0, splitTextSegment_1.splitTextSegment)(segment, paragraph, index, segment.text.length)
29792
+ : segment);
29793
+ break;
29794
+ }
29795
+ else {
29796
+ result = segment.text + result;
29797
+ splittedSegmentResult === null || splittedSegmentResult === void 0 ? void 0 : splittedSegmentResult.unshift(segment);
29798
+ }
29799
+ }
29800
+ if (i < 0) {
29801
+ result = '';
29802
+ }
29803
+ return result;
29804
+ }
29805
+ exports.getQueryString = getQueryString;
29806
+
29807
+
28213
29808
  /***/ }),
28214
29809
 
28215
29810
  /***/ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/CreateElement/createElement.ts":
@@ -28403,6 +29998,73 @@ var DragAndDropHelper = /** @class */ (function () {
28403
29998
  exports.DragAndDropHelper = DragAndDropHelper;
28404
29999
 
28405
30000
 
30001
+ /***/ }),
30002
+
30003
+ /***/ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getDOMInsertPointRect.ts":
30004
+ /*!************************************************************************************************!*\
30005
+ !*** ./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getDOMInsertPointRect.ts ***!
30006
+ \************************************************************************************************/
30007
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
30008
+
30009
+ "use strict";
30010
+
30011
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
30012
+ exports.getDOMInsertPointRect = void 0;
30013
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
30014
+ /**
30015
+ * Get bounding rect of the given DOM insert point
30016
+ * @param doc The document object
30017
+ * @param pos The input DOM insert point
30018
+ */
30019
+ function getDOMInsertPointRect(doc, pos) {
30020
+ var _a;
30021
+ var node = pos.node, offset = pos.offset;
30022
+ var range = doc.createRange();
30023
+ range.setStart(node, offset);
30024
+ // 1) try to get rect using range.getBoundingClientRect()
30025
+ var rect = (0, roosterjs_content_model_dom_1.normalizeRect)(range.getBoundingClientRect());
30026
+ if (rect) {
30027
+ return rect;
30028
+ }
30029
+ // 2) try to get rect using range.getClientRects
30030
+ while (node.lastChild) {
30031
+ if (offset == node.childNodes.length) {
30032
+ node = node.lastChild;
30033
+ offset = node.childNodes.length;
30034
+ }
30035
+ else {
30036
+ node = node.childNodes[offset];
30037
+ offset = 0;
30038
+ }
30039
+ }
30040
+ var rects = range.getClientRects && range.getClientRects();
30041
+ rect = rects && rects.length == 1 ? (0, roosterjs_content_model_dom_1.normalizeRect)(rects[0]) : null;
30042
+ if (rect) {
30043
+ return rect;
30044
+ }
30045
+ // 3) if node is text node, try inserting a SPAN and get the rect of SPAN for others
30046
+ if ((0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'TEXT_NODE')) {
30047
+ var span = node.ownerDocument.createElement('span');
30048
+ span.textContent = '\u200b';
30049
+ range.insertNode(span);
30050
+ rect = (0, roosterjs_content_model_dom_1.normalizeRect)(span.getBoundingClientRect());
30051
+ (_a = span.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(span);
30052
+ if (rect) {
30053
+ return rect;
30054
+ }
30055
+ }
30056
+ // 4) try getBoundingClientRect on element
30057
+ if ((0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'ELEMENT_NODE') && node.getBoundingClientRect) {
30058
+ rect = (0, roosterjs_content_model_dom_1.normalizeRect)(node.getBoundingClientRect());
30059
+ if (rect) {
30060
+ return rect;
30061
+ }
30062
+ }
30063
+ return null;
30064
+ }
30065
+ exports.getDOMInsertPointRect = getDOMInsertPointRect;
30066
+
30067
+
28406
30068
  /***/ }),
28407
30069
 
28408
30070
  /***/ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getIntersectedRect.ts":
@@ -28517,6 +30179,7 @@ var defaultShortcuts = [
28517
30179
  shortcuts_1.ShortcutUndo,
28518
30180
  shortcuts_1.ShortcutUndo2,
28519
30181
  shortcuts_1.ShortcutRedo,
30182
+ shortcuts_1.ShortcutRedoAlt,
28520
30183
  shortcuts_1.ShortcutRedoMacOS,
28521
30184
  shortcuts_1.ShortcutBullet,
28522
30185
  shortcuts_1.ShortcutNumbering,
@@ -28636,7 +30299,7 @@ exports.ShortcutPlugin = ShortcutPlugin;
28636
30299
  "use strict";
28637
30300
 
28638
30301
  Object.defineProperty(exports, "__esModule", ({ value: true }));
28639
- exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoMacOS = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = void 0;
30302
+ exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoAlt = exports.ShortcutRedoMacOS = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = void 0;
28640
30303
  var roosterjs_content_model_core_1 = __webpack_require__(/*! roosterjs-content-model-core */ "./packages/roosterjs-content-model-core/lib/index.ts");
28641
30304
  var setShortcutIndentationCommand_1 = __webpack_require__(/*! ./utils/setShortcutIndentationCommand */ "./packages/roosterjs-content-model-plugins/lib/shortcut/utils/setShortcutIndentationCommand.ts");
28642
30305
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
@@ -28697,7 +30360,7 @@ exports.ShortcutUnderline = {
28697
30360
  /**
28698
30361
  * Shortcut command for Clear Format
28699
30362
  * Windows: Ctrl + Space
28700
- * MacOS: Meta + Space
30363
+ * MacOS: N/A
28701
30364
  */
28702
30365
  exports.ShortcutClearFormat = {
28703
30366
  shortcutKey: {
@@ -28706,6 +30369,7 @@ exports.ShortcutClearFormat = {
28706
30369
  which: 32 /* SPACE */,
28707
30370
  },
28708
30371
  onClick: function (editor) { return (0, roosterjs_content_model_api_1.clearFormat)(editor); },
30372
+ environment: 'nonMac',
28709
30373
  };
28710
30374
  /**
28711
30375
  * Shortcut command for Undo 1
@@ -28749,6 +30413,7 @@ exports.ShortcutRedo = {
28749
30413
  environment: 'nonMac',
28750
30414
  };
28751
30415
  /**
30416
+ * @deprecated
28752
30417
  * Shortcut command for Redo 2
28753
30418
  * Windows: N/A
28754
30419
  * MacOS: Meta + Shift + Z
@@ -28762,6 +30427,19 @@ exports.ShortcutRedoMacOS = {
28762
30427
  onClick: function (editor) { return (0, roosterjs_content_model_core_1.redo)(editor); },
28763
30428
  environment: 'mac',
28764
30429
  };
30430
+ /**
30431
+ * Shortcut command for Redo 3
30432
+ * Windows: Ctrl + Shift + Z
30433
+ * MacOS: Meta + Shift + Z
30434
+ */
30435
+ exports.ShortcutRedoAlt = {
30436
+ shortcutKey: {
30437
+ modifierKey: 'ctrl',
30438
+ shiftKey: true,
30439
+ which: 90 /* Z */,
30440
+ },
30441
+ onClick: function (editor) { return (0, roosterjs_content_model_core_1.redo)(editor); },
30442
+ };
28765
30443
  /**
28766
30444
  * Shortcut command for Bullet List
28767
30445
  * Windows: Ctrl + . (Period)
@@ -28817,7 +30495,7 @@ exports.ShortcutDecreaseFont = {
28817
30495
  /**
28818
30496
  * Shortcut command for Intent list
28819
30497
  * Windows: Alt + Shift + Arrow Right
28820
- * MacOS: Option + Shift+ Arrow Right
30498
+ * MacOS: N/A
28821
30499
  */
28822
30500
  exports.ShortcutIndentList = {
28823
30501
  shortcutKey: {
@@ -28828,11 +30506,12 @@ exports.ShortcutIndentList = {
28828
30506
  onClick: function (editor) {
28829
30507
  (0, setShortcutIndentationCommand_1.setShortcutIndentationCommand)(editor, 'indent');
28830
30508
  },
30509
+ environment: 'nonMac',
28831
30510
  };
28832
30511
  /**
28833
30512
  * Shortcut command for Outdent list
28834
30513
  * Windows: Alt + Shift + Arrow Left
28835
- * MacOS: Option + Shift+ Arrow Left
30514
+ * MacOS: N/A
28836
30515
  */
28837
30516
  exports.ShortcutOutdentList = {
28838
30517
  shortcutKey: {
@@ -28843,6 +30522,7 @@ exports.ShortcutOutdentList = {
28843
30522
  onClick: function (editor) {
28844
30523
  (0, setShortcutIndentationCommand_1.setShortcutIndentationCommand)(editor, 'outdent');
28845
30524
  },
30525
+ environment: 'nonMac',
28846
30526
  };
28847
30527
 
28848
30528
 
@@ -28864,12 +30544,12 @@ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-mo
28864
30544
  * @internal
28865
30545
  */
28866
30546
  function setShortcutIndentationCommand(editor, operation) {
28867
- editor.formatContentModel(function (model) {
30547
+ editor.formatContentModel(function (model, context) {
28868
30548
  var listItem = (0, roosterjs_content_model_dom_1.getFirstSelectedListItem)(model);
28869
30549
  if (listItem &&
28870
30550
  listItem.blocks[0].blockType == 'Paragraph' &&
28871
30551
  listItem.blocks[0].segments[0].segmentType == 'SelectionMarker') {
28872
- (0, roosterjs_content_model_api_1.setModelIndentation)(model, operation);
30552
+ (0, roosterjs_content_model_api_1.setModelIndentation)(model, operation, undefined /*length*/, context);
28873
30553
  return true;
28874
30554
  }
28875
30555
  return false;
@@ -28902,10 +30582,12 @@ var TableEditPlugin = /** @class */ (function () {
28902
30582
  * @param anchorContainerSelector An optional selector string to specify the container to host the plugin.
28903
30583
  * The container must not be affected by transform: scale(), otherwise the position calculation will be wrong.
28904
30584
  * If not specified, the plugin will be inserted in document.body
30585
+ * @param onTableEditorCreated An optional callback to customize the Table Editors elements when created.
28905
30586
  */
28906
- function TableEditPlugin(anchorContainerSelector) {
30587
+ function TableEditPlugin(anchorContainerSelector, onTableEditorCreated) {
28907
30588
  var _this = this;
28908
30589
  this.anchorContainerSelector = anchorContainerSelector;
30590
+ this.onTableEditorCreated = onTableEditorCreated;
28909
30591
  this.editor = null;
28910
30592
  this.onMouseMoveDisposer = null;
28911
30593
  this.tableRectMap = null;
@@ -28983,6 +30665,7 @@ var TableEditPlugin = /** @class */ (function () {
28983
30665
  this.disposeTableEditor();
28984
30666
  this.editor = null;
28985
30667
  this.onMouseMoveDisposer = null;
30668
+ this.onTableEditorCreated = undefined;
28986
30669
  };
28987
30670
  /**
28988
30671
  * Handle events triggered from editor
@@ -29013,7 +30696,7 @@ var TableEditPlugin = /** @class */ (function () {
29013
30696
  var container = this.anchorContainerSelector
29014
30697
  ? this.editor.getDocument().querySelector(this.anchorContainerSelector)
29015
30698
  : undefined;
29016
- this.tableEditor = new TableEditor_1.TableEditor(this.editor, table, this.invalidateTableRects, (0, roosterjs_content_model_dom_1.isNodeOfType)(container, 'ELEMENT_NODE') ? container : undefined, event === null || event === void 0 ? void 0 : event.currentTarget);
30699
+ this.tableEditor = new TableEditor_1.TableEditor(this.editor, table, this.invalidateTableRects, (0, roosterjs_content_model_dom_1.isNodeOfType)(container, 'ELEMENT_NODE') ? container : undefined, event === null || event === void 0 ? void 0 : event.currentTarget, this.onTableEditorCreated);
29017
30700
  }
29018
30701
  };
29019
30702
  TableEditPlugin.prototype.disposeTableEditor = function () {
@@ -29098,7 +30781,7 @@ var TOP_OR_SIDE;
29098
30781
  * When set a different current table or change current TD, we need to update these areas
29099
30782
  */
29100
30783
  var TableEditor = /** @class */ (function () {
29101
- function TableEditor(editor, table, onChanged, anchorContainer, contentDiv) {
30784
+ function TableEditor(editor, table, onChanged, anchorContainer, contentDiv, onTableEditorCreated) {
29102
30785
  var _this = this;
29103
30786
  var _a;
29104
30787
  this.editor = editor;
@@ -29106,6 +30789,7 @@ var TableEditor = /** @class */ (function () {
29106
30789
  this.onChanged = onChanged;
29107
30790
  this.anchorContainer = anchorContainer;
29108
30791
  this.contentDiv = contentDiv;
30792
+ this.onTableEditorCreated = onTableEditorCreated;
29109
30793
  // 1, 2 - Insert a column or a row
29110
30794
  this.horizontalInserter = null;
29111
30795
  this.verticalInserter = null;
@@ -29117,6 +30801,20 @@ var TableEditor = /** @class */ (function () {
29117
30801
  // 6 - Move as well as select whole table
29118
30802
  this.tableMover = null;
29119
30803
  this.range = null;
30804
+ this.onEditorCreated = function (editorType, element) {
30805
+ var _a;
30806
+ var disposer = (_a = _this.onTableEditorCreated) === null || _a === void 0 ? void 0 : _a.call(_this, editorType, element);
30807
+ var onMouseOut = element && _this.getOnMouseOut(element);
30808
+ if (onMouseOut) {
30809
+ element.addEventListener('mouseout', onMouseOut);
30810
+ }
30811
+ return function () {
30812
+ disposer === null || disposer === void 0 ? void 0 : disposer();
30813
+ if (onMouseOut) {
30814
+ element.removeEventListener('mouseout', onMouseOut);
30815
+ }
30816
+ };
30817
+ };
29120
30818
  this.onFinishEditing = function () {
29121
30819
  _this.editor.focus();
29122
30820
  if (_this.range) {
@@ -29145,14 +30843,16 @@ var TableEditor = /** @class */ (function () {
29145
30843
  * @param table the table to select
29146
30844
  */
29147
30845
  this.onSelect = function (table) {
30846
+ var _a, _b;
29148
30847
  _this.editor.focus();
29149
30848
  if (table) {
30849
+ var parsedTable = (0, roosterjs_content_model_dom_1.parseTableCells)(table);
29150
30850
  var selection = {
29151
30851
  table: table,
29152
30852
  firstRow: 0,
29153
30853
  firstColumn: 0,
29154
- lastRow: table.rows.length - 1,
29155
- lastColumn: table.rows[table.rows.length - 1].cells.length - 1,
30854
+ lastRow: parsedTable.length - 1,
30855
+ lastColumn: ((_b = (_a = parsedTable[0]) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) - 1,
29156
30856
  type: 'table',
29157
30857
  };
29158
30858
  _this.editor.setDOMSelection(selection);
@@ -29198,7 +30898,6 @@ var TableEditor = /** @class */ (function () {
29198
30898
  var _a;
29199
30899
  // Get whole table rect
29200
30900
  var tableRect = (0, roosterjs_content_model_dom_1.normalizeRect)(this.table.getBoundingClientRect());
29201
- //console.log('>>>tableRect', tableRect);
29202
30901
  if (!tableRect) {
29203
30902
  return;
29204
30903
  }
@@ -29269,10 +30968,10 @@ var TableEditor = /** @class */ (function () {
29269
30968
  };
29270
30969
  TableEditor.prototype.setEditorFeatures = function () {
29271
30970
  if (!this.tableMover) {
29272
- this.tableMover = (0, TableMover_1.createTableMover)(this.table, this.editor, this.isRTL, this.onSelect, this.getOnMouseOut, this.contentDiv, this.anchorContainer);
30971
+ this.tableMover = (0, TableMover_1.createTableMover)(this.table, this.editor, this.isRTL, this.onSelect, this.contentDiv, this.anchorContainer, this.onEditorCreated);
29273
30972
  }
29274
30973
  if (!this.tableResizer) {
29275
- this.tableResizer = (0, TableResizer_1.createTableResizer)(this.table, this.editor, this.isRTL, this.onStartTableResize, this.onFinishEditing, this.contentDiv, this.anchorContainer);
30974
+ this.tableResizer = (0, TableResizer_1.createTableResizer)(this.table, this.editor, this.isRTL, this.onStartTableResize, this.onFinishEditing, this.contentDiv, this.anchorContainer, this.onTableEditorCreated);
29276
30975
  }
29277
30976
  };
29278
30977
  TableEditor.prototype.setResizingTd = function (td) {
@@ -29294,7 +30993,7 @@ var TableEditor = /** @class */ (function () {
29294
30993
  this.disposeTableInserter();
29295
30994
  }
29296
30995
  if (!this.horizontalInserter && !this.verticalInserter && td) {
29297
- var newInserter = (0, TableInserter_1.createTableInserter)(this.editor, td, this.table, this.isRTL, !!isHorizontal, this.onInserted, this.getOnMouseOut, this.anchorContainer);
30996
+ var newInserter = (0, TableInserter_1.createTableInserter)(this.editor, td, this.table, this.isRTL, !!isHorizontal, this.onInserted, this.anchorContainer, this.onEditorCreated);
29298
30997
  if (isHorizontal) {
29299
30998
  this.horizontalInserter = newInserter;
29300
30999
  }
@@ -29544,10 +31243,10 @@ exports.disposeTableEditFeature = void 0;
29544
31243
  function disposeTableEditFeature(resizer) {
29545
31244
  var _a, _b, _c;
29546
31245
  if (resizer) {
29547
- (_b = (_a = resizer.div) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(resizer.div);
29548
- resizer.div = null;
29549
- (_c = resizer.featureHandler) === null || _c === void 0 ? void 0 : _c.dispose();
31246
+ (_a = resizer.featureHandler) === null || _a === void 0 ? void 0 : _a.dispose();
29550
31247
  resizer.featureHandler = null;
31248
+ (_c = (_b = resizer.div) === null || _b === void 0 ? void 0 : _b.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(resizer.div);
31249
+ resizer.div = null;
29551
31250
  }
29552
31251
  }
29553
31252
  exports.disposeTableEditFeature = disposeTableEditFeature;
@@ -29576,7 +31275,7 @@ var INSERTER_BORDER_SIZE = 1;
29576
31275
  /**
29577
31276
  * @internal
29578
31277
  */
29579
- function createTableInserter(editor, td, table, isRTL, isHorizontal, onInsert, getOnMouseOut, anchorContainer) {
31278
+ function createTableInserter(editor, td, table, isRTL, isHorizontal, onInsert, anchorContainer, onTableEditorCreated) {
29580
31279
  var tdRect = (0, roosterjs_content_model_dom_1.normalizeRect)(td.getBoundingClientRect());
29581
31280
  var viewPort = editor.getVisibleViewport();
29582
31281
  var tableRect = table && viewPort ? (0, getIntersectedRect_1.getIntersectedRect)([table], [viewPort]) : null;
@@ -29602,14 +31301,14 @@ function createTableInserter(editor, td, table, isRTL, isHorizontal, onInsert, g
29602
31301
  div.firstChild.style.height = tableRect.bottom - tableRect.top + "px";
29603
31302
  }
29604
31303
  (anchorContainer || document_1.body).appendChild(div);
29605
- var handler = new TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, getOnMouseOut);
31304
+ var handler = new TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, onTableEditorCreated);
29606
31305
  return { div: div, featureHandler: handler, node: td };
29607
31306
  }
29608
31307
  return null;
29609
31308
  }
29610
31309
  exports.createTableInserter = createTableInserter;
29611
31310
  var TableInsertHandler = /** @class */ (function () {
29612
- function TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, getOnMouseOut) {
31311
+ function TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, onTableEditorCreated) {
29613
31312
  var _this = this;
29614
31313
  this.div = div;
29615
31314
  this.td = td;
@@ -29644,15 +31343,13 @@ var TableInsertHandler = /** @class */ (function () {
29644
31343
  _this.onInsert();
29645
31344
  };
29646
31345
  this.div.addEventListener('click', this.insertTd);
29647
- this.onMouseOutEvent = getOnMouseOut(div);
29648
- this.div.addEventListener('mouseout', this.onMouseOutEvent);
31346
+ this.disposer = onTableEditorCreated === null || onTableEditorCreated === void 0 ? void 0 : onTableEditorCreated(isHorizontal ? 'HorizontalTableInserter' : 'VerticalTableInserter', div);
29649
31347
  }
29650
31348
  TableInsertHandler.prototype.dispose = function () {
31349
+ var _a;
29651
31350
  this.div.removeEventListener('click', this.insertTd);
29652
- if (this.onMouseOutEvent) {
29653
- this.div.removeEventListener('mouseout', this.onMouseOutEvent);
29654
- }
29655
- this.onMouseOutEvent = null;
31351
+ (_a = this.disposer) === null || _a === void 0 ? void 0 : _a.call(this);
31352
+ this.disposer = undefined;
29656
31353
  };
29657
31354
  return TableInsertHandler;
29658
31355
  }());
@@ -29699,7 +31396,7 @@ var TABLE_MOVER_ID = '_Table_Mover';
29699
31396
  * Contains the function to select whole table
29700
31397
  * Moving behavior not implemented yet
29701
31398
  */
29702
- function createTableMover(table, editor, isRTL, onFinishDragging, getOnMouseOut, contentDiv, anchorContainer) {
31399
+ function createTableMover(table, editor, isRTL, onFinishDragging, contentDiv, anchorContainer, onTableEditorCreated) {
29703
31400
  var rect = (0, roosterjs_content_model_dom_1.normalizeRect)(table.getBoundingClientRect());
29704
31401
  if (!isTableTopVisible(editor, rect, contentDiv)) {
29705
31402
  return null;
@@ -29730,25 +31427,22 @@ function createTableMover(table, editor, isRTL, onFinishDragging, getOnMouseOut,
29730
31427
  };
29731
31428
  var featureHandler = new TableMoverFeature(div, context, setDivPosition, {
29732
31429
  onDragEnd: onDragEnd,
29733
- }, context.zoomScale, getOnMouseOut);
31430
+ }, context.zoomScale, onTableEditorCreated);
29734
31431
  return { div: div, featureHandler: featureHandler, node: table };
29735
31432
  }
29736
31433
  exports.createTableMover = createTableMover;
29737
31434
  var TableMoverFeature = /** @class */ (function (_super) {
29738
31435
  (0, tslib_1.__extends)(TableMoverFeature, _super);
29739
- function TableMoverFeature(div, context, onSubmit, handler, zoomScale, getOnMouseOut, forceMobile, container) {
29740
- var _this = _super.call(this, div, context, onSubmit, handler, zoomScale, forceMobile) || this;
29741
- _this.div = div;
29742
- _this.onMouseOut = getOnMouseOut(div);
29743
- div.addEventListener('mouseout', _this.onMouseOut);
31436
+ function TableMoverFeature(div, context, onSubmit, handler, zoomScale, onTableEditorCreated) {
31437
+ var _this = _super.call(this, div, context, onSubmit, handler, zoomScale) || this;
31438
+ _this.disposer = onTableEditorCreated === null || onTableEditorCreated === void 0 ? void 0 : onTableEditorCreated('TableMover', div);
29744
31439
  return _this;
29745
31440
  }
29746
31441
  TableMoverFeature.prototype.dispose = function () {
31442
+ var _a;
31443
+ (_a = this.disposer) === null || _a === void 0 ? void 0 : _a.call(this);
31444
+ this.disposer = undefined;
29747
31445
  _super.prototype.dispose.call(this);
29748
- if (this.onMouseOut) {
29749
- this.div.removeEventListener('mouseout', this.onMouseOut);
29750
- }
29751
- this.onMouseOut = null;
29752
31446
  };
29753
31447
  return TableMoverFeature;
29754
31448
  }(DragAndDropHelper_1.DragAndDropHelper));
@@ -29781,6 +31475,7 @@ function isTableTopVisible(editor, rect, contentDiv) {
29781
31475
 
29782
31476
  Object.defineProperty(exports, "__esModule", ({ value: true }));
29783
31477
  exports.createTableResizer = void 0;
31478
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
29784
31479
  var createElement_1 = __webpack_require__(/*! ../../../pluginUtils/CreateElement/createElement */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/CreateElement/createElement.ts");
29785
31480
  var DragAndDropHelper_1 = __webpack_require__(/*! ../../../pluginUtils/DragAndDrop/DragAndDropHelper */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/DragAndDrop/DragAndDropHelper.ts");
29786
31481
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
@@ -29789,7 +31484,7 @@ var TABLE_RESIZER_ID = '_Table_Resizer';
29789
31484
  /**
29790
31485
  * @internal
29791
31486
  */
29792
- function createTableResizer(table, editor, isRTL, onStart, onEnd, contentDiv, anchorContainer) {
31487
+ function createTableResizer(table, editor, isRTL, onStart, onEnd, contentDiv, anchorContainer, onTableEditorCreated) {
29793
31488
  var rect = (0, roosterjs_content_model_dom_1.normalizeRect)(table.getBoundingClientRect());
29794
31489
  if (!isTableBottomVisible(editor, rect, contentDiv)) {
29795
31490
  return null;
@@ -29816,15 +31511,30 @@ function createTableResizer(table, editor, isRTL, onStart, onEnd, contentDiv, an
29816
31511
  contentDiv: contentDiv,
29817
31512
  };
29818
31513
  setDivPosition(context, div);
29819
- var featureHandler = new DragAndDropHelper_1.DragAndDropHelper(div, context, hideResizer, // Resizer is hidden while dragging only
31514
+ var featureHandler = new TableResizer(div, context, hideResizer, // Resizer is hidden while dragging only
29820
31515
  {
29821
31516
  onDragStart: onDragStart,
29822
31517
  onDragging: onDragging,
29823
31518
  onDragEnd: onDragEnd,
29824
- }, zoomScale, editor.getEnvironment().isMobileOrTablet);
31519
+ }, zoomScale, editor.getEnvironment().isMobileOrTablet, onTableEditorCreated);
29825
31520
  return { node: table, div: div, featureHandler: featureHandler };
29826
31521
  }
29827
31522
  exports.createTableResizer = createTableResizer;
31523
+ var TableResizer = /** @class */ (function (_super) {
31524
+ (0, tslib_1.__extends)(TableResizer, _super);
31525
+ function TableResizer(trigger, context, onSubmit, handler, zoomScale, forceMobile, onTableEditorCreated) {
31526
+ var _this = _super.call(this, trigger, context, onSubmit, handler, zoomScale, forceMobile) || this;
31527
+ _this.disposer = onTableEditorCreated === null || onTableEditorCreated === void 0 ? void 0 : onTableEditorCreated('TableResizer', trigger);
31528
+ return _this;
31529
+ }
31530
+ TableResizer.prototype.dispose = function () {
31531
+ var _a;
31532
+ (_a = this.disposer) === null || _a === void 0 ? void 0 : _a.call(this);
31533
+ this.disposer = undefined;
31534
+ _super.prototype.dispose.call(this);
31535
+ };
31536
+ return TableResizer;
31537
+ }(DragAndDropHelper_1.DragAndDropHelper));
29828
31538
  function onDragStart(context, event) {
29829
31539
  context.onStart();
29830
31540
  var editor = context.editor, table = context.table;