roosterjs 9.1.0 → 9.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2094,7 +2094,7 @@ exports["default"] = getDarkColor;
2094
2094
 
2095
2095
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2096
2096
  exports.formatTextSegmentBeforeSelectionMarker = exports.formatSegmentWithContentModel = exports.formatParagraphWithContentModel = exports.formatImageWithContentModel = exports.formatTableWithContentModel = exports.clearSelectedCells = exports.insertTableColumn = exports.insertTableRow = exports.insertEntity = exports.toggleCode = exports.setParagraphMargin = exports.adjustImageSelection = exports.setImageAltText = exports.adjustLinkSelection = exports.removeLink = exports.insertLink = exports.clearFormat = exports.getFormatState = exports.changeImage = exports.setImageBoxShadow = exports.setImageBorder = exports.setSpacing = exports.toggleBlockQuote = exports.setHeadingLevel = exports.setDirection = exports.setAlignment = exports.setIndentation = exports.setListStartNumber = exports.setListStyle = exports.insertImage = exports.changeCapitalization = exports.applySegmentFormat = exports.changeFontSize = exports.setTextColor = exports.setFontSize = exports.setFontName = exports.setBackgroundColor = exports.toggleSuperscript = exports.toggleSubscript = exports.toggleStrikethrough = exports.toggleUnderline = exports.toggleItalic = exports.toggleBold = exports.toggleNumbering = exports.toggleBullet = exports.applyTableBorderFormat = exports.editTable = exports.setTableCellShade = exports.formatTable = exports.insertTable = void 0;
2097
- exports.matchLink = exports.setModelIndentation = exports.findListItemsInSameThread = exports.setModelListStartNumber = exports.setModelListStyle = exports.setListType = void 0;
2097
+ exports.getListAnnounceData = exports.matchLink = exports.setModelIndentation = exports.findListItemsInSameThread = exports.setModelListStartNumber = exports.setModelListStyle = exports.setListType = exports.formatInsertPointWithContentModel = void 0;
2098
2098
  var insertTable_1 = __webpack_require__(/*! ./publicApi/table/insertTable */ "./packages/roosterjs-content-model-api/lib/publicApi/table/insertTable.ts");
2099
2099
  Object.defineProperty(exports, "insertTable", ({ enumerable: true, get: function () { return insertTable_1.insertTable; } }));
2100
2100
  var formatTable_1 = __webpack_require__(/*! ./publicApi/table/formatTable */ "./packages/roosterjs-content-model-api/lib/publicApi/table/formatTable.ts");
@@ -2195,6 +2195,8 @@ var formatSegmentWithContentModel_1 = __webpack_require__(/*! ./publicApi/utils/
2195
2195
  Object.defineProperty(exports, "formatSegmentWithContentModel", ({ enumerable: true, get: function () { return formatSegmentWithContentModel_1.formatSegmentWithContentModel; } }));
2196
2196
  var formatTextSegmentBeforeSelectionMarker_1 = __webpack_require__(/*! ./publicApi/utils/formatTextSegmentBeforeSelectionMarker */ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatTextSegmentBeforeSelectionMarker.ts");
2197
2197
  Object.defineProperty(exports, "formatTextSegmentBeforeSelectionMarker", ({ enumerable: true, get: function () { return formatTextSegmentBeforeSelectionMarker_1.formatTextSegmentBeforeSelectionMarker; } }));
2198
+ var formatInsertPointWithContentModel_1 = __webpack_require__(/*! ./publicApi/utils/formatInsertPointWithContentModel */ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatInsertPointWithContentModel.ts");
2199
+ Object.defineProperty(exports, "formatInsertPointWithContentModel", ({ enumerable: true, get: function () { return formatInsertPointWithContentModel_1.formatInsertPointWithContentModel; } }));
2198
2200
  var setListType_1 = __webpack_require__(/*! ./modelApi/list/setListType */ "./packages/roosterjs-content-model-api/lib/modelApi/list/setListType.ts");
2199
2201
  Object.defineProperty(exports, "setListType", ({ enumerable: true, get: function () { return setListType_1.setListType; } }));
2200
2202
  var setModelListStyle_1 = __webpack_require__(/*! ./modelApi/list/setModelListStyle */ "./packages/roosterjs-content-model-api/lib/modelApi/list/setModelListStyle.ts");
@@ -2207,6 +2209,8 @@ var setModelIndentation_1 = __webpack_require__(/*! ./modelApi/block/setModelInd
2207
2209
  Object.defineProperty(exports, "setModelIndentation", ({ enumerable: true, get: function () { return setModelIndentation_1.setModelIndentation; } }));
2208
2210
  var matchLink_1 = __webpack_require__(/*! ./modelApi/link/matchLink */ "./packages/roosterjs-content-model-api/lib/modelApi/link/matchLink.ts");
2209
2211
  Object.defineProperty(exports, "matchLink", ({ enumerable: true, get: function () { return matchLink_1.matchLink; } }));
2212
+ var getListAnnounceData_1 = __webpack_require__(/*! ./modelApi/list/getListAnnounceData */ "./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts");
2213
+ Object.defineProperty(exports, "getListAnnounceData", ({ enumerable: true, get: function () { return getListAnnounceData_1.getListAnnounceData; } }));
2210
2214
 
2211
2215
 
2212
2216
  /***/ }),
@@ -2373,7 +2377,9 @@ function setProperty(format, key, value) {
2373
2377
 
2374
2378
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2375
2379
  exports.setModelIndentation = void 0;
2380
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
2376
2381
  var findListItemsInSameThread_1 = __webpack_require__(/*! ../list/findListItemsInSameThread */ "./packages/roosterjs-content-model-api/lib/modelApi/list/findListItemsInSameThread.ts");
2382
+ var getListAnnounceData_1 = __webpack_require__(/*! ../list/getListAnnounceData */ "./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts");
2377
2383
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
2378
2384
  var IndentStepInPixel = 40;
2379
2385
  /**
@@ -2382,7 +2388,7 @@ var IndentStepInPixel = 40;
2382
2388
  * @param length The length of indentation in pixel, default value is 40
2383
2389
  * Set indentation for selected list items or paragraphs
2384
2390
  */
2385
- function setModelIndentation(model, indentation, length) {
2391
+ function setModelIndentation(model, indentation, length, context) {
2386
2392
  if (length === void 0) { length = IndentStepInPixel; }
2387
2393
  var paragraphOrListItem = (0, roosterjs_content_model_dom_1.getOperationalBlocks)(model, ['ListItem'], ['TableCell']);
2388
2394
  var isIndent = indentation == 'indent';
@@ -2429,6 +2435,9 @@ function setModelIndentation(model, indentation, length) {
2429
2435
  else {
2430
2436
  block.levels.pop();
2431
2437
  }
2438
+ if (block.levels.length > 0 && context) {
2439
+ context.announceData = (0, getListAnnounceData_1.getListAnnounceData)((0, tslib_1.__spreadArray)([block], (0, tslib_1.__read)(path), false));
2440
+ }
2432
2441
  }
2433
2442
  }
2434
2443
  else if (block) {
@@ -3129,9 +3138,9 @@ exports.findListItemsInSameThread = void 0;
3129
3138
  * @param currentItem The current list item
3130
3139
  * Search for all list items in the same thread as the current list item
3131
3140
  */
3132
- function findListItemsInSameThread(model, currentItem) {
3141
+ function findListItemsInSameThread(group, currentItem) {
3133
3142
  var items = [];
3134
- findListItems(model, items);
3143
+ findListItems(group, items);
3135
3144
  return filterListItems(items, currentItem);
3136
3145
  }
3137
3146
  exports.findListItemsInSameThread = findListItemsInSameThread;
@@ -3199,7 +3208,9 @@ function filterListItems(items, currentItem) {
3199
3208
  break;
3200
3209
  }
3201
3210
  }
3202
- else if (!isOrderedList || startNumberOverride) {
3211
+ else if (!isOrderedList ||
3212
+ startNumberOverride ||
3213
+ item.levels.length < currentItem.levels.length) {
3203
3214
  break;
3204
3215
  }
3205
3216
  }
@@ -3217,7 +3228,9 @@ function filterListItems(items, currentItem) {
3217
3228
  if (areListTypesCompatible(items, currentIndex, i) && !startNumberOverride) {
3218
3229
  result.push(item);
3219
3230
  }
3220
- else if (!isOrderedList || startNumberOverride) {
3231
+ else if (!isOrderedList ||
3232
+ startNumberOverride ||
3233
+ item.levels.length < currentItem.levels.length) {
3221
3234
  break;
3222
3235
  }
3223
3236
  }
@@ -3237,6 +3250,85 @@ function hasStartNumberOverride(item, levelLength) {
3237
3250
  }
3238
3251
 
3239
3252
 
3253
+ /***/ }),
3254
+
3255
+ /***/ "./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts":
3256
+ /*!***************************************************************************************!*\
3257
+ !*** ./packages/roosterjs-content-model-api/lib/modelApi/list/getListAnnounceData.ts ***!
3258
+ \***************************************************************************************/
3259
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
3260
+
3261
+ "use strict";
3262
+
3263
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
3264
+ exports.getListAnnounceData = void 0;
3265
+ var findListItemsInSameThread_1 = __webpack_require__(/*! ./findListItemsInSameThread */ "./packages/roosterjs-content-model-api/lib/modelApi/list/findListItemsInSameThread.ts");
3266
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
3267
+ /**
3268
+ * Get announce data for list item
3269
+ * @param path Content model path that include the list item
3270
+ * @returns Announce data of current list item if any, or null
3271
+ */
3272
+ function getListAnnounceData(path) {
3273
+ var index = (0, roosterjs_content_model_dom_1.getClosestAncestorBlockGroupIndex)(path, ['ListItem'], ['TableCell']);
3274
+ if (index >= 0) {
3275
+ var listItem = path[index];
3276
+ var level = listItem.levels[listItem.levels.length - 1];
3277
+ if (level.format.displayForDummyItem) {
3278
+ return null;
3279
+ }
3280
+ else if (level.listType == 'OL') {
3281
+ var listNumber = getListNumber(path, listItem);
3282
+ var metadata = (0, roosterjs_content_model_dom_1.updateListMetadata)(level);
3283
+ var listStyle = (0, roosterjs_content_model_dom_1.getAutoListStyleType)('OL', metadata !== null && metadata !== void 0 ? metadata : {}, listItem.levels.length - 1, level.format.listStyleType);
3284
+ return listStyle === undefined
3285
+ ? null
3286
+ : {
3287
+ defaultStrings: 'announceListItemNumbering',
3288
+ formatStrings: [(0, roosterjs_content_model_dom_1.getOrderedListNumberStr)(listStyle, listNumber)],
3289
+ };
3290
+ }
3291
+ else {
3292
+ return {
3293
+ defaultStrings: 'announceListItemBullet',
3294
+ };
3295
+ }
3296
+ }
3297
+ else {
3298
+ return null;
3299
+ }
3300
+ }
3301
+ exports.getListAnnounceData = getListAnnounceData;
3302
+ function getListNumber(path, listItem) {
3303
+ var _a, _b;
3304
+ var items = (0, findListItemsInSameThread_1.findListItemsInSameThread)(path[path.length - 1], listItem);
3305
+ var listNumber = 0;
3306
+ for (var i = 0; i < items.length; i++) {
3307
+ var item = items[i];
3308
+ if (listNumber == 0 && item.levels.length == listItem.levels.length) {
3309
+ listNumber = (_b = (_a = item.levels[item.levels.length - 1]) === null || _a === void 0 ? void 0 : _a.format.startNumberOverride) !== null && _b !== void 0 ? _b : 1;
3310
+ }
3311
+ if (item == listItem) {
3312
+ // Found current item, so break and return
3313
+ break;
3314
+ }
3315
+ else if (item.levels.length < listItem.levels.length) {
3316
+ // Found upper level item, reset list number
3317
+ listNumber = 0;
3318
+ }
3319
+ else if (item.levels.length > listItem.levels.length) {
3320
+ // Found deeper level item, skip
3321
+ continue;
3322
+ }
3323
+ else if (!item.levels[item.levels.length - 1].format.displayForDummyItem) {
3324
+ // Save level, and is not dummy, number plus one
3325
+ listNumber++;
3326
+ }
3327
+ }
3328
+ return listNumber;
3329
+ }
3330
+
3331
+
3240
3332
  /***/ }),
3241
3333
 
3242
3334
  /***/ "./packages/roosterjs-content-model-api/lib/modelApi/list/setListType.ts":
@@ -4991,6 +5083,8 @@ function insertImageWithSrc(editor, src) {
4991
5083
  (0, roosterjs_content_model_dom_1.mergeModel)(model, doc, context, {
4992
5084
  mergeFormat: 'mergeAll',
4993
5085
  });
5086
+ image.isSelected = true;
5087
+ (0, roosterjs_content_model_dom_1.setSelection)(model, image);
4994
5088
  return true;
4995
5089
  }, {
4996
5090
  apiName: 'insertImage',
@@ -6303,6 +6397,7 @@ var alignTableCell_1 = __webpack_require__(/*! ../../modelApi/table/alignTableCe
6303
6397
  */
6304
6398
  function editTable(editor, operation) {
6305
6399
  editor.focus();
6400
+ fixUpSafariSelection(editor);
6306
6401
  (0, formatTableWithContentModel_1.formatTableWithContentModel)(editor, 'editTable', function (tableModel) {
6307
6402
  switch (operation) {
6308
6403
  case 'alignCellLeft':
@@ -6358,6 +6453,22 @@ function editTable(editor, operation) {
6358
6453
  });
6359
6454
  }
6360
6455
  exports.editTable = editTable;
6456
+ // In safari, when open context menu under a table, it may expand the range selection to the beginning of next table cell.
6457
+ // So we make a workaround here to collapse the selection when need, to avoid unexpected table editing behavior
6458
+ // (e.g. insert two columns but actually need one only)
6459
+ function fixUpSafariSelection(editor) {
6460
+ if (editor.getEnvironment().isSafari) {
6461
+ var selection = editor.getDOMSelection();
6462
+ if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'range' && !selection.range.collapsed) {
6463
+ selection.range.collapse(true /*toStart*/);
6464
+ editor.setDOMSelection({
6465
+ type: 'range',
6466
+ range: selection.range,
6467
+ isReverted: false,
6468
+ });
6469
+ }
6470
+ }
6471
+ }
6361
6472
 
6362
6473
 
6363
6474
  /***/ }),
@@ -6554,7 +6665,11 @@ exports.formatInsertPointWithContentModel = void 0;
6554
6665
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
6555
6666
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
6556
6667
  /**
6557
- * @internal
6668
+ * Format content model at a given insert point with a callback function
6669
+ * @param editor The editor object
6670
+ * @param insertPoint The insert point to format
6671
+ * @param callback The callback function to format the content model
6672
+ * @param options Options to control the behavior of the formatting
6558
6673
  */
6559
6674
  function formatInsertPointWithContentModel(editor, insertPoint, callback, options) {
6560
6675
  var bundle = {
@@ -6739,7 +6854,8 @@ function formatSegmentWithContentModel(editor, apiName, toggleStyleCallback, seg
6739
6854
  segmentAndParagraphs[0][0].segmentType == 'SelectionMarker';
6740
6855
  if (isCollapsedSelection) {
6741
6856
  var para_1 = segmentAndParagraphs[0][1];
6742
- segmentAndParagraphs = (0, adjustWordSelection_1.adjustWordSelection)(model, segmentAndParagraphs[0][0]).map(function (x) { return [x, para_1]; });
6857
+ var path_1 = segmentAndParagraphs[0][2];
6858
+ segmentAndParagraphs = (0, adjustWordSelection_1.adjustWordSelection)(model, segmentAndParagraphs[0][0]).map(function (x) { return [x, para_1, path_1]; });
6743
6859
  if (segmentAndParagraphs.length > 1) {
6744
6860
  isCollapsedSelection = false;
6745
6861
  }
@@ -6841,8 +6957,10 @@ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-mo
6841
6957
  * Invoke a callback to format the text segment before the selection marker using Content Model
6842
6958
  * @param editor The editor object
6843
6959
  * @param callback The callback to format the text segment.
6960
+ * @returns True if the segment before cursor is found and callback is called, otherwise false
6844
6961
  */
6845
- function formatTextSegmentBeforeSelectionMarker(editor, callback) {
6962
+ function formatTextSegmentBeforeSelectionMarker(editor, callback, options) {
6963
+ var result = false;
6846
6964
  editor.formatContentModel(function (model, context) {
6847
6965
  var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /*includeFormatHolder*/);
6848
6966
  if (selectedSegmentsAndParagraphs.length > 0 && selectedSegmentsAndParagraphs[0][1]) {
@@ -6852,12 +6970,14 @@ function formatTextSegmentBeforeSelectionMarker(editor, callback) {
6852
6970
  if (marker.segmentType === 'SelectionMarker' && markerIndex > 0) {
6853
6971
  var previousSegment = paragraph.segments[markerIndex - 1];
6854
6972
  if (previousSegment && previousSegment.segmentType === 'Text') {
6973
+ result = true;
6855
6974
  return callback(model, previousSegment, paragraph, marker.format, context);
6856
6975
  }
6857
6976
  }
6858
6977
  }
6859
6978
  return false;
6860
- });
6979
+ }, options);
6980
+ return result;
6861
6981
  }
6862
6982
  exports.formatTextSegmentBeforeSelectionMarker = formatTextSegmentBeforeSelectionMarker;
6863
6983
 
@@ -7416,16 +7536,7 @@ function isCssVariable(value) {
7416
7536
  Object.defineProperty(exports, "__esModule", ({ value: true }));
7417
7537
  exports.exportContent = void 0;
7418
7538
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
7419
- /**
7420
- * Export string content of editor
7421
- * @param editor The editor to get content from
7422
- * @param mode Mode of content to export. It supports:
7423
- * - HTML: Export HTML content. If there are entities, this will cause EntityOperation event with option = 'replaceTemporaryContent' to get a dehydrated entity
7424
- * - PlainText: Export plain text content
7425
- * - PlainTextFast: Export plain text using editor's textContent property directly
7426
- * @param options @optional Options for Model to DOM conversion
7427
- */
7428
- function exportContent(editor, mode, options) {
7539
+ function exportContent(editor, mode, optionsOrCallbacks) {
7429
7540
  if (mode === void 0) { mode = 'HTML'; }
7430
7541
  if (mode == 'PlainTextFast') {
7431
7542
  return editor.getDOMHelper().getTextContent();
@@ -7433,12 +7544,12 @@ function exportContent(editor, mode, options) {
7433
7544
  else {
7434
7545
  var model = editor.getContentModelCopy('clean');
7435
7546
  if (mode == 'PlainText') {
7436
- return (0, roosterjs_content_model_dom_1.contentModelToText)(model);
7547
+ return (0, roosterjs_content_model_dom_1.contentModelToText)(model, undefined /*separator*/, optionsOrCallbacks);
7437
7548
  }
7438
7549
  else {
7439
7550
  var doc = editor.getDocument();
7440
7551
  var div = doc.createElement('div');
7441
- (0, roosterjs_content_model_dom_1.contentModelToDom)(doc, div, model, (0, roosterjs_content_model_dom_1.createModelToDomContext)(undefined /*editorContext*/, options));
7552
+ (0, roosterjs_content_model_dom_1.contentModelToDom)(doc, div, model, (0, roosterjs_content_model_dom_1.createModelToDomContext)(undefined /*editorContext*/, optionsOrCallbacks));
7442
7553
  editor.triggerEvent('extractContentWithDom', { clonedRoot: div }, true /*broadcast*/);
7443
7554
  return div.innerHTML;
7444
7555
  }
@@ -7644,6 +7755,7 @@ function mergePasteContent(editor, eventResult, clipboardData) {
7644
7755
  }, {
7645
7756
  changeSource: roosterjs_content_model_dom_1.ChangeSource.Paste,
7646
7757
  getChangeData: function () { return clipboardData; },
7758
+ scrollCaretIntoView: true,
7647
7759
  apiName: 'paste',
7648
7760
  });
7649
7761
  }
@@ -7691,7 +7803,10 @@ function paste(editor, clipboardData, pasteType) {
7691
7803
  editor.focus();
7692
7804
  var trustedHTMLHandler = editor.getTrustedHTMLHandler();
7693
7805
  if (!clipboardData.modelBeforePaste) {
7694
- clipboardData.modelBeforePaste = (0, mergePasteContent_1.cloneModelForPaste)(editor.getContentModelCopy('connected'));
7806
+ editor.formatContentModel(function (model) {
7807
+ clipboardData.modelBeforePaste = (0, mergePasteContent_1.cloneModelForPaste)(model);
7808
+ return false;
7809
+ });
7695
7810
  }
7696
7811
  // 1. Prepare variables
7697
7812
  var doc = createDOMFromHtml(clipboardData.rawHtml, trustedHTMLHandler);
@@ -8126,6 +8241,69 @@ function getPath(node, offset, rootNode) {
8126
8241
  exports.getPath = getPath;
8127
8242
 
8128
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
+
8129
8307
  /***/ }),
8130
8308
 
8131
8309
  /***/ "./packages/roosterjs-content-model-core/lib/coreApi/attachDomEvent/attachDomEvent.ts":
@@ -8185,6 +8363,7 @@ exports.attachDomEvent = attachDomEvent;
8185
8363
  Object.defineProperty(exports, "__esModule", ({ value: true }));
8186
8364
  exports.coreApiMap = void 0;
8187
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");
8188
8367
  var attachDomEvent_1 = __webpack_require__(/*! ./attachDomEvent/attachDomEvent */ "./packages/roosterjs-content-model-core/lib/coreApi/attachDomEvent/attachDomEvent.ts");
8189
8368
  var createContentModel_1 = __webpack_require__(/*! ./createContentModel/createContentModel */ "./packages/roosterjs-content-model-core/lib/coreApi/createContentModel/createContentModel.ts");
8190
8369
  var createEditorContext_1 = __webpack_require__(/*! ./createEditorContext/createEditorContext */ "./packages/roosterjs-content-model-core/lib/coreApi/createEditorContext/createEditorContext.ts");
@@ -8219,6 +8398,7 @@ exports.coreApiMap = {
8219
8398
  switchShadowEdit: switchShadowEdit_1.switchShadowEdit,
8220
8399
  getVisibleViewport: getVisibleViewport_1.getVisibleViewport,
8221
8400
  setEditorStyle: setEditorStyle_1.setEditorStyle,
8401
+ announce: announce_1.announce,
8222
8402
  };
8223
8403
 
8224
8404
 
@@ -8247,34 +8427,33 @@ var createContentModel = function (core, option, selectionOverride) {
8247
8427
  var _a;
8248
8428
  // Flush all mutations if any, so that we can get an up-to-date Content Model
8249
8429
  (_a = core.cache.textMutationObserver) === null || _a === void 0 ? void 0 : _a.flushMutations();
8250
- var cachedModel = selectionOverride || (option && !option.tryGetFromCache) ? null : core.cache.cachedModel;
8251
- if (cachedModel && core.lifecycle.shadowEditFragment) {
8252
- // When in shadow edit, use a cloned model so we won't pollute the cached one
8253
- cachedModel = (0, roosterjs_content_model_dom_1.cloneModel)(cachedModel, { includeCachedElement: true });
8430
+ if (!selectionOverride && (!option || option.tryGetFromCache)) {
8431
+ var cachedModel = core.cache.cachedModel;
8432
+ if (cachedModel) {
8433
+ // When in shadow edit, use a cloned model so we won't pollute the cached one
8434
+ return core.lifecycle.shadowEditFragment
8435
+ ? (0, roosterjs_content_model_dom_1.cloneModel)(cachedModel, { includeCachedElement: true })
8436
+ : cachedModel;
8437
+ }
8254
8438
  }
8255
- if (cachedModel) {
8256
- return cachedModel;
8439
+ var selection = selectionOverride == 'none'
8440
+ ? undefined
8441
+ : selectionOverride || core.api.getDOMSelection(core) || undefined;
8442
+ var saveIndex = !option && !selectionOverride;
8443
+ var editorContext = core.api.createEditorContext(core, saveIndex);
8444
+ var settings = core.environment.domToModelSettings;
8445
+ var domToModelContext = option
8446
+ ? (0, roosterjs_content_model_dom_1.createDomToModelContext)(editorContext, settings.builtIn, settings.customized, option)
8447
+ : (0, roosterjs_content_model_dom_1.createDomToModelContextWithConfig)(settings.calculated, editorContext);
8448
+ if (selection) {
8449
+ domToModelContext.selection = selection;
8257
8450
  }
8258
- else {
8259
- var selection = selectionOverride == 'none'
8260
- ? undefined
8261
- : selectionOverride || core.api.getDOMSelection(core) || undefined;
8262
- var saveIndex = !option && !selectionOverride;
8263
- var editorContext = core.api.createEditorContext(core, saveIndex);
8264
- var settings = core.environment.domToModelSettings;
8265
- var domToModelContext = option
8266
- ? (0, roosterjs_content_model_dom_1.createDomToModelContext)(editorContext, settings.builtIn, settings.customized, option)
8267
- : (0, roosterjs_content_model_dom_1.createDomToModelContextWithConfig)(settings.calculated, editorContext);
8268
- if (selection) {
8269
- domToModelContext.selection = selection;
8270
- }
8271
- var model = (0, roosterjs_content_model_dom_1.domToContentModel)(core.logicalRoot, domToModelContext);
8272
- if (saveIndex) {
8273
- core.cache.cachedModel = model;
8274
- (0, updateCachedSelection_1.updateCachedSelection)(core.cache, selection);
8275
- }
8276
- return model;
8451
+ var model = (0, roosterjs_content_model_dom_1.domToContentModel)(core.logicalRoot, domToModelContext);
8452
+ if (saveIndex) {
8453
+ core.cache.cachedModel = model;
8454
+ (0, updateCachedSelection_1.updateCachedSelection)(core.cache, selection);
8277
8455
  }
8456
+ return model;
8278
8457
  };
8279
8458
  exports.createContentModel = createContentModel;
8280
8459
 
@@ -8302,17 +8481,12 @@ var createEditorContext = function (core, saveIndex) {
8302
8481
  var lifecycle = core.lifecycle, format = core.format, darkColorHandler = core.darkColorHandler, logicalRoot = core.logicalRoot, cache = core.cache, domHelper = core.domHelper;
8303
8482
  saveIndex = saveIndex && !core.lifecycle.shadowEditFragment;
8304
8483
  var context = (0, tslib_1.__assign)({ isDarkMode: lifecycle.isDarkMode, defaultFormat: format.defaultFormat, pendingFormat: (_a = format.pendingFormat) !== null && _a !== void 0 ? _a : undefined, darkColorHandler: darkColorHandler, addDelimiterForEntity: true, allowCacheElement: true, domIndexer: saveIndex ? cache.domIndexer : undefined, zoomScale: domHelper.calculateZoomScale() }, (0, getRootComputedStyleForContext_1.getRootComputedStyleForContext)(logicalRoot.ownerDocument));
8305
- checkRootRtl(logicalRoot, context);
8484
+ if (core.domHelper.isRightToLeft()) {
8485
+ context.isRootRtl = true;
8486
+ }
8306
8487
  return context;
8307
8488
  };
8308
8489
  exports.createEditorContext = createEditorContext;
8309
- function checkRootRtl(element, context) {
8310
- var _a;
8311
- var style = (_a = element === null || element === void 0 ? void 0 : element.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(element);
8312
- if ((style === null || style === void 0 ? void 0 : style.direction) == 'rtl') {
8313
- context.isRootRtl = true;
8314
- }
8315
- }
8316
8490
 
8317
8491
 
8318
8492
  /***/ }),
@@ -8399,7 +8573,7 @@ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-mo
8399
8573
  */
8400
8574
  var formatContentModel = function (core, formatter, options, domToModelOptions) {
8401
8575
  var _a;
8402
- var _b = options || {}, apiName = _b.apiName, onNodeCreated = _b.onNodeCreated, getChangeData = _b.getChangeData, changeSource = _b.changeSource, rawEvent = _b.rawEvent, selectionOverride = _b.selectionOverride;
8576
+ var _b = options || {}, apiName = _b.apiName, onNodeCreated = _b.onNodeCreated, getChangeData = _b.getChangeData, changeSource = _b.changeSource, rawEvent = _b.rawEvent, selectionOverride = _b.selectionOverride, scrollCaretIntoView = _b.scrollCaretIntoView;
8403
8577
  var model = core.api.createContentModel(core, domToModelOptions, selectionOverride);
8404
8578
  var context = {
8405
8579
  newEntities: [],
@@ -8424,6 +8598,11 @@ var formatContentModel = function (core, formatter, options, domToModelOptions)
8424
8598
  (_a = core.api.setContentModel(core, model, hasFocus ? undefined : { ignoreSelection: true }, // If editor did not have focus before format, do not set focus after format
8425
8599
  onNodeCreated)) !== null && _a !== void 0 ? _a : undefined;
8426
8600
  handlePendingFormat(core, context, selection);
8601
+ if (selection && scrollCaretIntoView) {
8602
+ var selectionRoot = (0, roosterjs_content_model_dom_1.getSelectionRootNode)(selection);
8603
+ var rootElement = selectionRoot && core.domHelper.findClosestElementAncestor(selectionRoot);
8604
+ rootElement === null || rootElement === void 0 ? void 0 : rootElement.scrollIntoView();
8605
+ }
8427
8606
  var eventData = {
8428
8607
  eventType: 'contentChanged',
8429
8608
  contentModel: clearModelCache ? undefined : model,
@@ -8460,19 +8639,19 @@ var formatContentModel = function (core, formatter, options, domToModelOptions)
8460
8639
  }
8461
8640
  handlePendingFormat(core, context, core.api.getDOMSelection(core));
8462
8641
  }
8642
+ if (context.announceData) {
8643
+ core.api.announce(core, context.announceData);
8644
+ }
8463
8645
  };
8464
8646
  exports.formatContentModel = formatContentModel;
8465
8647
  function handleImages(core, context) {
8466
8648
  if (context.newImages.length > 0) {
8467
- var viewport = core.api.getVisibleViewport(core);
8468
- if (viewport) {
8469
- var left = viewport.left, right = viewport.right;
8470
- var minMaxImageSize = 10;
8471
- var maxWidth_1 = Math.max(right - left, minMaxImageSize);
8472
- context.newImages.forEach(function (image) {
8473
- image.format.maxWidth = maxWidth_1 + "px";
8474
- });
8475
- }
8649
+ var width = core.domHelper.getClientWidth();
8650
+ var minMaxImageSize = 10;
8651
+ var maxWidth_1 = Math.max(width, minMaxImageSize);
8652
+ context.newImages.forEach(function (image) {
8653
+ image.format.maxWidth = maxWidth_1 + "px";
8654
+ });
8476
8655
  }
8477
8656
  }
8478
8657
  function handlePendingFormat(core, context, selection) {
@@ -8692,7 +8871,6 @@ exports.restoreSnapshotColors = restoreSnapshotColors;
8692
8871
  Object.defineProperty(exports, "__esModule", ({ value: true }));
8693
8872
  exports.restoreSnapshotHTML = void 0;
8694
8873
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
8695
- var BlockEntityContainer = '_E_EBlockEntityContainer';
8696
8874
  /**
8697
8875
  * @internal
8698
8876
  */
@@ -8744,22 +8922,19 @@ function tryGetEntityElement(entityMap, node) {
8744
8922
  var format = (0, roosterjs_content_model_dom_1.parseEntityFormat)(node);
8745
8923
  result = getEntityWrapperForReuse(entityMap, format.id);
8746
8924
  }
8747
- else if (isBlockEntityContainer(node)) {
8925
+ else if ((0, roosterjs_content_model_dom_1.isBlockEntityContainer)(node)) {
8748
8926
  result = tryGetEntityFromContainer(node, entityMap);
8749
8927
  }
8750
8928
  }
8751
8929
  return result;
8752
8930
  }
8753
- function isBlockEntityContainer(node) {
8754
- return node.classList.contains(BlockEntityContainer);
8755
- }
8756
8931
  function tryGetEntityFromContainer(element, entityMap) {
8757
8932
  var _a;
8758
8933
  for (var node = element.firstChild; node; node = node.nextSibling) {
8759
8934
  if ((0, roosterjs_content_model_dom_1.isEntityElement)(node) && (0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'ELEMENT_NODE')) {
8760
8935
  var format = (0, roosterjs_content_model_dom_1.parseEntityFormat)(node);
8761
8936
  var parent_1 = (_a = getEntityWrapperForReuse(entityMap, format.id)) === null || _a === void 0 ? void 0 : _a.parentElement;
8762
- return (0, roosterjs_content_model_dom_1.isNodeOfType)(parent_1, 'ELEMENT_NODE') && isBlockEntityContainer(parent_1)
8937
+ return (0, roosterjs_content_model_dom_1.isNodeOfType)(parent_1, 'ELEMENT_NODE') && (0, roosterjs_content_model_dom_1.isBlockEntityContainer)(parent_1)
8763
8938
  ? parent_1
8764
8939
  : null;
8765
8940
  }
@@ -9120,7 +9295,7 @@ var TABLE_ID = 'table';
9120
9295
  var DEFAULT_SELECTION_BORDER_COLOR = '#DB626C';
9121
9296
  var TABLE_CSS_RULE = 'background-color:#C6C6C6!important;';
9122
9297
  var CARET_CSS_RULE = 'caret-color: transparent';
9123
- var TRANSPARENT_SELECTION_CSS_RULE = 'background-color: transparent !important';
9298
+ var TRANSPARENT_SELECTION_CSS_RULE = 'background-color: transparent !important;';
9124
9299
  var SELECTION_SELECTOR = '*::selection';
9125
9300
  /**
9126
9301
  * @internal
@@ -9138,9 +9313,12 @@ var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
9138
9313
  try {
9139
9314
  switch (selection === null || selection === void 0 ? void 0 : selection.type) {
9140
9315
  case 'image':
9141
- var image = selection.image;
9142
- core.selection.selection = selection;
9143
- 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)]);
9316
+ var image = ensureImageHasSpanParent(selection.image);
9317
+ core.selection.selection = {
9318
+ type: 'image',
9319
+ image: image,
9320
+ };
9321
+ core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, "outline-style:auto!important; outline-color:" + (core.selection.imageSelectionBorderColor || DEFAULT_SELECTION_BORDER_COLOR) + "!important;", ["span:has(>img#" + (0, ensureUniqueId_1.ensureUniqueId)(image, IMAGE_ID) + ")"]);
9144
9322
  core.api.setEditorStyle(core, HIDE_SELECTION_CSS_KEY, TRANSPARENT_SELECTION_CSS_RULE, [SELECTION_SELECTOR]);
9145
9323
  setRangeSelection(doc, image, false /* collapse */);
9146
9324
  break;
@@ -9271,6 +9449,18 @@ function setRangeSelection(doc, element, collapse) {
9271
9449
  (0, addRangeToSelection_1.addRangeToSelection)(doc, range, isReverted);
9272
9450
  }
9273
9451
  }
9452
+ function ensureImageHasSpanParent(image) {
9453
+ var parent = image.parentElement;
9454
+ if (parent &&
9455
+ (0, roosterjs_content_model_dom_1.isNodeOfType)(parent, 'ELEMENT_NODE') &&
9456
+ (0, roosterjs_content_model_dom_1.isElementOfType)(parent, 'span') &&
9457
+ parent.firstChild == image &&
9458
+ parent.lastChild == image) {
9459
+ return image;
9460
+ }
9461
+ (0, roosterjs_content_model_dom_1.wrap)(image.ownerDocument, image, 'span');
9462
+ return image;
9463
+ }
9274
9464
 
9275
9465
 
9276
9466
  /***/ }),
@@ -9811,11 +10001,15 @@ function reconcileSelection(model, newSelection, oldSelection) {
9811
10001
  var newRange = newSelection.range;
9812
10002
  if (newRange) {
9813
10003
  var startContainer = newRange.startContainer, startOffset = newRange.startOffset, endContainer = newRange.endContainer, endOffset = newRange.endOffset, collapsed = newRange.collapsed;
10004
+ delete model.hasRevertedRangeSelection;
9814
10005
  if (collapsed) {
9815
10006
  return !!reconcileNodeSelection(startContainer, startOffset);
9816
10007
  }
9817
10008
  else if (startContainer == endContainer &&
9818
10009
  (0, roosterjs_content_model_dom_1.isNodeOfType)(startContainer, 'TEXT_NODE')) {
10010
+ if (newSelection.isReverted) {
10011
+ model.hasRevertedRangeSelection = true;
10012
+ }
9819
10013
  return (isIndexedSegment(startContainer) &&
9820
10014
  !!reconcileTextSelection(startContainer, startOffset, endOffset));
9821
10015
  }
@@ -9823,6 +10017,9 @@ function reconcileSelection(model, newSelection, oldSelection) {
9823
10017
  var marker1 = reconcileNodeSelection(startContainer, startOffset);
9824
10018
  var marker2 = reconcileNodeSelection(endContainer, endOffset);
9825
10019
  if (marker1 && marker2) {
10020
+ if (newSelection.isReverted) {
10021
+ model.hasRevertedRangeSelection = true;
10022
+ }
9826
10023
  (0, roosterjs_content_model_dom_1.setSelection)(model, marker1, marker2);
9827
10024
  return true;
9828
10025
  }
@@ -10286,8 +10483,8 @@ var CopyPastePlugin = /** @class */ (function () {
10286
10483
  return;
10287
10484
  }
10288
10485
  cleanUpAndRestoreSelection(tempDiv_1);
10289
- _this.editor.focus();
10290
10486
  _this.editor.setDOMSelection(selection);
10487
+ _this.editor.focus();
10291
10488
  if (isCut) {
10292
10489
  _this.editor.formatContentModel(function (model, context) {
10293
10490
  if ((0, roosterjs_content_model_dom_1.deleteSelection)(model, [deleteEmptyList_1.deleteEmptyList], context)
@@ -10954,6 +11151,123 @@ function createEntityPlugin() {
10954
11151
  exports.createEntityPlugin = createEntityPlugin;
10955
11152
 
10956
11153
 
11154
+ /***/ }),
11155
+
11156
+ /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/entity/adjustSelectionAroundEntity.ts":
11157
+ /*!****************************************************************************************************!*\
11158
+ !*** ./packages/roosterjs-content-model-core/lib/corePlugin/entity/adjustSelectionAroundEntity.ts ***!
11159
+ \****************************************************************************************************/
11160
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
11161
+
11162
+ "use strict";
11163
+
11164
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
11165
+ exports.adjustSelectionAroundEntity = void 0;
11166
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
11167
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
11168
+ /**
11169
+ * @internal
11170
+ */
11171
+ function adjustSelectionAroundEntity(editor, key, shiftKey) {
11172
+ var _a;
11173
+ var selection = editor.isDisposed() ? null : editor.getDOMSelection();
11174
+ if (!selection || selection.type != 'range') {
11175
+ return;
11176
+ }
11177
+ var range = selection.range, isReverted = selection.isReverted;
11178
+ var anchorNode = isReverted ? range.startContainer : range.endContainer;
11179
+ var offset = isReverted ? range.startOffset : range.endOffset;
11180
+ var delimiter = (0, roosterjs_content_model_dom_1.isNodeOfType)(anchorNode, 'ELEMENT_NODE')
11181
+ ? anchorNode
11182
+ : anchorNode.parentElement;
11183
+ var isRtl = delimiter &&
11184
+ ((_a = editor.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(delimiter).direction) == 'rtl';
11185
+ var movingBefore = (key == 'ArrowLeft') != !!isRtl;
11186
+ if (delimiter &&
11187
+ (((0, roosterjs_content_model_dom_1.isEntityDelimiter)(delimiter, !movingBefore) &&
11188
+ ((movingBefore && offset == 0) || (!movingBefore && offset == 1))) ||
11189
+ (0, roosterjs_content_model_dom_1.isBlockEntityContainer)(delimiter))) {
11190
+ editor.formatContentModel(function (model) {
11191
+ var _a, _b;
11192
+ var allSel = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /*includingFormatHolder*/, true /*includingEntity*/);
11193
+ var sel = allSel[isReverted ? 0 : allSel.length - 1];
11194
+ 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;
11195
+ if (sel && sel[1] && index >= 0) {
11196
+ var _c = (0, tslib_1.__read)(sel, 3), segment = _c[0], paragraph = _c[1], path = _c[2];
11197
+ var isShrinking = shiftKey && !range.collapsed && movingBefore != !!isReverted;
11198
+ var entitySegment = isShrinking
11199
+ ? segment
11200
+ : paragraph.segments[movingBefore ? index - 1 : index + 1];
11201
+ var pairedDelimiter = findPairedDelimiter(entitySegment, path, paragraph, movingBefore);
11202
+ if (pairedDelimiter) {
11203
+ var newRange = getNewRange(range, isShrinking, movingBefore, pairedDelimiter, shiftKey);
11204
+ editor.setDOMSelection({
11205
+ type: 'range',
11206
+ range: newRange,
11207
+ isReverted: newRange.collapsed ? false : isReverted,
11208
+ });
11209
+ }
11210
+ }
11211
+ return false;
11212
+ });
11213
+ }
11214
+ }
11215
+ exports.adjustSelectionAroundEntity = adjustSelectionAroundEntity;
11216
+ function getNewRange(originalRange, isShrinking, movingBefore, pairedDelimiter, shiftKey) {
11217
+ var newRange = originalRange.cloneRange();
11218
+ if (isShrinking) {
11219
+ if (movingBefore) {
11220
+ newRange.setEndBefore(pairedDelimiter);
11221
+ }
11222
+ else {
11223
+ newRange.setStartAfter(pairedDelimiter);
11224
+ }
11225
+ }
11226
+ else {
11227
+ if (movingBefore) {
11228
+ newRange.setStartBefore(pairedDelimiter);
11229
+ }
11230
+ else {
11231
+ newRange.setEndAfter(pairedDelimiter);
11232
+ }
11233
+ if (!shiftKey) {
11234
+ if (movingBefore) {
11235
+ newRange.setEndBefore(pairedDelimiter);
11236
+ }
11237
+ else {
11238
+ newRange.setStartAfter(pairedDelimiter);
11239
+ }
11240
+ }
11241
+ }
11242
+ return newRange;
11243
+ }
11244
+ function findPairedDelimiter(entitySegment, path, paragraph, movingBefore) {
11245
+ var entity = null;
11246
+ if ((entitySegment === null || entitySegment === void 0 ? void 0 : entitySegment.segmentType) == 'Entity') {
11247
+ // Inline entity
11248
+ entity = entitySegment;
11249
+ }
11250
+ else {
11251
+ // Block entity
11252
+ var blocks = path[0].blocks;
11253
+ var paraIndex = blocks.indexOf(paragraph);
11254
+ var entityBlock = paraIndex >= 0 ? blocks[movingBefore ? paraIndex - 1 : paraIndex + 1] : null;
11255
+ if ((entityBlock === null || entityBlock === void 0 ? void 0 : entityBlock.blockType) == 'Entity') {
11256
+ entity = entityBlock;
11257
+ }
11258
+ }
11259
+ var pairedDelimiter = entity
11260
+ ? movingBefore
11261
+ ? entity.wrapper.previousElementSibling
11262
+ : entity.wrapper.nextElementSibling
11263
+ : null;
11264
+ return (0, roosterjs_content_model_dom_1.isNodeOfType)(pairedDelimiter, 'ELEMENT_NODE') &&
11265
+ (0, roosterjs_content_model_dom_1.isEntityDelimiter)(pairedDelimiter, movingBefore)
11266
+ ? pairedDelimiter
11267
+ : null;
11268
+ }
11269
+
11270
+
10957
11271
  /***/ }),
10958
11272
 
10959
11273
  /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/entity/entityDelimiterUtils.ts":
@@ -10967,6 +11281,7 @@ exports.createEntityPlugin = createEntityPlugin;
10967
11281
  Object.defineProperty(exports, "__esModule", ({ value: true }));
10968
11282
  exports.handleEnterInlineEntity = exports.handleKeyDownInBlockDelimiter = exports.handleDelimiterKeyDownEvent = exports.handleCompositionEndEvent = exports.handleDelimiterContentChangedEvent = exports.preventTypeInDelimiter = void 0;
10969
11283
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
11284
+ var adjustSelectionAroundEntity_1 = __webpack_require__(/*! ./adjustSelectionAroundEntity */ "./packages/roosterjs-content-model-core/lib/corePlugin/entity/adjustSelectionAroundEntity.ts");
10970
11285
  var normalizePos_1 = __webpack_require__(/*! ../selection/normalizePos */ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/normalizePos.ts");
10971
11286
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
10972
11287
  var DelimiterBefore = 'entityDelimiterBefore';
@@ -10975,8 +11290,6 @@ var DelimiterSelector = '.' + DelimiterAfter + ',.' + DelimiterBefore;
10975
11290
  var ZeroWidthSpace = '\u200B';
10976
11291
  var EntityInfoName = '_Entity';
10977
11292
  var InlineEntitySelector = 'span.' + EntityInfoName;
10978
- var BlockEntityContainer = '_E_EBlockEntityContainer';
10979
- var BlockEntityContainerSelector = '.' + BlockEntityContainer;
10980
11293
  /**
10981
11294
  * @internal exported only for unit test
10982
11295
  */
@@ -11118,61 +11431,86 @@ exports.handleCompositionEndEvent = handleCompositionEndEvent;
11118
11431
  function handleDelimiterKeyDownEvent(editor, event) {
11119
11432
  var _a;
11120
11433
  var selection = editor.getDOMSelection();
11121
- var rawEvent = event.rawEvent;
11122
11434
  if (!selection || selection.type != 'range') {
11123
11435
  return;
11124
11436
  }
11125
- var isEnter = rawEvent.key === 'Enter';
11126
- var helper = editor.getDOMHelper();
11127
- if (selection.range.collapsed && ((0, roosterjs_content_model_dom_1.isCharacterValue)(rawEvent) || isEnter)) {
11128
- var helper_1 = editor.getDOMHelper();
11129
- var node_1 = getFocusedElement(selection);
11130
- if (node_1 && (0, roosterjs_content_model_dom_1.isEntityDelimiter)(node_1) && helper_1.isNodeInEditor(node_1)) {
11131
- var blockEntityContainer = node_1.closest(BlockEntityContainerSelector);
11132
- if (blockEntityContainer && helper_1.isNodeInEditor(blockEntityContainer)) {
11133
- var isAfter = node_1.classList.contains(DelimiterAfter);
11134
- if (isAfter) {
11135
- selection.range.setStartAfter(blockEntityContainer);
11136
- }
11137
- else {
11138
- selection.range.setStartBefore(blockEntityContainer);
11139
- }
11140
- selection.range.collapse(true /* toStart */);
11141
- if (isEnter) {
11142
- event.rawEvent.preventDefault();
11437
+ var rawEvent = event.rawEvent;
11438
+ var range = selection.range;
11439
+ var key = rawEvent.key;
11440
+ switch (key) {
11441
+ case 'Enter':
11442
+ if (range.collapsed) {
11443
+ handleInputOnDelimiter(editor, range, getFocusedElement(selection), rawEvent);
11444
+ }
11445
+ else {
11446
+ var helper = editor.getDOMHelper();
11447
+ var entity = (0, roosterjs_content_model_dom_1.findClosestEntityWrapper)(range.startContainer, helper);
11448
+ if (entity &&
11449
+ (0, roosterjs_content_model_dom_1.isNodeOfType)(entity, 'ELEMENT_NODE') &&
11450
+ helper.isNodeInEditor(entity)) {
11451
+ triggerEntityEventOnEnter(editor, entity, rawEvent);
11143
11452
  }
11144
- editor.formatContentModel(exports.handleKeyDownInBlockDelimiter, {
11145
- selectionOverride: {
11146
- type: 'range',
11147
- isReverted: false,
11148
- range: selection.range,
11149
- },
11453
+ }
11454
+ break;
11455
+ case 'ArrowLeft':
11456
+ case 'ArrowRight':
11457
+ if (!rawEvent.altKey && !rawEvent.ctrlKey && !rawEvent.metaKey) {
11458
+ // Handle in async so focus is already moved, this makes us easier to check if we should adjust the selection
11459
+ (_a = editor.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.requestAnimationFrame(function () {
11460
+ (0, adjustSelectionAroundEntity_1.adjustSelectionAroundEntity)(editor, key, rawEvent.shiftKey);
11150
11461
  });
11151
11462
  }
11463
+ break;
11464
+ default:
11465
+ if ((0, roosterjs_content_model_dom_1.isCharacterValue)(rawEvent) && range.collapsed) {
11466
+ handleInputOnDelimiter(editor, range, getFocusedElement(selection), rawEvent);
11467
+ }
11468
+ break;
11469
+ }
11470
+ }
11471
+ exports.handleDelimiterKeyDownEvent = handleDelimiterKeyDownEvent;
11472
+ function handleInputOnDelimiter(editor, range, focusedNode, rawEvent) {
11473
+ var _a;
11474
+ var helper = editor.getDOMHelper();
11475
+ if (focusedNode && (0, roosterjs_content_model_dom_1.isEntityDelimiter)(focusedNode) && helper.isNodeInEditor(focusedNode)) {
11476
+ var blockEntityContainer = (0, roosterjs_content_model_dom_1.findClosestBlockEntityContainer)(focusedNode, helper);
11477
+ var isEnter = rawEvent.key === 'Enter';
11478
+ if (blockEntityContainer && helper.isNodeInEditor(blockEntityContainer)) {
11479
+ var isAfter = focusedNode.classList.contains(DelimiterAfter);
11480
+ if (isAfter) {
11481
+ range.setStartAfter(blockEntityContainer);
11482
+ }
11152
11483
  else {
11153
- if (isEnter) {
11154
- event.rawEvent.preventDefault();
11155
- editor.formatContentModel(exports.handleEnterInlineEntity);
11156
- }
11157
- else {
11158
- editor.takeSnapshot();
11159
- (_a = editor
11160
- .getDocument()
11161
- .defaultView) === null || _a === void 0 ? void 0 : _a.requestAnimationFrame(function () {
11162
- return preventTypeInDelimiter(node_1, editor);
11163
- });
11164
- }
11484
+ range.setStartBefore(blockEntityContainer);
11165
11485
  }
11486
+ range.collapse(true /* toStart */);
11487
+ if (isEnter) {
11488
+ rawEvent.preventDefault();
11489
+ }
11490
+ editor.formatContentModel(exports.handleKeyDownInBlockDelimiter, {
11491
+ selectionOverride: {
11492
+ type: 'range',
11493
+ isReverted: false,
11494
+ range: range,
11495
+ },
11496
+ });
11166
11497
  }
11167
- }
11168
- else if (isEnter) {
11169
- var entity = (0, roosterjs_content_model_dom_1.findClosestEntityWrapper)(selection.range.startContainer, helper);
11170
- if (entity && (0, roosterjs_content_model_dom_1.isNodeOfType)(entity, 'ELEMENT_NODE') && helper.isNodeInEditor(entity)) {
11171
- triggerEntityEventOnEnter(editor, entity, rawEvent);
11498
+ else {
11499
+ if (isEnter) {
11500
+ rawEvent.preventDefault();
11501
+ editor.formatContentModel(exports.handleEnterInlineEntity);
11502
+ }
11503
+ else {
11504
+ editor.takeSnapshot();
11505
+ (_a = editor
11506
+ .getDocument()
11507
+ .defaultView) === null || _a === void 0 ? void 0 : _a.requestAnimationFrame(function () {
11508
+ return preventTypeInDelimiter(focusedNode, editor);
11509
+ });
11510
+ }
11172
11511
  }
11173
11512
  }
11174
11513
  }
11175
- exports.handleDelimiterKeyDownEvent = handleDelimiterKeyDownEvent;
11176
11514
  /**
11177
11515
  * @internal Exported Only for unit test
11178
11516
  * @returns
@@ -11667,6 +12005,7 @@ var LifecyclePlugin = /** @class */ (function () {
11667
12005
  isDarkMode: !!options.inDarkMode,
11668
12006
  shadowEditFragment: null,
11669
12007
  styleElements: {},
12008
+ announcerStringGetter: options.announcerStringGetter,
11670
12009
  };
11671
12010
  }
11672
12011
  /**
@@ -11694,7 +12033,7 @@ var LifecyclePlugin = /** @class */ (function () {
11694
12033
  */
11695
12034
  LifecyclePlugin.prototype.dispose = function () {
11696
12035
  var _this = this;
11697
- var _a;
12036
+ var _a, _b;
11698
12037
  (_a = this.editor) === null || _a === void 0 ? void 0 : _a.triggerEvent('beforeDispose', {}, true /*broadcast*/);
11699
12038
  (0, roosterjs_content_model_dom_1.getObjectKeys)(this.state.styleElements).forEach(function (key) {
11700
12039
  var _a;
@@ -11702,6 +12041,11 @@ var LifecyclePlugin = /** @class */ (function () {
11702
12041
  (_a = element.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(element);
11703
12042
  delete _this.state.styleElements[key];
11704
12043
  });
12044
+ var announceContainer = this.state.announceContainer;
12045
+ if (announceContainer) {
12046
+ (_b = announceContainer.parentElement) === null || _b === void 0 ? void 0 : _b.removeChild(announceContainer);
12047
+ delete this.state.announceContainer;
12048
+ }
11705
12049
  if (this.disposer) {
11706
12050
  this.disposer();
11707
12051
  this.disposer = null;
@@ -12085,14 +12429,14 @@ var SelectionPlugin = /** @class */ (function () {
12085
12429
  return rawEvent.shiftKey ? 'TabLeft' : 'TabRight';
12086
12430
  };
12087
12431
  SelectionPlugin.prototype.handleSelectionInTable = function (key) {
12088
- var _a, _b, _c, _d;
12432
+ var _a, _b, _c, _d, _e, _f;
12089
12433
  if (!this.editor || !this.state.tableSelection) {
12090
12434
  return;
12091
12435
  }
12092
12436
  var selection = this.editor.getDOMSelection();
12093
12437
  var domHelper = this.editor.getDOMHelper();
12094
12438
  if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'range') {
12095
- var _e = selection.range, collapsed = _e.collapsed, startContainer = _e.startContainer, endContainer = _e.endContainer, commonAncestorContainer = _e.commonAncestorContainer, isReverted = selection.isReverted;
12439
+ var _g = selection.range, collapsed = _g.collapsed, startContainer = _g.startContainer, endContainer = _g.endContainer, commonAncestorContainer = _g.commonAncestorContainer, isReverted = selection.isReverted;
12096
12440
  var start = isReverted ? endContainer : startContainer;
12097
12441
  var end = isReverted ? startContainer : endContainer;
12098
12442
  var tableSel = this.parseTableSelection(commonAncestorContainer, start, domHelper);
@@ -12100,7 +12444,7 @@ var SelectionPlugin = /** @class */ (function () {
12100
12444
  return;
12101
12445
  }
12102
12446
  var lastCo = (0, findCoordinate_1.findCoordinate)(tableSel === null || tableSel === void 0 ? void 0 : tableSel.parsedTable, end, domHelper);
12103
- var _f = this.state.tableSelection, parsedTable = _f.parsedTable, oldCo = _f.firstCo, table = _f.table;
12447
+ var _h = this.state.tableSelection, parsedTable = _h.parsedTable, oldCo = _h.firstCo, table = _h.table;
12104
12448
  if (lastCo && tableSel.table == table) {
12105
12449
  if (lastCo.col != oldCo.col && (key == Up || key == Down)) {
12106
12450
  var change = key == Up ? -1 : 1;
@@ -12138,6 +12482,8 @@ var SelectionPlugin = /** @class */ (function () {
12138
12482
  var cell = parsedTable[row][col];
12139
12483
  if (typeof cell != 'string') {
12140
12484
  this.setRangeSelectionInTable(cell, 0, this.editor);
12485
+ lastCo.row = row;
12486
+ lastCo.col = col;
12141
12487
  break;
12142
12488
  }
12143
12489
  }
@@ -12145,6 +12491,13 @@ var SelectionPlugin = /** @class */ (function () {
12145
12491
  else {
12146
12492
  this.state.tableSelection = null;
12147
12493
  }
12494
+ if (collapsed &&
12495
+ (lastCo.col != oldCo.col || lastCo.row != oldCo.row) &&
12496
+ lastCo.row >= 0 &&
12497
+ lastCo.row == parsedTable.length - 1 &&
12498
+ lastCo.col == ((_e = parsedTable[lastCo.row]) === null || _e === void 0 ? void 0 : _e.length) - 1) {
12499
+ (_f = this.editor) === null || _f === void 0 ? void 0 : _f.announce({ defaultStrings: 'announceOnFocusLastCell' });
12500
+ }
12148
12501
  }
12149
12502
  if (!collapsed && lastCo) {
12150
12503
  this.state.tableSelection = tableSel;
@@ -12658,6 +13011,11 @@ var UndoPlugin = /** @class */ (function () {
12658
13011
  case 'beforeKeyboardEditing':
12659
13012
  this.onBeforeKeyboardEditing(event.rawEvent);
12660
13013
  break;
13014
+ case 'mouseDown':
13015
+ if (this.state.snapshotsManager.hasNewContent) {
13016
+ this.addUndoSnapshot();
13017
+ }
13018
+ break;
12661
13019
  }
12662
13020
  };
12663
13021
  UndoPlugin.prototype.onKeyDown = function (editor, evt) {
@@ -12855,9 +13213,6 @@ var Editor = /** @class */ (function () {
12855
13213
  /**
12856
13214
  * Create Content Model from DOM tree in this editor
12857
13215
  * @param mode What kind of Content Model we want. Currently we support the following values:
12858
- * - connected: Returns a connect Content Model object. "Connected" means if there is any entity inside editor, the returned Content Model will
12859
- * contain the same wrapper element for entity. This option should only be used in some special cases. In most cases we should use "disconnected"
12860
- * to get a fully disconnected Content Model so that any change to the model will not impact editor content.
12861
13216
  * - disconnected: Returns a disconnected clone of Content Model from editor which you can do any change on it and it won't impact the editor content.
12862
13217
  * If there is any entity in editor, the returned object will contain cloned copy of entity wrapper element.
12863
13218
  * If editor is in dark mode, the cloned entity will be converted back to light mode.
@@ -12867,10 +13222,7 @@ var Editor = /** @class */ (function () {
12867
13222
  Editor.prototype.getContentModelCopy = function (mode) {
12868
13223
  var core = this.getCore();
12869
13224
  switch (mode) {
12870
- case 'connected':
12871
- return core.api.createContentModel(core, {
12872
- tryGetFromCache: true, // Pass an option here to force disable save index
12873
- });
13225
+ case 'connected': // Get a connected model is deprecated. Now we will always return disconnected model
12874
13226
  case 'disconnected':
12875
13227
  return (0, roosterjs_content_model_dom_1.cloneModel)(core.api.createContentModel(core, {
12876
13228
  processorOverride: {
@@ -13097,6 +13449,14 @@ var Editor = /** @class */ (function () {
13097
13449
  var core = this.getCore();
13098
13450
  core.api.setEditorStyle(core, key, cssRule, subSelectors);
13099
13451
  };
13452
+ /**
13453
+ * Announce the given data
13454
+ * @param announceData Data to announce
13455
+ */
13456
+ Editor.prototype.announce = function (announceData) {
13457
+ var core = this.getCore();
13458
+ core.api.announce(core, announceData);
13459
+ };
13100
13460
  /**
13101
13461
  * @returns the current EditorCore object
13102
13462
  * @throws a standard Error if there's no core object
@@ -13177,6 +13537,26 @@ var DOMHelperImpl = /** @class */ (function () {
13177
13537
  var activeElement = this.contentDiv.ownerDocument.activeElement;
13178
13538
  return !!(activeElement && this.contentDiv.contains(activeElement));
13179
13539
  };
13540
+ /**
13541
+ * Check if the root element is in RTL mode
13542
+ */
13543
+ DOMHelperImpl.prototype.isRightToLeft = function () {
13544
+ var _a;
13545
+ var contentDiv = this.contentDiv;
13546
+ var style = (_a = contentDiv.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(contentDiv);
13547
+ return (style === null || style === void 0 ? void 0 : style.direction) == 'rtl';
13548
+ };
13549
+ /**
13550
+ * Get the width of the editable area of the editor content div
13551
+ */
13552
+ DOMHelperImpl.prototype.getClientWidth = function () {
13553
+ var _a;
13554
+ var contentDiv = this.contentDiv;
13555
+ var style = (_a = contentDiv.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(contentDiv);
13556
+ var paddingLeft = (0, roosterjs_content_model_dom_1.parseValueWithUnit)(style === null || style === void 0 ? void 0 : style.paddingLeft);
13557
+ var paddingRight = (0, roosterjs_content_model_dom_1.parseValueWithUnit)(style === null || style === void 0 ? void 0 : style.paddingRight);
13558
+ return this.contentDiv.clientWidth - (paddingLeft + paddingRight);
13559
+ };
13180
13560
  return DOMHelperImpl;
13181
13561
  }());
13182
13562
  /**
@@ -13467,94 +13847,23 @@ exports.containerSizeFormatParser = containerSizeFormatParser;
13467
13847
 
13468
13848
  Object.defineProperty(exports, "__esModule", ({ value: true }));
13469
13849
  exports.listLevelMetadataApplier = exports.listItemMetadataApplier = void 0;
13470
- var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
13471
13850
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
13472
- var DefaultOrderedListStyles = ['decimal', 'lower-alpha', 'lower-roman'];
13473
- var DefaultUnorderedListStyles = ['disc', 'circle', 'square'];
13474
13851
  var OrderedMapPlaceholderRegex = /\$\{(\w+)\}/;
13475
- var CharCodeOfA = 65;
13476
- var RomanValues = {
13477
- M: 1000,
13478
- CM: 900,
13479
- D: 500,
13480
- CD: 400,
13481
- C: 100,
13482
- XC: 90,
13483
- L: 50,
13484
- XL: 40,
13485
- X: 10,
13486
- IX: 9,
13487
- V: 5,
13488
- IV: 4,
13489
- I: 1,
13490
- };
13491
- function getOrderedListStyleValue(template, listNumber) {
13492
- return template
13493
- ? template.replace(OrderedMapPlaceholderRegex, function (_, subStr) {
13494
- switch (subStr) {
13495
- case 'Number':
13496
- return listNumber + '';
13497
- case 'LowerAlpha':
13498
- return convertDecimalsToAlpha(listNumber, true /*isLowerCase*/);
13499
- case 'UpperAlpha':
13500
- return convertDecimalsToAlpha(listNumber, false /*isLowerCase*/);
13501
- case 'LowerRoman':
13502
- return convertDecimalsToRoman(listNumber, true /*isLowerCase*/);
13503
- case 'UpperRoman':
13504
- return convertDecimalsToRoman(listNumber, false /*isLowerCase*/);
13505
- }
13506
- return '';
13507
- })
13508
- : undefined;
13509
- }
13510
- function convertDecimalsToAlpha(decimal, isLowerCase) {
13511
- var alpha = '';
13512
- decimal--;
13513
- while (decimal >= 0) {
13514
- alpha = String.fromCharCode((decimal % 26) + CharCodeOfA) + alpha;
13515
- decimal = Math.floor(decimal / 26) - 1;
13852
+ function getListStyleValue(listType, listStyleType, listNumber) {
13853
+ if (listType == 'OL') {
13854
+ var numberStr = (0, roosterjs_content_model_dom_1.getOrderedListNumberStr)(listStyleType, listNumber !== null && listNumber !== void 0 ? listNumber : 1);
13855
+ var template = roosterjs_content_model_dom_1.OrderedListStyleMap[listStyleType];
13856
+ return template ? template.replace(OrderedMapPlaceholderRegex, numberStr) : undefined;
13857
+ }
13858
+ else {
13859
+ return roosterjs_content_model_dom_1.UnorderedListStyleMap[listStyleType];
13516
13860
  }
13517
- return isLowerCase ? alpha.toLowerCase() : alpha;
13518
13861
  }
13519
- function convertDecimalsToRoman(decimal, isLowerCase) {
13520
- var e_1, _a;
13521
- var romanValue = '';
13522
- try {
13523
- for (var _b = (0, tslib_1.__values)((0, roosterjs_content_model_dom_1.getObjectKeys)(RomanValues)), _c = _b.next(); !_c.done; _c = _b.next()) {
13524
- var i = _c.value;
13525
- var timesRomanCharAppear = Math.floor(decimal / RomanValues[i]);
13526
- decimal = decimal - timesRomanCharAppear * RomanValues[i];
13527
- romanValue = romanValue + i.repeat(timesRomanCharAppear);
13528
- }
13529
- }
13530
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
13531
- finally {
13532
- try {
13533
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
13534
- }
13535
- finally { if (e_1) throw e_1.error; }
13536
- }
13537
- return isLowerCase ? romanValue.toLocaleLowerCase() : romanValue;
13538
- }
13539
- function shouldApplyToItem(listStyleType) {
13540
- return listStyleType.indexOf('"') >= 0;
13541
- }
13542
- function getRawListStyleType(listType, metadata, depth) {
13543
- var orderedStyleType = metadata.orderedStyleType, unorderedStyleType = metadata.unorderedStyleType, applyListStyleFromLevel = metadata.applyListStyleFromLevel;
13544
- if (listType == 'OL') {
13545
- return typeof orderedStyleType == 'number'
13546
- ? roosterjs_content_model_dom_1.OrderedListStyleMap[orderedStyleType]
13547
- : applyListStyleFromLevel
13548
- ? DefaultOrderedListStyles[depth % DefaultOrderedListStyles.length]
13549
- : undefined;
13550
- }
13551
- else {
13552
- return typeof unorderedStyleType == 'number'
13553
- ? roosterjs_content_model_dom_1.UnorderedListStyleMap[unorderedStyleType]
13554
- : applyListStyleFromLevel
13555
- ? DefaultUnorderedListStyles[depth % DefaultUnorderedListStyles.length]
13556
- : undefined;
13557
- }
13862
+ function shouldApplyToItem(listStyleType, listType) {
13863
+ var style = listType == 'OL'
13864
+ ? roosterjs_content_model_dom_1.OrderedListStyleMap[listStyleType]
13865
+ : roosterjs_content_model_dom_1.UnorderedListStyleMap[listStyleType];
13866
+ return (style === null || style === void 0 ? void 0 : style.indexOf('"')) >= 0;
13558
13867
  }
13559
13868
  /**
13560
13869
  * @internal
@@ -13566,13 +13875,10 @@ exports.listItemMetadataApplier = {
13566
13875
  var depth = context.listFormat.nodeStack.length - 2; // Minus two for the parent element and convert length to index
13567
13876
  if (depth >= 0) {
13568
13877
  var listType = (_a = context.listFormat.nodeStack[depth + 1].listType) !== null && _a !== void 0 ? _a : 'OL';
13569
- var listStyleType = getRawListStyleType(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13570
- if (listStyleType) {
13571
- if (shouldApplyToItem(listStyleType)) {
13572
- format.listStyleType =
13573
- listType == 'OL'
13574
- ? getOrderedListStyleValue(listStyleType, context.listFormat.threadItemCounts[depth])
13575
- : listStyleType;
13878
+ var listStyleType = (0, roosterjs_content_model_dom_1.getAutoListStyleType)(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13879
+ if (listStyleType !== undefined) {
13880
+ if (shouldApplyToItem(listStyleType, listType)) {
13881
+ format.listStyleType = getListStyleValue(listType, listStyleType, context.listFormat.threadItemCounts[depth]);
13576
13882
  }
13577
13883
  else {
13578
13884
  delete format.listStyleType;
@@ -13591,10 +13897,13 @@ exports.listLevelMetadataApplier = {
13591
13897
  var depth = context.listFormat.nodeStack.length - 2; // Minus two for the parent element and convert length to index
13592
13898
  if (depth >= 0) {
13593
13899
  var listType = (_a = context.listFormat.nodeStack[depth + 1].listType) !== null && _a !== void 0 ? _a : 'OL';
13594
- var listStyleType = getRawListStyleType(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13595
- if (listStyleType) {
13596
- if (!shouldApplyToItem(listStyleType)) {
13597
- format.listStyleType = listStyleType;
13900
+ var listStyleType = (0, roosterjs_content_model_dom_1.getAutoListStyleType)(listType, metadata !== null && metadata !== void 0 ? metadata : {}, depth);
13901
+ if (listStyleType !== undefined) {
13902
+ if (!shouldApplyToItem(listStyleType, listType)) {
13903
+ var listStyleTypeFormat = getListStyleValue(listType, listStyleType, context.listFormat.threadItemCounts[depth]);
13904
+ if (listStyleTypeFormat) {
13905
+ format.listStyleType = listStyleTypeFormat;
13906
+ }
13598
13907
  }
13599
13908
  else {
13600
13909
  delete format.listStyleType;
@@ -14160,6 +14469,10 @@ exports.ChangeSource = {
14160
14469
  * Data of this event will be the key code number
14161
14470
  */
14162
14471
  Keyboard: 'Keyboard',
14472
+ /**
14473
+ * Content changed by auto format
14474
+ */
14475
+ AutoFormat: 'AutoFormat',
14163
14476
  };
14164
14477
 
14165
14478
 
@@ -14650,7 +14963,11 @@ var normalizeContentModel_1 = __webpack_require__(/*! ../modelApi/common/normali
14650
14963
  * @returns A ContentModelDocument object that contains all the models created from the give root element
14651
14964
  */
14652
14965
  function domToContentModel(root, context) {
14966
+ var _a;
14653
14967
  var model = (0, createContentModelDocument_1.createContentModelDocument)(context.defaultFormat);
14968
+ if (((_a = context.selection) === null || _a === void 0 ? void 0 : _a.type) == 'range' && context.selection.isReverted) {
14969
+ model.hasRevertedRangeSelection = true;
14970
+ }
14654
14971
  context.elementProcessors.child(model, root, context);
14655
14972
  (0, normalizeContentModel_1.normalizeContentModel)(model);
14656
14973
  return model;
@@ -16248,19 +16565,22 @@ function stackFormatInternal(format, processType) {
16248
16565
  "use strict";
16249
16566
 
16250
16567
  Object.defineProperty(exports, "__esModule", ({ value: true }));
16251
- exports.addDelimiters = exports.isEntityDelimiter = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestEntityWrapper = exports.isEntityElement = void 0;
16568
+ exports.addDelimiters = exports.isBlockEntityContainer = exports.isEntityDelimiter = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestBlockEntityContainer = exports.findClosestEntityWrapper = exports.isEntityElement = void 0;
16252
16569
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
16253
16570
  var applyFormat_1 = __webpack_require__(/*! ../modelToDom/utils/applyFormat */ "./packages/roosterjs-content-model-dom/lib/modelToDom/utils/applyFormat.ts");
16254
16571
  var isElementOfType_1 = __webpack_require__(/*! ./isElementOfType */ "./packages/roosterjs-content-model-dom/lib/domUtils/isElementOfType.ts");
16255
16572
  var isNodeOfType_1 = __webpack_require__(/*! ./isNodeOfType */ "./packages/roosterjs-content-model-dom/lib/domUtils/isNodeOfType.ts");
16256
16573
  var toArray_1 = __webpack_require__(/*! ./toArray */ "./packages/roosterjs-content-model-dom/lib/domUtils/toArray.ts");
16257
16574
  var ENTITY_INFO_NAME = '_Entity';
16575
+ var ENTITY_INFO_SELECTOR = '.' + ENTITY_INFO_NAME;
16258
16576
  var ENTITY_TYPE_PREFIX = '_EType_';
16259
16577
  var ENTITY_ID_PREFIX = '_EId_';
16260
16578
  var ENTITY_READONLY_PREFIX = '_EReadonly_';
16261
16579
  var ZERO_WIDTH_SPACE = '\u200B';
16262
16580
  var DELIMITER_BEFORE = 'entityDelimiterBefore';
16263
16581
  var DELIMITER_AFTER = 'entityDelimiterAfter';
16582
+ var BLOCK_ENTITY_CONTAINER = '_E_EBlockEntityContainer';
16583
+ var BLOCK_ENTITY_CONTAINER_SELECTOR = '.' + BLOCK_ENTITY_CONTAINER;
16264
16584
  /**
16265
16585
  * Check if the given DOM Node is an entity wrapper element
16266
16586
  */
@@ -16274,9 +16594,19 @@ exports.isEntityElement = isEntityElement;
16274
16594
  * @param domHelper The DOM helper to use
16275
16595
  */
16276
16596
  function findClosestEntityWrapper(startNode, domHelper) {
16277
- return domHelper.findClosestElementAncestor(startNode, "." + ENTITY_INFO_NAME);
16597
+ return domHelper.findClosestElementAncestor(startNode, ENTITY_INFO_SELECTOR);
16278
16598
  }
16279
16599
  exports.findClosestEntityWrapper = findClosestEntityWrapper;
16600
+ /**
16601
+ * Find the closest block entity wrapper element from a given DOM node
16602
+ * @param node The node to start looking for entity container
16603
+ * @param domHelper The DOM helper
16604
+ * @returns
16605
+ */
16606
+ function findClosestBlockEntityContainer(node, domHelper) {
16607
+ return domHelper.findClosestElementAncestor(node, BLOCK_ENTITY_CONTAINER_SELECTOR);
16608
+ }
16609
+ exports.findClosestBlockEntityContainer = findClosestBlockEntityContainer;
16280
16610
  /**
16281
16611
  * Get all entity wrapper elements under the given root element
16282
16612
  * @param root The root element to query from
@@ -16338,15 +16668,27 @@ exports.generateEntityClassNames = generateEntityClassNames;
16338
16668
  /**
16339
16669
  * Checks whether the node provided is a Entity delimiter
16340
16670
  * @param node the node to check
16671
+ * @param isBefore True to match delimiter before entity only, false to match delimiter after entity, or undefined means match both
16341
16672
  * @return true if it is a delimiter
16342
16673
  */
16343
- function isEntityDelimiter(element) {
16674
+ function isEntityDelimiter(element, isBefore) {
16675
+ var matchBefore = isBefore === undefined || isBefore;
16676
+ var matchAfter = isBefore === undefined || !isBefore;
16344
16677
  return ((0, isElementOfType_1.isElementOfType)(element, 'span') &&
16345
- (element.classList.contains(DELIMITER_AFTER) ||
16346
- element.classList.contains(DELIMITER_BEFORE)) &&
16678
+ ((matchAfter && element.classList.contains(DELIMITER_AFTER)) ||
16679
+ (matchBefore && element.classList.contains(DELIMITER_BEFORE))) &&
16347
16680
  element.textContent === ZERO_WIDTH_SPACE);
16348
16681
  }
16349
16682
  exports.isEntityDelimiter = isEntityDelimiter;
16683
+ /**
16684
+ * Check if the given element is a container element of block entity
16685
+ * @param element The element to check
16686
+ * @returns True if the element is a block entity container, otherwise false
16687
+ */
16688
+ function isBlockEntityContainer(element) {
16689
+ return (0, isElementOfType_1.isElementOfType)(element, 'div') && element.classList.contains(BLOCK_ENTITY_CONTAINER);
16690
+ }
16691
+ exports.isBlockEntityContainer = isBlockEntityContainer;
16350
16692
  /**
16351
16693
  * Adds delimiters to the element provided. If the delimiters already exists, will not be added
16352
16694
  * @param element the node to add the delimiters
@@ -19240,9 +19582,9 @@ exports.shouldSetValue = shouldSetValue;
19240
19582
  "use strict";
19241
19583
 
19242
19584
  Object.defineProperty(exports, "__esModule", ({ value: true }));
19243
- exports.addBlock = exports.createEmptyModel = exports.createListLevel = exports.createDivider = exports.createEntity = exports.createGeneralBlock = exports.createGeneralSegment = exports.createParagraphDecorator = exports.createContentModelDocument = exports.createImage = exports.createText = exports.createTableCell = exports.createTable = exports.createSelectionMarker = exports.createParagraph = exports.createFormatContainer = exports.createListItem = exports.createBr = exports.normalizeRect = exports.isWhiteSpacePreserved = exports.reuseCachedElement = exports.isEntityDelimiter = exports.addDelimiters = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestEntityWrapper = exports.isEntityElement = exports.wrap = exports.wrapAllChildNodes = exports.moveChildNodes = exports.toArray = exports.getObjectKeys = exports.isElementOfType = exports.isNodeOfType = exports.hasMetadata = exports.updateMetadata = exports.buildSelectionMarker = exports.isBlockElement = exports.areSameFormats = exports.parseFormat = exports.getRegularSelectionOffsets = exports.tableProcessor = exports.entityProcessor = exports.processChildNode = exports.handleRegularSelection = exports.childProcessor = exports.contentModelToText = exports.contentModelToDom = exports.domToContentModel = void 0;
19244
- exports.hasSelectionInSegment = exports.hasSelectionInBlock = exports.getSelectedCells = exports.getSelectedSegmentsAndParagraphs = exports.getSelectedSegments = exports.getSelectedParagraphs = exports.getOperationalBlocks = exports.getFirstSelectedTable = exports.getFirstSelectedListItem = exports.iterateSelections = exports.getClosestAncestorBlockGroupIndex = exports.isBlockGroupOfType = exports.cacheGetEventData = exports.extractClipboardItems = exports.transformColor = exports.readFile = exports.parseTableCells = exports.normalizeText = exports.isSpace = exports.isPunctuation = exports.extractBorderValues = exports.combineBorderValue = exports.isCursorMovingKey = exports.isModifierKey = exports.isCharacterValue = exports.getSelectionRootNode = exports.isBold = exports.createModelToDomConfig = exports.createModelToDomContextWithConfig = exports.createModelToDomContext = exports.createDomToModelConfig = exports.createDomToModelContextWithConfig = exports.createDomToModelContext = exports.parseColor = exports.setColor = exports.getColor = exports.DeprecatedColors = exports.BorderKeys = exports.parseValueWithUnit = exports.setParagraphNotImplicit = exports.normalizeSingleSegment = exports.isEmpty = exports.addSegment = exports.unwrapBlock = exports.isGeneralSegment = exports.normalizeContentModel = exports.normalizeParagraph = exports.addTextSegment = exports.addLink = exports.addCode = void 0;
19245
- exports.UnorderedListStyleMap = exports.OrderedListStyleMap = exports.TableBorderFormat = exports.NumberingListType = exports.BulletListType = exports.ChangeSource = exports.ListMetadataDefinition = exports.updateListMetadata = exports.updateTableMetadata = exports.updateTableCellMetadata = exports.updateImageMetadata = exports.getSegmentTextFormat = exports.getListStyleTypeFromString = exports.retrieveModelFormatState = exports.setTableCellBackgroundColor = exports.MIN_ALLOWED_TABLE_CELL_WIDTH = exports.normalizeTable = exports.applyTableFormat = exports.deleteBlock = exports.deleteSegment = exports.deleteSelection = exports.mergeModel = exports.cloneModel = exports.setSelection = exports.hasSelectionInBlockGroup = void 0;
19585
+ 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;
19586
+ 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;
19587
+ exports.UnorderedListStyleMap = exports.OrderedListStyleMap = exports.TableBorderFormat = exports.NumberingListType = exports.BulletListType = exports.ChangeSource = exports.ListMetadataDefinition = exports.updateListMetadata = exports.updateTableMetadata = exports.updateTableCellMetadata = exports.updateImageMetadata = exports.getSegmentTextFormat = exports.getListStyleTypeFromString = exports.retrieveModelFormatState = exports.setTableCellBackgroundColor = exports.MIN_ALLOWED_TABLE_CELL_WIDTH = exports.normalizeTable = exports.applyTableFormat = exports.deleteBlock = exports.deleteSegment = exports.deleteSelection = exports.mergeModel = exports.cloneModel = exports.setSelection = exports.hasSelectionInBlockGroup = exports.hasSelectionInSegment = exports.hasSelectionInBlock = exports.getSelectedCells = exports.getSelectedSegmentsAndParagraphs = void 0;
19246
19588
  var domToContentModel_1 = __webpack_require__(/*! ./domToModel/domToContentModel */ "./packages/roosterjs-content-model-dom/lib/domToModel/domToContentModel.ts");
19247
19589
  Object.defineProperty(exports, "domToContentModel", ({ enumerable: true, get: function () { return domToContentModel_1.domToContentModel; } }));
19248
19590
  var contentModelToDom_1 = __webpack_require__(/*! ./modelToDom/contentModelToDom */ "./packages/roosterjs-content-model-dom/lib/modelToDom/contentModelToDom.ts");
@@ -19291,6 +19633,8 @@ Object.defineProperty(exports, "parseEntityFormat", ({ enumerable: true, get: fu
19291
19633
  Object.defineProperty(exports, "generateEntityClassNames", ({ enumerable: true, get: function () { return entityUtils_1.generateEntityClassNames; } }));
19292
19634
  Object.defineProperty(exports, "addDelimiters", ({ enumerable: true, get: function () { return entityUtils_1.addDelimiters; } }));
19293
19635
  Object.defineProperty(exports, "isEntityDelimiter", ({ enumerable: true, get: function () { return entityUtils_1.isEntityDelimiter; } }));
19636
+ Object.defineProperty(exports, "isBlockEntityContainer", ({ enumerable: true, get: function () { return entityUtils_1.isBlockEntityContainer; } }));
19637
+ Object.defineProperty(exports, "findClosestBlockEntityContainer", ({ enumerable: true, get: function () { return entityUtils_1.findClosestBlockEntityContainer; } }));
19294
19638
  var reuseCachedElement_1 = __webpack_require__(/*! ./domUtils/reuseCachedElement */ "./packages/roosterjs-content-model-dom/lib/domUtils/reuseCachedElement.ts");
19295
19639
  Object.defineProperty(exports, "reuseCachedElement", ({ enumerable: true, get: function () { return reuseCachedElement_1.reuseCachedElement; } }));
19296
19640
  var isWhiteSpacePreserved_1 = __webpack_require__(/*! ./domUtils/isWhiteSpacePreserved */ "./packages/roosterjs-content-model-dom/lib/domUtils/isWhiteSpacePreserved.ts");
@@ -19355,6 +19699,10 @@ var normalizeSegment_1 = __webpack_require__(/*! ./modelApi/common/normalizeSegm
19355
19699
  Object.defineProperty(exports, "normalizeSingleSegment", ({ enumerable: true, get: function () { return normalizeSegment_1.normalizeSingleSegment; } }));
19356
19700
  var setParagraphNotImplicit_1 = __webpack_require__(/*! ./modelApi/block/setParagraphNotImplicit */ "./packages/roosterjs-content-model-dom/lib/modelApi/block/setParagraphNotImplicit.ts");
19357
19701
  Object.defineProperty(exports, "setParagraphNotImplicit", ({ enumerable: true, get: function () { return setParagraphNotImplicit_1.setParagraphNotImplicit; } }));
19702
+ var getOrderedListNumberStr_1 = __webpack_require__(/*! ./modelApi/list/getOrderedListNumberStr */ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getOrderedListNumberStr.ts");
19703
+ Object.defineProperty(exports, "getOrderedListNumberStr", ({ enumerable: true, get: function () { return getOrderedListNumberStr_1.getOrderedListNumberStr; } }));
19704
+ var getAutoListStyleType_1 = __webpack_require__(/*! ./modelApi/list/getAutoListStyleType */ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getAutoListStyleType.ts");
19705
+ Object.defineProperty(exports, "getAutoListStyleType", ({ enumerable: true, get: function () { return getAutoListStyleType_1.getAutoListStyleType; } }));
19358
19706
  var parseValueWithUnit_1 = __webpack_require__(/*! ./formatHandlers/utils/parseValueWithUnit */ "./packages/roosterjs-content-model-dom/lib/formatHandlers/utils/parseValueWithUnit.ts");
19359
19707
  Object.defineProperty(exports, "parseValueWithUnit", ({ enumerable: true, get: function () { return parseValueWithUnit_1.parseValueWithUnit; } }));
19360
19708
  var borderFormatHandler_1 = __webpack_require__(/*! ./formatHandlers/common/borderFormatHandler */ "./packages/roosterjs-content-model-dom/lib/formatHandlers/common/borderFormatHandler.ts");
@@ -22371,6 +22719,175 @@ function calculateLightness(color) {
22371
22719
  }
22372
22720
 
22373
22721
 
22722
+ /***/ }),
22723
+
22724
+ /***/ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getAutoListStyleType.ts":
22725
+ /*!****************************************************************************************!*\
22726
+ !*** ./packages/roosterjs-content-model-dom/lib/modelApi/list/getAutoListStyleType.ts ***!
22727
+ \****************************************************************************************/
22728
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
22729
+
22730
+ "use strict";
22731
+
22732
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
22733
+ exports.getAutoListStyleType = void 0;
22734
+ var BulletListType_1 = __webpack_require__(/*! ../../constants/BulletListType */ "./packages/roosterjs-content-model-dom/lib/constants/BulletListType.ts");
22735
+ var NumberingListType_1 = __webpack_require__(/*! ../../constants/NumberingListType */ "./packages/roosterjs-content-model-dom/lib/constants/NumberingListType.ts");
22736
+ var DefaultOrderedListStyles = [
22737
+ NumberingListType_1.NumberingListType.Decimal,
22738
+ NumberingListType_1.NumberingListType.LowerAlpha,
22739
+ NumberingListType_1.NumberingListType.LowerRoman,
22740
+ ];
22741
+ var DefaultUnorderedListStyles = [
22742
+ BulletListType_1.BulletListType.Disc,
22743
+ BulletListType_1.BulletListType.Circle,
22744
+ BulletListType_1.BulletListType.Square,
22745
+ ];
22746
+ var OrderedListStyleRevertMap = {
22747
+ 'lower-alpha': NumberingListType_1.NumberingListType.LowerAlpha,
22748
+ 'lower-latin': NumberingListType_1.NumberingListType.LowerAlpha,
22749
+ 'upper-alpha': NumberingListType_1.NumberingListType.UpperAlpha,
22750
+ 'upper-latin': NumberingListType_1.NumberingListType.UpperAlpha,
22751
+ 'lower-roman': NumberingListType_1.NumberingListType.LowerRoman,
22752
+ 'upper-roman': NumberingListType_1.NumberingListType.UpperRoman,
22753
+ };
22754
+ var UnorderedListStyleRevertMap = {
22755
+ disc: BulletListType_1.BulletListType.Disc,
22756
+ circle: BulletListType_1.BulletListType.Circle,
22757
+ square: BulletListType_1.BulletListType.Square,
22758
+ };
22759
+ /**
22760
+ * Get automatic list style of a list item according to its lis type and metadata.
22761
+ * @param listType The list type, either OL or UL
22762
+ * @param metadata Metadata of this list item from list item model
22763
+ * @param depth Depth of list level, start from 0
22764
+ * @param existingStyleType Existing list style type in format, if any
22765
+ * @returns A number to represent list style type.
22766
+ * This will be the value of either NumberingListType (when listType is OL) or BulletListType (when listType is UL).
22767
+ * When there is a specified list style in its metadata, return this value, otherwise
22768
+ * When specified "applyListStyleFromLevel" in metadata, calculate auto list type from its depth, otherwise
22769
+ * When there is already listStyleType in list level format, find a related style type index, otherwise
22770
+ * return undefined
22771
+ */
22772
+ function getAutoListStyleType(listType, metadata, depth, existingStyleType) {
22773
+ var orderedStyleType = metadata.orderedStyleType, unorderedStyleType = metadata.unorderedStyleType, applyListStyleFromLevel = metadata.applyListStyleFromLevel;
22774
+ if (listType == 'OL') {
22775
+ return typeof orderedStyleType == 'number'
22776
+ ? orderedStyleType
22777
+ : applyListStyleFromLevel
22778
+ ? DefaultOrderedListStyles[depth % DefaultOrderedListStyles.length]
22779
+ : existingStyleType
22780
+ ? OrderedListStyleRevertMap[existingStyleType]
22781
+ : undefined;
22782
+ }
22783
+ else {
22784
+ return typeof unorderedStyleType == 'number'
22785
+ ? unorderedStyleType
22786
+ : applyListStyleFromLevel
22787
+ ? DefaultUnorderedListStyles[depth % DefaultUnorderedListStyles.length]
22788
+ : existingStyleType
22789
+ ? UnorderedListStyleRevertMap[existingStyleType]
22790
+ : undefined;
22791
+ }
22792
+ }
22793
+ exports.getAutoListStyleType = getAutoListStyleType;
22794
+
22795
+
22796
+ /***/ }),
22797
+
22798
+ /***/ "./packages/roosterjs-content-model-dom/lib/modelApi/list/getOrderedListNumberStr.ts":
22799
+ /*!*******************************************************************************************!*\
22800
+ !*** ./packages/roosterjs-content-model-dom/lib/modelApi/list/getOrderedListNumberStr.ts ***!
22801
+ \*******************************************************************************************/
22802
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
22803
+
22804
+ "use strict";
22805
+
22806
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
22807
+ exports.getOrderedListNumberStr = void 0;
22808
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
22809
+ var getObjectKeys_1 = __webpack_require__(/*! ../../domUtils/getObjectKeys */ "./packages/roosterjs-content-model-dom/lib/domUtils/getObjectKeys.ts");
22810
+ var NumberingListType_1 = __webpack_require__(/*! ../../constants/NumberingListType */ "./packages/roosterjs-content-model-dom/lib/constants/NumberingListType.ts");
22811
+ var CharCodeOfA = 65;
22812
+ var RomanValues = {
22813
+ M: 1000,
22814
+ CM: 900,
22815
+ D: 500,
22816
+ CD: 400,
22817
+ C: 100,
22818
+ XC: 90,
22819
+ L: 50,
22820
+ XL: 40,
22821
+ X: 10,
22822
+ IX: 9,
22823
+ V: 5,
22824
+ IV: 4,
22825
+ I: 1,
22826
+ };
22827
+ /**
22828
+ * Get the list number for a list item according to list style type and its index number
22829
+ * @param styleType The list style number, should be a value of NumberingListType type
22830
+ * @param listNumber List number, start from 1
22831
+ * @returns A string for this list item. For example, when pass in NumberingListType.LowerAlpha and 2, it returns "b"
22832
+ */
22833
+ function getOrderedListNumberStr(styleType, listNumber) {
22834
+ switch (styleType) {
22835
+ case NumberingListType_1.NumberingListType.LowerAlpha:
22836
+ case NumberingListType_1.NumberingListType.LowerAlphaDash:
22837
+ case NumberingListType_1.NumberingListType.LowerAlphaDoubleParenthesis:
22838
+ case NumberingListType_1.NumberingListType.LowerAlphaParenthesis:
22839
+ return convertDecimalsToAlpha(listNumber, true /*isLowerCase*/);
22840
+ case NumberingListType_1.NumberingListType.UpperAlpha:
22841
+ case NumberingListType_1.NumberingListType.UpperAlphaDash:
22842
+ case NumberingListType_1.NumberingListType.UpperAlphaDoubleParenthesis:
22843
+ case NumberingListType_1.NumberingListType.UpperAlphaParenthesis:
22844
+ return convertDecimalsToAlpha(listNumber, false /*isLowerCase*/);
22845
+ case NumberingListType_1.NumberingListType.LowerRoman:
22846
+ case NumberingListType_1.NumberingListType.LowerRomanDash:
22847
+ case NumberingListType_1.NumberingListType.LowerRomanDoubleParenthesis:
22848
+ case NumberingListType_1.NumberingListType.LowerRomanParenthesis:
22849
+ return convertDecimalsToRoman(listNumber, true /*isLowerCase*/);
22850
+ case NumberingListType_1.NumberingListType.UpperRoman:
22851
+ case NumberingListType_1.NumberingListType.UpperRomanDash:
22852
+ case NumberingListType_1.NumberingListType.UpperRomanDoubleParenthesis:
22853
+ case NumberingListType_1.NumberingListType.UpperRomanParenthesis:
22854
+ return convertDecimalsToRoman(listNumber, false /*isLowerCase*/);
22855
+ default:
22856
+ return listNumber + '';
22857
+ }
22858
+ }
22859
+ exports.getOrderedListNumberStr = getOrderedListNumberStr;
22860
+ function convertDecimalsToAlpha(decimal, isLowerCase) {
22861
+ var alpha = '';
22862
+ decimal--;
22863
+ while (decimal >= 0) {
22864
+ alpha = String.fromCharCode((decimal % 26) + CharCodeOfA) + alpha;
22865
+ decimal = Math.floor(decimal / 26) - 1;
22866
+ }
22867
+ return isLowerCase ? alpha.toLowerCase() : alpha;
22868
+ }
22869
+ function convertDecimalsToRoman(decimal, isLowerCase) {
22870
+ var e_1, _a;
22871
+ var romanValue = '';
22872
+ try {
22873
+ for (var _b = (0, tslib_1.__values)((0, getObjectKeys_1.getObjectKeys)(RomanValues)), _c = _b.next(); !_c.done; _c = _b.next()) {
22874
+ var i = _c.value;
22875
+ var timesRomanCharAppear = Math.floor(decimal / RomanValues[i]);
22876
+ decimal = decimal - timesRomanCharAppear * RomanValues[i];
22877
+ romanValue = romanValue + i.repeat(timesRomanCharAppear);
22878
+ }
22879
+ }
22880
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
22881
+ finally {
22882
+ try {
22883
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
22884
+ }
22885
+ finally { if (e_1) throw e_1.error; }
22886
+ }
22887
+ return isLowerCase ? romanValue.toLocaleLowerCase() : romanValue;
22888
+ }
22889
+
22890
+
22374
22891
  /***/ }),
22375
22892
 
22376
22893
  /***/ "./packages/roosterjs-content-model-dom/lib/modelApi/metadata/definitionCreators.ts":
@@ -22767,17 +23284,19 @@ var iterateSelections_1 = __webpack_require__(/*! ./iterateSelections */ "./pack
22767
23284
  * @param model The Content Model to get selection from
22768
23285
  * @param includingFormatHolder True means also include format holder as segment from list item, in that case paragraph will be null
22769
23286
  */
22770
- function getSelectedSegmentsAndParagraphs(model, includingFormatHolder) {
23287
+ function getSelectedSegmentsAndParagraphs(model, includingFormatHolder, includingEntity) {
22771
23288
  var selections = collectSelections(model, {
22772
23289
  includeListFormatHolder: includingFormatHolder ? 'allSegments' : 'never',
22773
23290
  });
22774
23291
  var result = [];
22775
23292
  selections.forEach(function (_a) {
22776
- var segments = _a.segments, block = _a.block;
23293
+ var segments = _a.segments, block = _a.block, path = _a.path;
22777
23294
  if (segments && ((includingFormatHolder && !block) || (block === null || block === void 0 ? void 0 : block.blockType) == 'Paragraph')) {
22778
23295
  segments.forEach(function (segment) {
22779
- if (segment.segmentType != 'Entity' || !segment.entityFormat.isReadonly) {
22780
- result.push([segment, (block === null || block === void 0 ? void 0 : block.blockType) == 'Paragraph' ? block : null]);
23296
+ if (includingEntity ||
23297
+ segment.segmentType != 'Entity' ||
23298
+ !segment.entityFormat.isReadonly) {
23299
+ result.push([segment, (block === null || block === void 0 ? void 0 : block.blockType) == 'Paragraph' ? block : null, path]);
22781
23300
  }
22782
23301
  });
22783
23302
  }
@@ -22813,15 +23332,15 @@ function getSelectedParagraphs(model) {
22813
23332
  exports.getSelectedParagraphs = getSelectedParagraphs;
22814
23333
  /**
22815
23334
  * Get an array of block group - block pair that is of the expected block group type from selection
22816
- * @param model The Content Model to get selection from
23335
+ * @param group The root block group to search
22817
23336
  * @param blockGroupTypes The expected block group types
22818
23337
  * @param stopTypes Block group types that will stop searching when hit
22819
23338
  * @param deepFirst True means search in deep first, otherwise wide first
22820
23339
  */
22821
- function getOperationalBlocks(model, blockGroupTypes, stopTypes, deepFirst) {
23340
+ function getOperationalBlocks(group, blockGroupTypes, stopTypes, deepFirst) {
22822
23341
  var result = [];
22823
23342
  var findSequence = deepFirst ? blockGroupTypes.map(function (type) { return [type]; }) : [blockGroupTypes];
22824
- var selections = collectSelections(model, {
23343
+ var selections = collectSelections(group, {
22825
23344
  includeListFormatHolder: 'never',
22826
23345
  contentUnderSelectedTableCell: 'ignoreForTable', // When whole table is selected, we treat the table as a single block
22827
23346
  });
@@ -22899,9 +23418,9 @@ function getFirstSelectedListItem(model) {
22899
23418
  return listItem;
22900
23419
  }
22901
23420
  exports.getFirstSelectedListItem = getFirstSelectedListItem;
22902
- function collectSelections(model, option) {
23421
+ function collectSelections(group, option) {
22903
23422
  var selections = [];
22904
- (0, iterateSelections_1.iterateSelections)(model, function (path, tableContext, block, segments) {
23423
+ (0, iterateSelections_1.iterateSelections)(group, function (path, tableContext, block, segments) {
22905
23424
  selections.push({
22906
23425
  path: path,
22907
23426
  tableContext: tableContext,
@@ -23442,6 +23961,9 @@ var toArray_1 = __webpack_require__(/*! ../domUtils/toArray */ "./packages/roost
23442
23961
  function contentModelToDom(doc, root, model, context) {
23443
23962
  context.modelHandlers.blockGroupChildren(doc, root, model, context);
23444
23963
  var range = extractSelectionRange(doc, context);
23964
+ if (model.hasRevertedRangeSelection && (range === null || range === void 0 ? void 0 : range.type) == 'range') {
23965
+ range.isReverted = true;
23966
+ }
23445
23967
  root.normalize();
23446
23968
  return range;
23447
23969
  }
@@ -24631,7 +25153,8 @@ function removeUnnecessarySpan(root) {
24631
25153
  for (var child = root.firstChild; child;) {
24632
25154
  if ((0, isNodeOfType_1.isNodeOfType)(child, 'ELEMENT_NODE') &&
24633
25155
  child.tagName == 'SPAN' &&
24634
- child.attributes.length == 0) {
25156
+ child.attributes.length == 0 &&
25157
+ !isImageSpan(child)) {
24635
25158
  var node = child;
24636
25159
  var refNode = child.nextSibling;
24637
25160
  child = child.nextSibling;
@@ -24648,6 +25171,11 @@ function removeUnnecessarySpan(root) {
24648
25171
  }
24649
25172
  }
24650
25173
  exports.removeUnnecessarySpan = removeUnnecessarySpan;
25174
+ var isImageSpan = function (child) {
25175
+ return ((0, isNodeOfType_1.isNodeOfType)(child.firstChild, 'ELEMENT_NODE') &&
25176
+ child.firstChild.tagName == 'IMG' &&
25177
+ child.firstChild == child.lastChild);
25178
+ };
24651
25179
 
24652
25180
 
24653
25181
  /***/ }),
@@ -24786,65 +25314,84 @@ exports.stackFormat = stackFormat;
24786
25314
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24787
25315
  exports.contentModelToText = void 0;
24788
25316
  var TextForHR = '________________________________________';
25317
+ var defaultCallbacks = {
25318
+ onDivider: function (divider) { return (divider.tagName == 'hr' ? TextForHR : ''); },
25319
+ onEntityBlock: function () { return ''; },
25320
+ onEntitySegment: function (entity) { var _a; return (_a = entity.wrapper.textContent) !== null && _a !== void 0 ? _a : ''; },
25321
+ onGeneralSegment: function (segment) { var _a; return (_a = segment.element.textContent) !== null && _a !== void 0 ? _a : ''; },
25322
+ onImage: function () { return ' '; },
25323
+ onText: function (text) { return text.text; },
25324
+ onParagraph: function () { return true; },
25325
+ onTable: function () { return true; },
25326
+ onBlockGroup: function () { return true; },
25327
+ };
24789
25328
  /**
24790
25329
  * Convert Content Model to plain text
24791
25330
  * @param model The source Content Model
24792
25331
  * @param [separator='\r\n'] The separator string used for connect lines
25332
+ * @param callbacks Callbacks to customize the behavior of contentModelToText function
24793
25333
  */
24794
- function contentModelToText(model, separator) {
25334
+ function contentModelToText(model, separator, callbacks) {
24795
25335
  if (separator === void 0) { separator = '\r\n'; }
24796
25336
  var textArray = [];
24797
- contentModelToTextArray(model, textArray);
25337
+ var fullCallbacks = Object.assign({}, defaultCallbacks, callbacks);
25338
+ contentModelToTextArray(model, textArray, fullCallbacks);
24798
25339
  return textArray.join(separator);
24799
25340
  }
24800
25341
  exports.contentModelToText = contentModelToText;
24801
- function contentModelToTextArray(group, textArray) {
24802
- group.blocks.forEach(function (block) {
24803
- switch (block.blockType) {
24804
- case 'Paragraph':
24805
- var text_1 = '';
24806
- block.segments.forEach(function (segment) {
24807
- switch (segment.segmentType) {
24808
- case 'Br':
25342
+ function contentModelToTextArray(group, textArray, callbacks) {
25343
+ if (callbacks.onBlockGroup(group)) {
25344
+ group.blocks.forEach(function (block) {
25345
+ switch (block.blockType) {
25346
+ case 'Paragraph':
25347
+ if (callbacks.onParagraph(block)) {
25348
+ var text_1 = '';
25349
+ block.segments.forEach(function (segment) {
25350
+ switch (segment.segmentType) {
25351
+ case 'Br':
25352
+ textArray.push(text_1);
25353
+ text_1 = '';
25354
+ break;
25355
+ case 'Entity':
25356
+ text_1 += callbacks.onEntitySegment(segment);
25357
+ break;
25358
+ case 'General':
25359
+ text_1 += callbacks.onGeneralSegment(segment);
25360
+ break;
25361
+ case 'Text':
25362
+ text_1 += callbacks.onText(segment);
25363
+ break;
25364
+ case 'Image':
25365
+ text_1 += callbacks.onImage(segment);
25366
+ break;
25367
+ }
25368
+ });
25369
+ if (text_1) {
24809
25370
  textArray.push(text_1);
24810
- text_1 = '';
24811
- break;
24812
- case 'Entity':
24813
- text_1 += segment.wrapper.textContent || '';
24814
- break;
24815
- case 'General':
24816
- text_1 += segment.element.textContent || '';
24817
- break;
24818
- case 'Text':
24819
- text_1 += segment.text;
24820
- break;
24821
- case 'Image':
24822
- text_1 += ' ';
24823
- break;
25371
+ }
24824
25372
  }
24825
- });
24826
- if (text_1) {
24827
- textArray.push(text_1);
24828
- }
24829
- break;
24830
- case 'Divider':
24831
- textArray.push(block.tagName == 'hr' ? TextForHR : '');
24832
- break;
24833
- case 'Entity':
24834
- textArray.push('');
24835
- break;
24836
- case 'Table':
24837
- block.rows.forEach(function (row) {
24838
- return row.cells.forEach(function (cell) {
24839
- contentModelToTextArray(cell, textArray);
24840
- });
24841
- });
24842
- break;
24843
- case 'BlockGroup':
24844
- contentModelToTextArray(block, textArray);
24845
- break;
24846
- }
24847
- });
25373
+ break;
25374
+ case 'Divider':
25375
+ textArray.push(callbacks.onDivider(block));
25376
+ break;
25377
+ case 'Entity':
25378
+ textArray.push(callbacks.onEntityBlock(block));
25379
+ break;
25380
+ case 'Table':
25381
+ if (callbacks.onTable(block)) {
25382
+ block.rows.forEach(function (row) {
25383
+ return row.cells.forEach(function (cell) {
25384
+ contentModelToTextArray(cell, textArray, callbacks);
25385
+ });
25386
+ });
25387
+ }
25388
+ break;
25389
+ case 'BlockGroup':
25390
+ contentModelToTextArray(block, textArray, callbacks);
25391
+ break;
25392
+ }
25393
+ });
25394
+ }
24848
25395
  }
24849
25396
 
24850
25397
 
@@ -24860,11 +25407,14 @@ function contentModelToTextArray(group, textArray) {
24860
25407
 
24861
25408
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24862
25409
  exports.AutoFormatPlugin = void 0;
25410
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
24863
25411
  var createLink_1 = __webpack_require__(/*! ./link/createLink */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLink.ts");
24864
25412
  var createLinkAfterSpace_1 = __webpack_require__(/*! ./link/createLinkAfterSpace */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLinkAfterSpace.ts");
24865
25413
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
24866
25414
  var keyboardListTrigger_1 = __webpack_require__(/*! ./list/keyboardListTrigger */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/list/keyboardListTrigger.ts");
25415
+ var transformFraction_1 = __webpack_require__(/*! ./numbers/transformFraction */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformFraction.ts");
24867
25416
  var transformHyphen_1 = __webpack_require__(/*! ./hyphen/transformHyphen */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/hyphen/transformHyphen.ts");
25417
+ var transformOrdinals_1 = __webpack_require__(/*! ./numbers/transformOrdinals */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformOrdinals.ts");
24868
25418
  var unlink_1 = __webpack_require__(/*! ./link/unlink */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/unlink.ts");
24869
25419
  /**
24870
25420
  * @internal
@@ -24875,6 +25425,8 @@ var DefaultOptions = {
24875
25425
  autoUnlink: false,
24876
25426
  autoLink: false,
24877
25427
  autoHyphen: false,
25428
+ autoFraction: false,
25429
+ autoOrdinals: false,
24878
25430
  };
24879
25431
  /**
24880
25432
  * Auto Format plugin handles auto formatting, such as transforming * characters into a bullet list.
@@ -24888,6 +25440,8 @@ var AutoFormatPlugin = /** @class */ (function () {
24888
25440
  * - autoLink: A boolean that enables or disables automatic hyperlink creation when pasting or typing content. Defaults to false.
24889
25441
  * - autoUnlink: A boolean that enables or disables automatic hyperlink removal when pressing backspace. Defaults to false.
24890
25442
  * - autoHyphen: A boolean that enables or disables automatic hyphen transformation. Defaults to false.
25443
+ * - autoFraction: A boolean that enables or disables automatic fraction transformation. Defaults to false.
25444
+ * - autoOrdinals: A boolean that enables or disables automatic ordinal number transformation. Defaults to false.
24891
25445
  */
24892
25446
  function AutoFormatPlugin(options) {
24893
25447
  if (options === void 0) { options = DefaultOptions; }
@@ -24948,20 +25502,40 @@ var AutoFormatPlugin = /** @class */ (function () {
24948
25502
  selection.range.collapsed) {
24949
25503
  switch (rawEvent.data) {
24950
25504
  case ' ':
25505
+ var formatOptions_1 = {
25506
+ changeSource: '',
25507
+ apiName: '',
25508
+ };
24951
25509
  (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (model, previousSegment, paragraph, _markerFormat, context) {
24952
- var _a = _this.options, autoBullet = _a.autoBullet, autoNumbering = _a.autoNumbering, autoLink = _a.autoLink, autoHyphen = _a.autoHyphen;
25510
+ var _a = _this.options, autoBullet = _a.autoBullet, autoNumbering = _a.autoNumbering, autoLink = _a.autoLink, autoHyphen = _a.autoHyphen, autoFraction = _a.autoFraction, autoOrdinals = _a.autoOrdinals;
24953
25511
  var shouldHyphen = false;
24954
25512
  var shouldLink = false;
25513
+ var shouldList = false;
25514
+ var shouldFraction = false;
25515
+ var shouldOrdinals = false;
25516
+ if (autoBullet || autoNumbering) {
25517
+ shouldList = (0, keyboardListTrigger_1.keyboardListTrigger)(model, paragraph, context, autoBullet, autoNumbering);
25518
+ }
24955
25519
  if (autoLink) {
24956
25520
  shouldLink = (0, createLinkAfterSpace_1.createLinkAfterSpace)(previousSegment, paragraph, context);
24957
25521
  }
24958
25522
  if (autoHyphen) {
24959
25523
  shouldHyphen = (0, transformHyphen_1.transformHyphen)(previousSegment, paragraph, context);
24960
25524
  }
24961
- return ((0, keyboardListTrigger_1.keyboardListTrigger)(model, paragraph, context, autoBullet, autoNumbering) ||
25525
+ if (autoFraction) {
25526
+ shouldFraction = (0, transformFraction_1.transformFraction)(previousSegment, paragraph, context);
25527
+ }
25528
+ if (autoOrdinals) {
25529
+ shouldOrdinals = (0, transformOrdinals_1.transformOrdinals)(previousSegment, paragraph, context);
25530
+ }
25531
+ formatOptions_1.apiName = getApiName(shouldList, shouldHyphen);
25532
+ formatOptions_1.changeSource = getChangeSource(shouldList, shouldHyphen, shouldLink);
25533
+ return (shouldList ||
24962
25534
  shouldHyphen ||
24963
- shouldLink);
24964
- });
25535
+ shouldLink ||
25536
+ shouldFraction ||
25537
+ shouldOrdinals);
25538
+ }, formatOptions_1);
24965
25539
  break;
24966
25540
  }
24967
25541
  }
@@ -24987,6 +25561,16 @@ var AutoFormatPlugin = /** @class */ (function () {
24987
25561
  return AutoFormatPlugin;
24988
25562
  }());
24989
25563
  exports.AutoFormatPlugin = AutoFormatPlugin;
25564
+ var getApiName = function (shouldList, shouldHyphen) {
25565
+ return shouldList ? 'autoToggleList' : shouldHyphen ? 'autoHyphen' : '';
25566
+ };
25567
+ var getChangeSource = function (shouldList, shouldHyphen, shouldLink) {
25568
+ return shouldList || shouldHyphen
25569
+ ? roosterjs_content_model_dom_1.ChangeSource.AutoFormat
25570
+ : shouldLink
25571
+ ? roosterjs_content_model_dom_1.ChangeSource.AutoLink
25572
+ : '';
25573
+ };
24990
25574
 
24991
25575
 
24992
25576
  /***/ }),
@@ -25065,6 +25649,8 @@ function createLink(editor) {
25065
25649
  return true;
25066
25650
  }
25067
25651
  return false;
25652
+ }, {
25653
+ changeSource: roosterjs_content_model_dom_1.ChangeSource.AutoLink,
25068
25654
  });
25069
25655
  }
25070
25656
  exports.createLink = createLink;
@@ -25479,15 +26065,13 @@ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-mo
25479
26065
  function keyboardListTrigger(model, paragraph, context, shouldSearchForBullet, shouldSearchForNumbering) {
25480
26066
  if (shouldSearchForBullet === void 0) { shouldSearchForBullet = true; }
25481
26067
  if (shouldSearchForNumbering === void 0) { shouldSearchForNumbering = true; }
25482
- if (shouldSearchForBullet || shouldSearchForNumbering) {
25483
- var listStyleType = (0, getListTypeStyle_1.getListTypeStyle)(model, shouldSearchForBullet, shouldSearchForNumbering);
25484
- if (listStyleType) {
25485
- paragraph.segments.splice(0, 1);
25486
- var listType = listStyleType.listType, styleType = listStyleType.styleType, index = listStyleType.index;
25487
- triggerList(model, listType, styleType, index);
25488
- context.canUndoByBackspace = true;
25489
- return true;
25490
- }
26068
+ var listStyleType = (0, getListTypeStyle_1.getListTypeStyle)(model, shouldSearchForBullet, shouldSearchForNumbering);
26069
+ if (listStyleType) {
26070
+ paragraph.segments.splice(0, 1);
26071
+ var listType = listStyleType.listType, styleType = listStyleType.styleType, index = listStyleType.index;
26072
+ triggerList(model, listType, styleType, index);
26073
+ context.canUndoByBackspace = true;
26074
+ return true;
25491
26075
  }
25492
26076
  return false;
25493
26077
  }
@@ -25508,6 +26092,85 @@ var triggerList = function (model, listType, styleType, index) {
25508
26092
  };
25509
26093
 
25510
26094
 
26095
+ /***/ }),
26096
+
26097
+ /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformFraction.ts":
26098
+ /*!**********************************************************************************************!*\
26099
+ !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformFraction.ts ***!
26100
+ \**********************************************************************************************/
26101
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26102
+
26103
+ "use strict";
26104
+
26105
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26106
+ exports.transformFraction = void 0;
26107
+ var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26108
+ var FRACTIONS = {
26109
+ '1/2': '½',
26110
+ '1/4': '¼',
26111
+ '3/4': '¾',
26112
+ };
26113
+ /**
26114
+ * @internal
26115
+ */
26116
+ function transformFraction(previousSegment, paragraph, context) {
26117
+ var _a;
26118
+ var fraction = (_a = previousSegment.text.split(' ').pop()) === null || _a === void 0 ? void 0 : _a.trim();
26119
+ if (fraction && FRACTIONS[fraction]) {
26120
+ var textLength = previousSegment.text.length - 1;
26121
+ var textIndex = textLength - fraction.length;
26122
+ var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textLength);
26123
+ textSegment.text = FRACTIONS[fraction];
26124
+ context.canUndoByBackspace = true;
26125
+ return true;
26126
+ }
26127
+ return false;
26128
+ }
26129
+ exports.transformFraction = transformFraction;
26130
+
26131
+
26132
+ /***/ }),
26133
+
26134
+ /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformOrdinals.ts":
26135
+ /*!**********************************************************************************************!*\
26136
+ !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/numbers/transformOrdinals.ts ***!
26137
+ \**********************************************************************************************/
26138
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26139
+
26140
+ "use strict";
26141
+
26142
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26143
+ exports.transformOrdinals = void 0;
26144
+ var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26145
+ var getOrdinal = function (value) {
26146
+ var ORDINALS = {
26147
+ 1: 'st',
26148
+ 2: 'nd',
26149
+ 3: 'rd',
26150
+ };
26151
+ return ORDINALS[value] || 'th';
26152
+ };
26153
+ /**
26154
+ * @internal
26155
+ */
26156
+ function transformOrdinals(previousSegment, paragraph, context) {
26157
+ var _a;
26158
+ var value = (_a = previousSegment.text.split(' ').pop()) === null || _a === void 0 ? void 0 : _a.trim();
26159
+ if (value) {
26160
+ var ordinal = value.substring(value.length - 2);
26161
+ var ordinalValue = parseInt(value);
26162
+ if (ordinalValue && getOrdinal(ordinalValue) === ordinal) {
26163
+ var ordinalSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - 3, previousSegment.text.length - 1);
26164
+ ordinalSegment.format.superOrSubScriptSequence = 'super';
26165
+ context.canUndoByBackspace = true;
26166
+ return true;
26167
+ }
26168
+ }
26169
+ return false;
26170
+ }
26171
+ exports.transformOrdinals = transformOrdinals;
26172
+
26173
+
25511
26174
  /***/ }),
25512
26175
 
25513
26176
  /***/ "./packages/roosterjs-content-model-plugins/lib/contextMenuBase/ContextMenuPluginBase.ts":
@@ -25604,8 +26267,105 @@ exports.ContextMenuPluginBase = ContextMenuPluginBase;
25604
26267
 
25605
26268
  /***/ }),
25606
26269
 
25607
- /***/ "./packages/roosterjs-content-model-plugins/lib/edit/EditPlugin.ts":
25608
- /*!*************************************************************************!*\
26270
+ /***/ "./packages/roosterjs-content-model-plugins/lib/customReplace/CustomReplacePlugin.ts":
26271
+ /*!*******************************************************************************************!*\
26272
+ !*** ./packages/roosterjs-content-model-plugins/lib/customReplace/CustomReplacePlugin.ts ***!
26273
+ \*******************************************************************************************/
26274
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26275
+
26276
+ "use strict";
26277
+
26278
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26279
+ exports.CustomReplacePlugin = void 0;
26280
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26281
+ /**
26282
+ * CustomReplacePlugin is a plugin that allows you to replace a string with another string in the editor.
26283
+ */
26284
+ var CustomReplacePlugin = /** @class */ (function () {
26285
+ /**
26286
+ * @param customReplacements Custom replacement rules.
26287
+ * Ex: [{ stringToReplace: ':)', replacementString: '🙂', replacementHandler: replaceEmojis }]
26288
+ */
26289
+ function CustomReplacePlugin(customReplacements) {
26290
+ this.customReplacements = customReplacements;
26291
+ this.editor = null;
26292
+ this.triggerKeys = [];
26293
+ }
26294
+ /**
26295
+ * Get name of this plugin
26296
+ */
26297
+ CustomReplacePlugin.prototype.getName = function () {
26298
+ return 'CustomReplace';
26299
+ };
26300
+ /**
26301
+ * The first method that editor will call to a plugin when editor is initializing.
26302
+ * It will pass in the editor instance, plugin should take this chance to save the
26303
+ * editor reference so that it can call to any editor method or format API later.
26304
+ * @param editor The editor object
26305
+ */
26306
+ CustomReplacePlugin.prototype.initialize = function (editor) {
26307
+ this.editor = editor;
26308
+ this.triggerKeys = this.customReplacements.map(function (replacement) {
26309
+ return replacement.stringToReplace.slice(-1);
26310
+ });
26311
+ };
26312
+ /**
26313
+ * The last method that editor will call to a plugin before it is disposed.
26314
+ * Plugin can take this chance to clear the reference to editor. After this method is
26315
+ * called, plugin should not call to any editor method since it will result in error.
26316
+ */
26317
+ CustomReplacePlugin.prototype.dispose = function () {
26318
+ this.editor = null;
26319
+ };
26320
+ /**
26321
+ * Core method for a plugin. Once an event happens in editor, editor will call this
26322
+ * method of each plugin to handle the event as long as the event is not handled
26323
+ * exclusively by another plugin.
26324
+ * @param event The event to handle:
26325
+ */
26326
+ CustomReplacePlugin.prototype.onPluginEvent = function (event) {
26327
+ if (this.editor) {
26328
+ switch (event.eventType) {
26329
+ case 'input':
26330
+ this.handleEditorInputEvent(this.editor, event);
26331
+ break;
26332
+ }
26333
+ }
26334
+ };
26335
+ CustomReplacePlugin.prototype.handleEditorInputEvent = function (editor, event) {
26336
+ var _this = this;
26337
+ var rawEvent = event.rawEvent;
26338
+ var selection = editor.getDOMSelection();
26339
+ var key = rawEvent.data;
26340
+ if (this.customReplacements.length > 0 &&
26341
+ rawEvent.inputType === 'insertText' &&
26342
+ selection &&
26343
+ selection.type === 'range' &&
26344
+ selection.range.collapsed &&
26345
+ key &&
26346
+ this.triggerKeys.indexOf(key) > -1) {
26347
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (_model, previousSegment, paragraph, _markerFormat, context) {
26348
+ var replaced = _this.customReplacements.some(function (_a) {
26349
+ var stringToReplace = _a.stringToReplace, replacementString = _a.replacementString, replacementHandler = _a.replacementHandler;
26350
+ return replacementHandler(previousSegment, stringToReplace, replacementString, paragraph);
26351
+ });
26352
+ if (replaced) {
26353
+ context.canUndoByBackspace = true;
26354
+ return true;
26355
+ }
26356
+ return false;
26357
+ });
26358
+ }
26359
+ };
26360
+ return CustomReplacePlugin;
26361
+ }());
26362
+ exports.CustomReplacePlugin = CustomReplacePlugin;
26363
+
26364
+
26365
+ /***/ }),
26366
+
26367
+ /***/ "./packages/roosterjs-content-model-plugins/lib/edit/EditPlugin.ts":
26368
+ /*!*************************************************************************!*\
25609
26369
  !*** ./packages/roosterjs-content-model-plugins/lib/edit/EditPlugin.ts ***!
25610
26370
  \*************************************************************************/
25611
26371
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
@@ -25686,11 +26446,18 @@ var EditPlugin = /** @class */ (function () {
25686
26446
  if (!rawEvent.defaultPrevented && !event.handledByEditFeature) {
25687
26447
  switch (rawEvent.key) {
25688
26448
  case 'Backspace':
25689
- case 'Delete':
25690
26449
  // Use our API to handle BACKSPACE/DELETE key.
25691
26450
  // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache
25692
26451
  (0, keyboardDelete_1.keyboardDelete)(editor, rawEvent);
25693
26452
  break;
26453
+ case 'Delete':
26454
+ // Use our API to handle BACKSPACE/DELETE key.
26455
+ // 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
26456
+ // And leave it to browser when shift key is pressed so that browser will trigger cut event
26457
+ if (!event.rawEvent.shiftKey) {
26458
+ (0, keyboardDelete_1.keyboardDelete)(editor, rawEvent);
26459
+ }
26460
+ break;
25694
26461
  case 'Tab':
25695
26462
  (0, keyboardTab_1.keyboardTab)(editor, rawEvent);
25696
26463
  break;
@@ -25707,6 +26474,8 @@ var EditPlugin = /** @class */ (function () {
25707
26474
  }
25708
26475
  };
25709
26476
  EditPlugin.prototype.handleBeforeInputEvent = function (editor, rawEvent) {
26477
+ var _this = this;
26478
+ var _a, _b;
25710
26479
  // Some Android IMEs doesn't fire correct keydown event for BACKSPACE/DELETE key
25711
26480
  // Here we translate input event to BACKSPACE/DELETE keydown event to be compatible with existing logic
25712
26481
  if (!this.shouldHandleNextInputEvent ||
@@ -25734,6 +26503,15 @@ var EditPlugin = /** @class */ (function () {
25734
26503
  }
25735
26504
  if (handled) {
25736
26505
  rawEvent.preventDefault();
26506
+ // Restore the selection to avoid the cursor jump issue
26507
+ // See: https://issues.chromium.org/issues/330596261
26508
+ var selection_1 = editor.getDOMSelection();
26509
+ var doc = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDocument();
26510
+ (_b = doc === null || doc === void 0 ? void 0 : doc.defaultView) === null || _b === void 0 ? void 0 : _b.requestAnimationFrame(function () {
26511
+ if (_this.editor) {
26512
+ _this.editor.setDOMSelection(selection_1);
26513
+ }
26514
+ });
25737
26515
  }
25738
26516
  };
25739
26517
  return EditPlugin;
@@ -26265,6 +27043,7 @@ exports.shouldDeleteAllSegmentsBefore = shouldDeleteAllSegmentsBefore;
26265
27043
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26266
27044
  exports.handleEnterOnList = void 0;
26267
27045
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
27046
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26268
27047
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26269
27048
  /**
26270
27049
  * @internal
@@ -26311,7 +27090,12 @@ var handleEnterOnList = function (context) {
26311
27090
  listItem_1.levels.pop();
26312
27091
  }
26313
27092
  else {
26314
- createNewListItem(context, listItem_1, listParent);
27093
+ var newListItem = createNewListItem(context, listItem_1, listParent);
27094
+ if (context.formatContext) {
27095
+ context.formatContext.announceData = (0, roosterjs_content_model_api_1.getListAnnounceData)((0, tslib_1.__spreadArray)([
27096
+ newListItem
27097
+ ], (0, tslib_1.__read)(path.slice(index + 1)), false));
27098
+ }
26315
27099
  }
26316
27100
  }
26317
27101
  rawEvent === null || rawEvent === void 0 ? void 0 : rawEvent.preventDefault();
@@ -26337,6 +27121,7 @@ var createNewListItem = function (context, listItem, listParent) {
26337
27121
  insertPoint.paragraph = newParagraph;
26338
27122
  context.lastParagraph = newParagraph;
26339
27123
  listParent.blocks.splice(listIndex + 1, 0, newListItem);
27124
+ return newListItem;
26340
27125
  };
26341
27126
  var createNewListLevel = function (listItem) {
26342
27127
  return listItem.levels.map(function (level) {
@@ -26397,6 +27182,7 @@ function keyboardDelete(editor, rawEvent) {
26397
27182
  rawEvent: rawEvent,
26398
27183
  changeSource: roosterjs_content_model_dom_1.ChangeSource.Keyboard,
26399
27184
  getChangeData: function () { return rawEvent.which; },
27185
+ scrollCaretIntoView: true,
26400
27186
  apiName: rawEvent.key == 'Delete' ? 'handleDeleteKey' : 'handleBackspaceKey',
26401
27187
  });
26402
27188
  }
@@ -26489,6 +27275,7 @@ function keyboardInput(editor, rawEvent) {
26489
27275
  return false;
26490
27276
  }
26491
27277
  }, {
27278
+ scrollCaretIntoView: true,
26492
27279
  rawEvent: rawEvent,
26493
27280
  });
26494
27281
  return true;
@@ -26542,8 +27329,8 @@ function keyboardTab(editor, rawEvent) {
26542
27329
  var selection = editor.getDOMSelection();
26543
27330
  switch (selection === null || selection === void 0 ? void 0 : selection.type) {
26544
27331
  case 'range':
26545
- editor.formatContentModel(function (model) {
26546
- return handleTab(model, rawEvent);
27332
+ editor.formatContentModel(function (model, context) {
27333
+ return handleTab(model, rawEvent, context);
26547
27334
  }, {
26548
27335
  apiName: 'handleTabKey',
26549
27336
  });
@@ -26565,7 +27352,7 @@ exports.keyboardTab = keyboardTab;
26565
27352
  * - If it is a paragraph, call handleTabOnParagraph to handle the tab key.
26566
27353
  * - If it is a list item, call handleTabOnList to handle the tab key.
26567
27354
  */
26568
- function handleTab(model, rawEvent) {
27355
+ function handleTab(model, rawEvent, context) {
26569
27356
  var blocks = (0, roosterjs_content_model_dom_1.getOperationalBlocks)(model, ['ListItem', 'TableCell'], []);
26570
27357
  var block = blocks.length > 0 ? blocks[0].block : undefined;
26571
27358
  if (blocks.length > 1) {
@@ -26577,10 +27364,10 @@ function handleTab(model, rawEvent) {
26577
27364
  return (0, handleTabOnTableCell_1.handleTabOnTableCell)(model, block, rawEvent);
26578
27365
  }
26579
27366
  else if ((block === null || block === void 0 ? void 0 : block.blockType) === 'Paragraph') {
26580
- return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, block, rawEvent);
27367
+ return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, block, rawEvent, context);
26581
27368
  }
26582
27369
  else if ((0, roosterjs_content_model_dom_1.isBlockGroupOfType)(block, 'ListItem')) {
26583
- return (0, handleTabOnList_1.handleTabOnList)(model, block, rawEvent);
27370
+ return (0, handleTabOnList_1.handleTabOnList)(model, block, rawEvent, context);
26584
27371
  }
26585
27372
  return false;
26586
27373
  }
@@ -26605,15 +27392,15 @@ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-mo
26605
27392
  * 2. Otherwise call handleTabOnParagraph.
26606
27393
  * @internal
26607
27394
  */
26608
- function handleTabOnList(model, listItem, rawEvent) {
27395
+ function handleTabOnList(model, listItem, rawEvent, context) {
26609
27396
  var selectedParagraph = findSelectedParagraph(listItem);
26610
27397
  if (!isMarkerAtStartOfBlock(listItem) &&
26611
27398
  selectedParagraph.length == 1 &&
26612
27399
  selectedParagraph[0].blockType === 'Paragraph') {
26613
- return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, selectedParagraph[0], rawEvent);
27400
+ return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, selectedParagraph[0], rawEvent, context);
26614
27401
  }
26615
27402
  else {
26616
- (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
27403
+ (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent', undefined /*length*/, context);
26617
27404
  rawEvent.preventDefault();
26618
27405
  return true;
26619
27406
  }
@@ -26661,7 +27448,7 @@ var space = ' ';
26661
27448
  * 4. When the selection is not collapsed, replace the selected range with a 4 space.
26662
27449
  * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to outdent the whole paragraph
26663
27450
  */
26664
- function handleTabOnParagraph(model, paragraph, rawEvent) {
27451
+ function handleTabOnParagraph(model, paragraph, rawEvent, context) {
26665
27452
  var selectedSegments = paragraph.segments.filter(function (segment) { return segment.isSelected; });
26666
27453
  var isCollapsed = selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';
26667
27454
  var isAllSelected = paragraph.segments.every(function (segment) { return segment.isSelected; });
@@ -26673,7 +27460,7 @@ function handleTabOnParagraph(model, paragraph, rawEvent) {
26673
27460
  (isRtl && (!marginRight || marginRight == '0px')))) {
26674
27461
  return false;
26675
27462
  }
26676
- (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
27463
+ (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent', undefined /*length*/, context);
26677
27464
  }
26678
27465
  else {
26679
27466
  if (!isCollapsed) {
@@ -26988,7 +27775,7 @@ var HyperlinkPlugin = /** @class */ (function () {
26988
27775
  */
26989
27776
  HyperlinkPlugin.prototype.onPluginEvent = function (event) {
26990
27777
  var _this = this;
26991
- var _a, _b;
27778
+ var _a, _b, _c;
26992
27779
  var matchedLink;
26993
27780
  if (event.eventType == 'keyDown') {
26994
27781
  var selection = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDOMSelection();
@@ -27033,6 +27820,9 @@ var HyperlinkPlugin = /** @class */ (function () {
27033
27820
  }
27034
27821
  });
27035
27822
  }
27823
+ else if (event.eventType == 'contentChanged') {
27824
+ (_c = this.domHelper) === null || _c === void 0 ? void 0 : _c.setDomAttribute('title', null /*value*/);
27825
+ }
27036
27826
  };
27037
27827
  HyperlinkPlugin.prototype.runWithHyperlink = function (node, callback) {
27038
27828
  var _a;
@@ -27061,7 +27851,7 @@ exports.HyperlinkPlugin = HyperlinkPlugin;
27061
27851
  "use strict";
27062
27852
 
27063
27853
  Object.defineProperty(exports, "__esModule", ({ value: true }));
27064
- exports.HyperlinkPlugin = exports.MarkdownPlugin = exports.WatermarkPlugin = exports.ContextMenuPluginBase = exports.ShortcutPlugin = exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoMacOS = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = exports.AutoFormatPlugin = exports.EditPlugin = exports.PastePlugin = exports.TableEditPlugin = void 0;
27854
+ exports.getDOMInsertPointRect = exports.CustomReplacePlugin = exports.PickerPlugin = exports.HyperlinkPlugin = exports.MarkdownPlugin = exports.WatermarkPlugin = exports.ContextMenuPluginBase = exports.ShortcutPlugin = exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoMacOS = exports.ShortcutRedoAlt = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = exports.AutoFormatPlugin = exports.EditPlugin = exports.PastePlugin = exports.TableEditPlugin = void 0;
27065
27855
  var TableEditPlugin_1 = __webpack_require__(/*! ./tableEdit/TableEditPlugin */ "./packages/roosterjs-content-model-plugins/lib/tableEdit/TableEditPlugin.ts");
27066
27856
  Object.defineProperty(exports, "TableEditPlugin", ({ enumerable: true, get: function () { return TableEditPlugin_1.TableEditPlugin; } }));
27067
27857
  var PastePlugin_1 = __webpack_require__(/*! ./paste/PastePlugin */ "./packages/roosterjs-content-model-plugins/lib/paste/PastePlugin.ts");
@@ -27078,6 +27868,7 @@ Object.defineProperty(exports, "ShortcutClearFormat", ({ enumerable: true, get:
27078
27868
  Object.defineProperty(exports, "ShortcutUndo", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutUndo; } }));
27079
27869
  Object.defineProperty(exports, "ShortcutUndo2", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutUndo2; } }));
27080
27870
  Object.defineProperty(exports, "ShortcutRedo", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutRedo; } }));
27871
+ Object.defineProperty(exports, "ShortcutRedoAlt", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutRedoAlt; } }));
27081
27872
  Object.defineProperty(exports, "ShortcutRedoMacOS", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutRedoMacOS; } }));
27082
27873
  Object.defineProperty(exports, "ShortcutBullet", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutBullet; } }));
27083
27874
  Object.defineProperty(exports, "ShortcutNumbering", ({ enumerable: true, get: function () { return shortcuts_1.ShortcutNumbering; } }));
@@ -27095,6 +27886,12 @@ var MarkdownPlugin_1 = __webpack_require__(/*! ./markdown/MarkdownPlugin */ "./p
27095
27886
  Object.defineProperty(exports, "MarkdownPlugin", ({ enumerable: true, get: function () { return MarkdownPlugin_1.MarkdownPlugin; } }));
27096
27887
  var HyperlinkPlugin_1 = __webpack_require__(/*! ./hyperlink/HyperlinkPlugin */ "./packages/roosterjs-content-model-plugins/lib/hyperlink/HyperlinkPlugin.ts");
27097
27888
  Object.defineProperty(exports, "HyperlinkPlugin", ({ enumerable: true, get: function () { return HyperlinkPlugin_1.HyperlinkPlugin; } }));
27889
+ var PickerPlugin_1 = __webpack_require__(/*! ./picker/PickerPlugin */ "./packages/roosterjs-content-model-plugins/lib/picker/PickerPlugin.ts");
27890
+ Object.defineProperty(exports, "PickerPlugin", ({ enumerable: true, get: function () { return PickerPlugin_1.PickerPlugin; } }));
27891
+ var CustomReplacePlugin_1 = __webpack_require__(/*! ./customReplace/CustomReplacePlugin */ "./packages/roosterjs-content-model-plugins/lib/customReplace/CustomReplacePlugin.ts");
27892
+ Object.defineProperty(exports, "CustomReplacePlugin", ({ enumerable: true, get: function () { return CustomReplacePlugin_1.CustomReplacePlugin; } }));
27893
+ var getDOMInsertPointRect_1 = __webpack_require__(/*! ./pluginUtils/Rect/getDOMInsertPointRect */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getDOMInsertPointRect.ts");
27894
+ Object.defineProperty(exports, "getDOMInsertPointRect", ({ enumerable: true, get: function () { return getDOMInsertPointRect_1.getDOMInsertPointRect; } }));
27098
27895
 
27099
27896
 
27100
27897
  /***/ }),
@@ -27331,16 +28128,18 @@ function setFormat(editor, character, format, codeFormat) {
27331
28128
  var firstCharIndex = previousSegment.text
27332
28129
  .substring(0, lastCharIndex - 1)
27333
28130
  .lastIndexOf(character);
27334
- var formattedText = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, firstCharIndex, lastCharIndex);
27335
- formattedText.text = formattedText.text.replace(character, '').slice(0, -1);
27336
- formattedText.format = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, formattedText.format), format);
27337
- if (codeFormat) {
27338
- formattedText.code = {
27339
- format: codeFormat,
27340
- };
28131
+ if (lastCharIndex - firstCharIndex > 2) {
28132
+ var formattedText = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, firstCharIndex, lastCharIndex);
28133
+ formattedText.text = formattedText.text.replace(character, '').slice(0, -1);
28134
+ formattedText.format = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, formattedText.format), format);
28135
+ if (codeFormat) {
28136
+ formattedText.code = {
28137
+ format: codeFormat,
28138
+ };
28139
+ }
28140
+ context.canUndoByBackspace = true;
28141
+ return true;
27341
28142
  }
27342
- context.canUndoByBackspace = true;
27343
- return true;
27344
28143
  }
27345
28144
  }
27346
28145
  return false;
@@ -28717,6 +29516,343 @@ function setProcessor(domToModelOption, entry, processorOverride) {
28717
29516
  exports.setProcessor = setProcessor;
28718
29517
 
28719
29518
 
29519
+ /***/ }),
29520
+
29521
+ /***/ "./packages/roosterjs-content-model-plugins/lib/picker/PickerHelperImpl.ts":
29522
+ /*!*********************************************************************************!*\
29523
+ !*** ./packages/roosterjs-content-model-plugins/lib/picker/PickerHelperImpl.ts ***!
29524
+ \*********************************************************************************/
29525
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
29526
+
29527
+ "use strict";
29528
+
29529
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
29530
+ exports.PickerHelperImpl = void 0;
29531
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
29532
+ var getQueryString_1 = __webpack_require__(/*! ./getQueryString */ "./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts");
29533
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
29534
+ /**
29535
+ * @internal
29536
+ */
29537
+ var PickerHelperImpl = /** @class */ (function () {
29538
+ function PickerHelperImpl(editor, handler, triggerCharacter) {
29539
+ this.editor = editor;
29540
+ this.handler = handler;
29541
+ this.triggerCharacter = triggerCharacter;
29542
+ this.direction = null;
29543
+ }
29544
+ /**
29545
+ * Replace the query string with a given Content Model.
29546
+ * This is used for commit a change from picker and insert the committed content into editor.
29547
+ * @param model The Content Model to insert
29548
+ * @param options Options for formatting content model
29549
+ * @param canUndoByBackspace Whether this change can be undone using Backspace key
29550
+ */
29551
+ PickerHelperImpl.prototype.replaceQueryString = function (model, options, canUndoByBackspace) {
29552
+ var _this = this;
29553
+ this.editor.focus();
29554
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(this.editor, function (target, previousSegment, paragraph, _, context) {
29555
+ var potentialSegments = [];
29556
+ var queryString = (0, getQueryString_1.getQueryString)(_this.triggerCharacter, paragraph, previousSegment, potentialSegments);
29557
+ if (queryString) {
29558
+ potentialSegments.forEach(function (x) { return (x.isSelected = true); });
29559
+ (0, roosterjs_content_model_dom_1.mergeModel)(target, model, context);
29560
+ context.canUndoByBackspace = canUndoByBackspace;
29561
+ return true;
29562
+ }
29563
+ else {
29564
+ return false;
29565
+ }
29566
+ }, options);
29567
+ };
29568
+ /**
29569
+ * Notify Picker Plugin that picker is closed from the handler code, so picker plugin can quit the suggesting state
29570
+ */
29571
+ PickerHelperImpl.prototype.closePicker = function () {
29572
+ var _a, _b;
29573
+ if (this.direction) {
29574
+ this.direction = null;
29575
+ (_b = (_a = this.handler).onClosePicker) === null || _b === void 0 ? void 0 : _b.call(_a);
29576
+ }
29577
+ };
29578
+ return PickerHelperImpl;
29579
+ }());
29580
+ exports.PickerHelperImpl = PickerHelperImpl;
29581
+
29582
+
29583
+ /***/ }),
29584
+
29585
+ /***/ "./packages/roosterjs-content-model-plugins/lib/picker/PickerPlugin.ts":
29586
+ /*!*****************************************************************************!*\
29587
+ !*** ./packages/roosterjs-content-model-plugins/lib/picker/PickerPlugin.ts ***!
29588
+ \*****************************************************************************/
29589
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
29590
+
29591
+ "use strict";
29592
+
29593
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
29594
+ exports.PickerPlugin = void 0;
29595
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
29596
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
29597
+ var getQueryString_1 = __webpack_require__(/*! ./getQueryString */ "./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts");
29598
+ var PickerHelperImpl_1 = __webpack_require__(/*! ./PickerHelperImpl */ "./packages/roosterjs-content-model-plugins/lib/picker/PickerHelperImpl.ts");
29599
+ /**
29600
+ * PickerPlugin represents a plugin of editor which can handle picker related behaviors, including
29601
+ * - Show picker when special trigger key is pressed
29602
+ * - Hide picker
29603
+ * - Change selection in picker by Up/Down/Left/Right
29604
+ * - Apply selected item in picker
29605
+ *
29606
+ * PickerPlugin doesn't provide any UI, it just wraps related DOM events and invoke callback functions.
29607
+ */
29608
+ var PickerPlugin = /** @class */ (function () {
29609
+ /**
29610
+ * Construct a new instance of PickerPlugin class
29611
+ * @param triggerCharacter The character to trigger a picker to be shown
29612
+ * @param handler Picker handler for receiving picker state change events
29613
+ */
29614
+ function PickerPlugin(triggerCharacter, handler) {
29615
+ this.triggerCharacter = triggerCharacter;
29616
+ this.handler = handler;
29617
+ this.isMac = false;
29618
+ this.lastQueryString = '';
29619
+ this.helper = null;
29620
+ }
29621
+ /**
29622
+ * Get a friendly name
29623
+ */
29624
+ PickerPlugin.prototype.getName = function () {
29625
+ return 'Picker';
29626
+ };
29627
+ /**
29628
+ * Initialize this plugin. This should only be called from Editor
29629
+ * @param editor Editor instance
29630
+ */
29631
+ PickerPlugin.prototype.initialize = function (editor) {
29632
+ this.isMac = !!editor.getEnvironment().isMac;
29633
+ this.helper = new PickerHelperImpl_1.PickerHelperImpl(editor, this.handler, this.triggerCharacter);
29634
+ this.handler.onInitialize(this.helper);
29635
+ };
29636
+ /**
29637
+ * Dispose this plugin
29638
+ */
29639
+ PickerPlugin.prototype.dispose = function () {
29640
+ this.handler.onDispose();
29641
+ this.helper = null;
29642
+ };
29643
+ /**
29644
+ * Check if the plugin should handle the given event exclusively.
29645
+ * Handle an event exclusively means other plugin will not receive this event in
29646
+ * onPluginEvent method.
29647
+ * If two plugins will return true in willHandleEventExclusively() for the same event,
29648
+ * the final result depends on the order of the plugins are added into editor
29649
+ * @param event The event to check
29650
+ */
29651
+ PickerPlugin.prototype.willHandleEventExclusively = function (event) {
29652
+ var _a;
29653
+ return (!!((_a = this.helper) === null || _a === void 0 ? void 0 : _a.direction) &&
29654
+ event.eventType == 'keyDown' &&
29655
+ ((0, roosterjs_content_model_dom_1.isCursorMovingKey)(event.rawEvent) ||
29656
+ event.rawEvent.key == 'Enter' ||
29657
+ event.rawEvent.key == 'Tab' ||
29658
+ event.rawEvent.key == 'Escape'));
29659
+ };
29660
+ /**
29661
+ * Handle events triggered from editor
29662
+ * @param event PluginEvent object
29663
+ */
29664
+ PickerPlugin.prototype.onPluginEvent = function (event) {
29665
+ if (!this.helper) {
29666
+ return;
29667
+ }
29668
+ switch (event.eventType) {
29669
+ case 'contentChanged':
29670
+ if (this.helper.direction) {
29671
+ if (event.source == roosterjs_content_model_dom_1.ChangeSource.SetContent) {
29672
+ this.helper.closePicker();
29673
+ }
29674
+ else {
29675
+ this.onSuggestingInput(this.helper);
29676
+ }
29677
+ }
29678
+ break;
29679
+ case 'keyDown':
29680
+ if (this.helper.direction) {
29681
+ this.onSuggestingKeyDown(this.helper, event.rawEvent);
29682
+ }
29683
+ break;
29684
+ case 'input':
29685
+ if (this.helper.direction) {
29686
+ this.onSuggestingInput(this.helper);
29687
+ }
29688
+ else {
29689
+ this.onInput(this.helper, event.rawEvent);
29690
+ }
29691
+ break;
29692
+ case 'mouseUp':
29693
+ if (this.helper.direction) {
29694
+ this.helper.closePicker();
29695
+ }
29696
+ break;
29697
+ }
29698
+ };
29699
+ PickerPlugin.prototype.onSuggestingKeyDown = function (helper, event) {
29700
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
29701
+ switch (event.key) {
29702
+ case 'ArrowLeft':
29703
+ case 'ArrowRight':
29704
+ if (helper.direction == 'horizontal' || helper.direction == 'both') {
29705
+ var isIncrement = event.key == 'ArrowRight';
29706
+ if (helper.editor.getDOMHelper().isRightToLeft()) {
29707
+ isIncrement = !isIncrement;
29708
+ }
29709
+ (_b = (_a = this.handler).onSelectionChanged) === null || _b === void 0 ? void 0 : _b.call(_a, isIncrement ? 'next' : 'previous');
29710
+ }
29711
+ event.preventDefault();
29712
+ break;
29713
+ case 'ArrowUp':
29714
+ case 'ArrowDown':
29715
+ {
29716
+ var isIncrement = event.key == 'ArrowDown';
29717
+ if (helper.direction != 'horizontal') {
29718
+ (_d = (_c = this.handler).onSelectionChanged) === null || _d === void 0 ? void 0 : _d.call(_c, helper.direction == 'both'
29719
+ ? isIncrement
29720
+ ? 'nextRow'
29721
+ : 'previousRow'
29722
+ : isIncrement
29723
+ ? 'next'
29724
+ : 'previous');
29725
+ }
29726
+ }
29727
+ event.preventDefault();
29728
+ break;
29729
+ case 'PageUp':
29730
+ case 'PageDown':
29731
+ (_f = (_e = this.handler).onSelectionChanged) === null || _f === void 0 ? void 0 : _f.call(_e, event.key == 'PageDown' ? 'nextPage' : 'previousPage');
29732
+ event.preventDefault();
29733
+ break;
29734
+ case 'Home':
29735
+ case 'End':
29736
+ var hasCtrl = this.isMac ? event.metaKey : event.ctrlKey;
29737
+ (_h = (_g = this.handler).onSelectionChanged) === null || _h === void 0 ? void 0 : _h.call(_g, event.key == 'Home'
29738
+ ? hasCtrl
29739
+ ? 'first'
29740
+ : 'firstInRow'
29741
+ : hasCtrl
29742
+ ? 'last'
29743
+ : 'lastInRow');
29744
+ event.preventDefault();
29745
+ break;
29746
+ case 'Escape':
29747
+ helper.closePicker();
29748
+ event.preventDefault();
29749
+ break;
29750
+ case 'Enter':
29751
+ case 'Tab':
29752
+ (_k = (_j = this.handler).onSelect) === null || _k === void 0 ? void 0 : _k.call(_j);
29753
+ event.preventDefault();
29754
+ break;
29755
+ }
29756
+ };
29757
+ PickerPlugin.prototype.onSuggestingInput = function (helper) {
29758
+ var _this = this;
29759
+ if (!(0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(helper.editor, function (_, segment, paragraph) {
29760
+ var _a, _b;
29761
+ var newQueryString = (0, getQueryString_1.getQueryString)(_this.triggerCharacter, paragraph, segment).replace(/[\u0020\u00A0]/g, ' ');
29762
+ var oldQueryString = _this.lastQueryString;
29763
+ if (newQueryString &&
29764
+ ((newQueryString.length >= oldQueryString.length &&
29765
+ newQueryString.indexOf(oldQueryString) == 0) ||
29766
+ (newQueryString.length < oldQueryString.length &&
29767
+ oldQueryString.indexOf(newQueryString) == 0))) {
29768
+ _this.lastQueryString = newQueryString;
29769
+ (_b = (_a = _this.handler).onQueryStringChanged) === null || _b === void 0 ? void 0 : _b.call(_a, newQueryString);
29770
+ }
29771
+ else {
29772
+ helper.closePicker();
29773
+ }
29774
+ return false;
29775
+ })) {
29776
+ helper.closePicker();
29777
+ }
29778
+ };
29779
+ PickerPlugin.prototype.onInput = function (helper, event) {
29780
+ var _this = this;
29781
+ if (event.inputType == 'insertText' && event.data == this.triggerCharacter) {
29782
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(helper.editor, function (_, segment) {
29783
+ if (segment.text.endsWith(_this.triggerCharacter)) {
29784
+ var charBeforeTrigger = segment.text[segment.text.length - 2];
29785
+ if (!charBeforeTrigger ||
29786
+ !charBeforeTrigger.trim() ||
29787
+ (0, roosterjs_content_model_dom_1.isPunctuation)(charBeforeTrigger)) {
29788
+ var selection = helper.editor.getDOMSelection();
29789
+ var pos = (selection === null || selection === void 0 ? void 0 : selection.type) == 'range' && selection.range.collapsed
29790
+ ? {
29791
+ node: selection.range.startContainer,
29792
+ offset: selection.range.startOffset,
29793
+ }
29794
+ : null;
29795
+ if (pos) {
29796
+ _this.lastQueryString = _this.triggerCharacter;
29797
+ helper.direction = _this.handler.onTrigger(_this.lastQueryString, pos);
29798
+ }
29799
+ }
29800
+ }
29801
+ return false;
29802
+ });
29803
+ }
29804
+ };
29805
+ return PickerPlugin;
29806
+ }());
29807
+ exports.PickerPlugin = PickerPlugin;
29808
+
29809
+
29810
+ /***/ }),
29811
+
29812
+ /***/ "./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts":
29813
+ /*!*******************************************************************************!*\
29814
+ !*** ./packages/roosterjs-content-model-plugins/lib/picker/getQueryString.ts ***!
29815
+ \*******************************************************************************/
29816
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
29817
+
29818
+ "use strict";
29819
+
29820
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
29821
+ exports.getQueryString = void 0;
29822
+ var splitTextSegment_1 = __webpack_require__(/*! ../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
29823
+ /**
29824
+ * @internal
29825
+ */
29826
+ function getQueryString(triggerCharacter, paragraph, previousSegment, splittedSegmentResult) {
29827
+ var result = '';
29828
+ var i = paragraph.segments.indexOf(previousSegment);
29829
+ for (; i >= 0; i--) {
29830
+ var segment = paragraph.segments[i];
29831
+ if (segment.segmentType != 'Text') {
29832
+ result = '';
29833
+ break;
29834
+ }
29835
+ var index = segment.text.lastIndexOf(triggerCharacter);
29836
+ if (index >= 0) {
29837
+ result = segment.text.substring(index) + result;
29838
+ splittedSegmentResult === null || splittedSegmentResult === void 0 ? void 0 : splittedSegmentResult.unshift(index > 0
29839
+ ? (0, splitTextSegment_1.splitTextSegment)(segment, paragraph, index, segment.text.length)
29840
+ : segment);
29841
+ break;
29842
+ }
29843
+ else {
29844
+ result = segment.text + result;
29845
+ splittedSegmentResult === null || splittedSegmentResult === void 0 ? void 0 : splittedSegmentResult.unshift(segment);
29846
+ }
29847
+ }
29848
+ if (i < 0) {
29849
+ result = '';
29850
+ }
29851
+ return result;
29852
+ }
29853
+ exports.getQueryString = getQueryString;
29854
+
29855
+
28720
29856
  /***/ }),
28721
29857
 
28722
29858
  /***/ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/CreateElement/createElement.ts":
@@ -28910,6 +30046,73 @@ var DragAndDropHelper = /** @class */ (function () {
28910
30046
  exports.DragAndDropHelper = DragAndDropHelper;
28911
30047
 
28912
30048
 
30049
+ /***/ }),
30050
+
30051
+ /***/ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getDOMInsertPointRect.ts":
30052
+ /*!************************************************************************************************!*\
30053
+ !*** ./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getDOMInsertPointRect.ts ***!
30054
+ \************************************************************************************************/
30055
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
30056
+
30057
+ "use strict";
30058
+
30059
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
30060
+ exports.getDOMInsertPointRect = void 0;
30061
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
30062
+ /**
30063
+ * Get bounding rect of the given DOM insert point
30064
+ * @param doc The document object
30065
+ * @param pos The input DOM insert point
30066
+ */
30067
+ function getDOMInsertPointRect(doc, pos) {
30068
+ var _a;
30069
+ var node = pos.node, offset = pos.offset;
30070
+ var range = doc.createRange();
30071
+ range.setStart(node, offset);
30072
+ // 1) try to get rect using range.getBoundingClientRect()
30073
+ var rect = (0, roosterjs_content_model_dom_1.normalizeRect)(range.getBoundingClientRect());
30074
+ if (rect) {
30075
+ return rect;
30076
+ }
30077
+ // 2) try to get rect using range.getClientRects
30078
+ while (node.lastChild) {
30079
+ if (offset == node.childNodes.length) {
30080
+ node = node.lastChild;
30081
+ offset = node.childNodes.length;
30082
+ }
30083
+ else {
30084
+ node = node.childNodes[offset];
30085
+ offset = 0;
30086
+ }
30087
+ }
30088
+ var rects = range.getClientRects && range.getClientRects();
30089
+ rect = rects && rects.length == 1 ? (0, roosterjs_content_model_dom_1.normalizeRect)(rects[0]) : null;
30090
+ if (rect) {
30091
+ return rect;
30092
+ }
30093
+ // 3) if node is text node, try inserting a SPAN and get the rect of SPAN for others
30094
+ if ((0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'TEXT_NODE')) {
30095
+ var span = node.ownerDocument.createElement('span');
30096
+ span.textContent = '\u200b';
30097
+ range.insertNode(span);
30098
+ rect = (0, roosterjs_content_model_dom_1.normalizeRect)(span.getBoundingClientRect());
30099
+ (_a = span.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(span);
30100
+ if (rect) {
30101
+ return rect;
30102
+ }
30103
+ }
30104
+ // 4) try getBoundingClientRect on element
30105
+ if ((0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'ELEMENT_NODE') && node.getBoundingClientRect) {
30106
+ rect = (0, roosterjs_content_model_dom_1.normalizeRect)(node.getBoundingClientRect());
30107
+ if (rect) {
30108
+ return rect;
30109
+ }
30110
+ }
30111
+ return null;
30112
+ }
30113
+ exports.getDOMInsertPointRect = getDOMInsertPointRect;
30114
+
30115
+
28913
30116
  /***/ }),
28914
30117
 
28915
30118
  /***/ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getIntersectedRect.ts":
@@ -29024,6 +30227,7 @@ var defaultShortcuts = [
29024
30227
  shortcuts_1.ShortcutUndo,
29025
30228
  shortcuts_1.ShortcutUndo2,
29026
30229
  shortcuts_1.ShortcutRedo,
30230
+ shortcuts_1.ShortcutRedoAlt,
29027
30231
  shortcuts_1.ShortcutRedoMacOS,
29028
30232
  shortcuts_1.ShortcutBullet,
29029
30233
  shortcuts_1.ShortcutNumbering,
@@ -29143,7 +30347,7 @@ exports.ShortcutPlugin = ShortcutPlugin;
29143
30347
  "use strict";
29144
30348
 
29145
30349
  Object.defineProperty(exports, "__esModule", ({ value: true }));
29146
- exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoMacOS = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = void 0;
30350
+ exports.ShortcutOutdentList = exports.ShortcutIndentList = exports.ShortcutDecreaseFont = exports.ShortcutIncreaseFont = exports.ShortcutNumbering = exports.ShortcutBullet = exports.ShortcutRedoAlt = exports.ShortcutRedoMacOS = exports.ShortcutRedo = exports.ShortcutUndo2 = exports.ShortcutUndo = exports.ShortcutClearFormat = exports.ShortcutUnderline = exports.ShortcutItalic = exports.ShortcutBold = void 0;
29147
30351
  var roosterjs_content_model_core_1 = __webpack_require__(/*! roosterjs-content-model-core */ "./packages/roosterjs-content-model-core/lib/index.ts");
29148
30352
  var setShortcutIndentationCommand_1 = __webpack_require__(/*! ./utils/setShortcutIndentationCommand */ "./packages/roosterjs-content-model-plugins/lib/shortcut/utils/setShortcutIndentationCommand.ts");
29149
30353
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
@@ -29257,6 +30461,7 @@ exports.ShortcutRedo = {
29257
30461
  environment: 'nonMac',
29258
30462
  };
29259
30463
  /**
30464
+ * @deprecated
29260
30465
  * Shortcut command for Redo 2
29261
30466
  * Windows: N/A
29262
30467
  * MacOS: Meta + Shift + Z
@@ -29270,6 +30475,19 @@ exports.ShortcutRedoMacOS = {
29270
30475
  onClick: function (editor) { return (0, roosterjs_content_model_core_1.redo)(editor); },
29271
30476
  environment: 'mac',
29272
30477
  };
30478
+ /**
30479
+ * Shortcut command for Redo 3
30480
+ * Windows: Ctrl + Shift + Z
30481
+ * MacOS: Meta + Shift + Z
30482
+ */
30483
+ exports.ShortcutRedoAlt = {
30484
+ shortcutKey: {
30485
+ modifierKey: 'ctrl',
30486
+ shiftKey: true,
30487
+ which: 90 /* Z */,
30488
+ },
30489
+ onClick: function (editor) { return (0, roosterjs_content_model_core_1.redo)(editor); },
30490
+ };
29273
30491
  /**
29274
30492
  * Shortcut command for Bullet List
29275
30493
  * Windows: Ctrl + . (Period)
@@ -29374,12 +30592,12 @@ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-mo
29374
30592
  * @internal
29375
30593
  */
29376
30594
  function setShortcutIndentationCommand(editor, operation) {
29377
- editor.formatContentModel(function (model) {
30595
+ editor.formatContentModel(function (model, context) {
29378
30596
  var listItem = (0, roosterjs_content_model_dom_1.getFirstSelectedListItem)(model);
29379
30597
  if (listItem &&
29380
30598
  listItem.blocks[0].blockType == 'Paragraph' &&
29381
30599
  listItem.blocks[0].segments[0].segmentType == 'SelectionMarker') {
29382
- (0, roosterjs_content_model_api_1.setModelIndentation)(model, operation);
30600
+ (0, roosterjs_content_model_api_1.setModelIndentation)(model, operation, undefined /*length*/, context);
29383
30601
  return true;
29384
30602
  }
29385
30603
  return false;
@@ -29412,10 +30630,14 @@ var TableEditPlugin = /** @class */ (function () {
29412
30630
  * @param anchorContainerSelector An optional selector string to specify the container to host the plugin.
29413
30631
  * The container must not be affected by transform: scale(), otherwise the position calculation will be wrong.
29414
30632
  * If not specified, the plugin will be inserted in document.body
30633
+ * @param onTableEditorCreated An optional callback to customize the Table Editors elements when created.
30634
+ * @param disableFeatures An optional array of TableEditFeatures to disable
29415
30635
  */
29416
- function TableEditPlugin(anchorContainerSelector) {
30636
+ function TableEditPlugin(anchorContainerSelector, onTableEditorCreated, disableFeatures) {
29417
30637
  var _this = this;
29418
30638
  this.anchorContainerSelector = anchorContainerSelector;
30639
+ this.onTableEditorCreated = onTableEditorCreated;
30640
+ this.disableFeatures = disableFeatures;
29419
30641
  this.editor = null;
29420
30642
  this.onMouseMoveDisposer = null;
29421
30643
  this.tableRectMap = null;
@@ -29493,6 +30715,7 @@ var TableEditPlugin = /** @class */ (function () {
29493
30715
  this.disposeTableEditor();
29494
30716
  this.editor = null;
29495
30717
  this.onMouseMoveDisposer = null;
30718
+ this.onTableEditorCreated = undefined;
29496
30719
  };
29497
30720
  /**
29498
30721
  * Handle events triggered from editor
@@ -29523,7 +30746,7 @@ var TableEditPlugin = /** @class */ (function () {
29523
30746
  var container = this.anchorContainerSelector
29524
30747
  ? this.editor.getDocument().querySelector(this.anchorContainerSelector)
29525
30748
  : undefined;
29526
- this.tableEditor = new TableEditor_1.TableEditor(this.editor, table, this.invalidateTableRects, (0, roosterjs_content_model_dom_1.isNodeOfType)(container, 'ELEMENT_NODE') ? container : undefined, event === null || event === void 0 ? void 0 : event.currentTarget);
30749
+ 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, this.disableFeatures);
29527
30750
  }
29528
30751
  };
29529
30752
  TableEditPlugin.prototype.disposeTableEditor = function () {
@@ -29608,7 +30831,7 @@ var TOP_OR_SIDE;
29608
30831
  * When set a different current table or change current TD, we need to update these areas
29609
30832
  */
29610
30833
  var TableEditor = /** @class */ (function () {
29611
- function TableEditor(editor, table, onChanged, anchorContainer, contentDiv) {
30834
+ function TableEditor(editor, table, onChanged, anchorContainer, contentDiv, onTableEditorCreated, disableFeatures) {
29612
30835
  var _this = this;
29613
30836
  var _a;
29614
30837
  this.editor = editor;
@@ -29616,6 +30839,8 @@ var TableEditor = /** @class */ (function () {
29616
30839
  this.onChanged = onChanged;
29617
30840
  this.anchorContainer = anchorContainer;
29618
30841
  this.contentDiv = contentDiv;
30842
+ this.onTableEditorCreated = onTableEditorCreated;
30843
+ this.disableFeatures = disableFeatures;
29619
30844
  // 1, 2 - Insert a column or a row
29620
30845
  this.horizontalInserter = null;
29621
30846
  this.verticalInserter = null;
@@ -29627,6 +30852,20 @@ var TableEditor = /** @class */ (function () {
29627
30852
  // 6 - Move as well as select whole table
29628
30853
  this.tableMover = null;
29629
30854
  this.range = null;
30855
+ this.onEditorCreated = function (featureType, element) {
30856
+ var _a;
30857
+ var disposer = (_a = _this.onTableEditorCreated) === null || _a === void 0 ? void 0 : _a.call(_this, featureType, element);
30858
+ var onMouseOut = element && _this.getOnMouseOut(element);
30859
+ if (onMouseOut) {
30860
+ element.addEventListener('mouseout', onMouseOut);
30861
+ }
30862
+ return function () {
30863
+ disposer === null || disposer === void 0 ? void 0 : disposer();
30864
+ if (onMouseOut) {
30865
+ element.removeEventListener('mouseout', onMouseOut);
30866
+ }
30867
+ };
30868
+ };
29630
30869
  this.onFinishEditing = function () {
29631
30870
  _this.editor.focus();
29632
30871
  if (_this.range) {
@@ -29646,6 +30885,16 @@ var TableEditor = /** @class */ (function () {
29646
30885
  _this.disposeTableResizer();
29647
30886
  _this.onStartResize();
29648
30887
  };
30888
+ this.onStartTableMove = function () {
30889
+ _this.isCurrentlyEditing = true;
30890
+ _this.disposeTableResizer();
30891
+ _this.disposeTableInserter();
30892
+ _this.disposeCellResizers();
30893
+ };
30894
+ this.onEndTableMove = function () {
30895
+ _this.disposeTableMover();
30896
+ return _this.onFinishEditing();
30897
+ };
29649
30898
  this.onInserted = function () {
29650
30899
  _this.disposeTableResizer();
29651
30900
  _this.onFinishEditing();
@@ -29655,14 +30904,16 @@ var TableEditor = /** @class */ (function () {
29655
30904
  * @param table the table to select
29656
30905
  */
29657
30906
  this.onSelect = function (table) {
30907
+ var _a, _b;
29658
30908
  _this.editor.focus();
29659
30909
  if (table) {
30910
+ var parsedTable = (0, roosterjs_content_model_dom_1.parseTableCells)(table);
29660
30911
  var selection = {
29661
30912
  table: table,
29662
30913
  firstRow: 0,
29663
30914
  firstColumn: 0,
29664
- lastRow: table.rows.length - 1,
29665
- lastColumn: table.rows[table.rows.length - 1].cells.length - 1,
30915
+ lastRow: parsedTable.length - 1,
30916
+ lastColumn: ((_b = (_a = parsedTable[0]) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) - 1,
29666
30917
  type: 'table',
29667
30918
  };
29668
30919
  _this.editor.setDOMSelection(selection);
@@ -29674,7 +30925,8 @@ var TableEditor = /** @class */ (function () {
29674
30925
  ev.relatedTarget != feature &&
29675
30926
  (0, roosterjs_content_model_dom_1.isNodeOfType)(_this.contentDiv, 'ELEMENT_NODE') &&
29676
30927
  (0, roosterjs_content_model_dom_1.isNodeOfType)(ev.relatedTarget, 'ELEMENT_NODE') &&
29677
- !(_this.contentDiv == ev.relatedTarget)) {
30928
+ !(_this.contentDiv == ev.relatedTarget) &&
30929
+ !_this.isEditing()) {
29678
30930
  _this.dispose();
29679
30931
  }
29680
30932
  };
@@ -29708,7 +30960,6 @@ var TableEditor = /** @class */ (function () {
29708
30960
  var _a;
29709
30961
  // Get whole table rect
29710
30962
  var tableRect = (0, roosterjs_content_model_dom_1.normalizeRect)(this.table.getBoundingClientRect());
29711
- //console.log('>>>tableRect', tableRect);
29712
30963
  if (!tableRect) {
29713
30964
  return;
29714
30965
  }
@@ -29746,7 +30997,8 @@ var TableEditor = /** @class */ (function () {
29746
30997
  if (i === 0 && topOrSide == 0 /* top */) {
29747
30998
  var center = (tdRect.left + tdRect.right) / 2;
29748
30999
  var isOnRightHalf = this.isRTL ? x < center : x > center;
29749
- this.setInserterTd(isOnRightHalf ? td : tr.cells[j - 1], false /*isHorizontal*/);
31000
+ !this.isFeatureDisabled('VerticalTableInserter') &&
31001
+ this.setInserterTd(isOnRightHalf ? td : tr.cells[j - 1], false /*isHorizontal*/);
29750
31002
  }
29751
31003
  else if (j === 0 && topOrSide == 1 /* side */) {
29752
31004
  var tdAbove = (_a = this.table.rows[i - 1]) === null || _a === void 0 ? void 0 : _a.cells[0];
@@ -29758,14 +31010,15 @@ var TableEditor = /** @class */ (function () {
29758
31010
  : this.isRTL
29759
31011
  ? tdAboveRect.right === tdRect.right
29760
31012
  : tdAboveRect.left === tdRect.left;
29761
- this.setInserterTd(y < (tdRect.top + tdRect.bottom) / 2 && isTdNotAboveMerged
29762
- ? tdAbove
29763
- : td, true /*isHorizontal*/);
31013
+ !this.isFeatureDisabled('HorizontalTableInserter') &&
31014
+ this.setInserterTd(y < (tdRect.top + tdRect.bottom) / 2 && isTdNotAboveMerged
31015
+ ? tdAbove
31016
+ : td, true /*isHorizontal*/);
29764
31017
  }
29765
31018
  else {
29766
31019
  this.setInserterTd(null);
29767
31020
  }
29768
- this.setResizingTd(td);
31021
+ !this.isFeatureDisabled('CellResizer') && this.setResizingTd(td);
29769
31022
  //Cell found
29770
31023
  break;
29771
31024
  }
@@ -29778,11 +31031,13 @@ var TableEditor = /** @class */ (function () {
29778
31031
  this.setEditorFeatures();
29779
31032
  };
29780
31033
  TableEditor.prototype.setEditorFeatures = function () {
29781
- if (!this.tableMover) {
29782
- this.tableMover = (0, TableMover_1.createTableMover)(this.table, this.editor, this.isRTL, this.onSelect, this.getOnMouseOut, this.contentDiv, this.anchorContainer);
31034
+ var disableSelector = this.isFeatureDisabled('TableSelector');
31035
+ var disableMovement = this.isFeatureDisabled('TableMover');
31036
+ if (!this.tableMover && !(disableSelector && disableMovement)) {
31037
+ this.tableMover = (0, TableMover_1.createTableMover)(this.table, this.editor, this.isRTL, disableSelector ? function () { } : this.onSelect, this.onStartTableMove, this.onEndTableMove, this.contentDiv, this.anchorContainer, this.onEditorCreated, disableMovement);
29783
31038
  }
29784
- if (!this.tableResizer) {
29785
- this.tableResizer = (0, TableResizer_1.createTableResizer)(this.table, this.editor, this.isRTL, this.onStartTableResize, this.onFinishEditing, this.contentDiv, this.anchorContainer);
31039
+ if (!this.tableResizer && !this.isFeatureDisabled('TableResizer')) {
31040
+ this.tableResizer = (0, TableResizer_1.createTableResizer)(this.table, this.editor, this.isRTL, this.onStartTableResize, this.onFinishEditing, this.contentDiv, this.anchorContainer, this.onTableEditorCreated);
29786
31041
  }
29787
31042
  };
29788
31043
  TableEditor.prototype.setResizingTd = function (td) {
@@ -29804,7 +31059,7 @@ var TableEditor = /** @class */ (function () {
29804
31059
  this.disposeTableInserter();
29805
31060
  }
29806
31061
  if (!this.horizontalInserter && !this.verticalInserter && td) {
29807
- var newInserter = (0, TableInserter_1.createTableInserter)(this.editor, td, this.table, this.isRTL, !!isHorizontal, this.onInserted, this.getOnMouseOut, this.anchorContainer);
31062
+ var newInserter = (0, TableInserter_1.createTableInserter)(this.editor, td, this.table, this.isRTL, !!isHorizontal, this.onInserted, this.anchorContainer, this.onEditorCreated);
29808
31063
  if (isHorizontal) {
29809
31064
  this.horizontalInserter = newInserter;
29810
31065
  }
@@ -29853,6 +31108,10 @@ var TableEditor = /** @class */ (function () {
29853
31108
  }
29854
31109
  this.editor.takeSnapshot();
29855
31110
  };
31111
+ TableEditor.prototype.isFeatureDisabled = function (feature) {
31112
+ var _a;
31113
+ return (_a = this.disableFeatures) === null || _a === void 0 ? void 0 : _a.includes(feature);
31114
+ };
29856
31115
  return TableEditor;
29857
31116
  }());
29858
31117
  exports.TableEditor = TableEditor;
@@ -29869,12 +31128,20 @@ exports.TableEditor = TableEditor;
29869
31128
  "use strict";
29870
31129
 
29871
31130
  Object.defineProperty(exports, "__esModule", ({ value: true }));
29872
- exports.createCellResizer = void 0;
31131
+ exports.createCellResizer = exports.VERTICAL_RESIZER_ID = exports.HORIZONTAL_RESIZER_ID = void 0;
29873
31132
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
29874
31133
  var createElement_1 = __webpack_require__(/*! ../../../pluginUtils/CreateElement/createElement */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/CreateElement/createElement.ts");
29875
31134
  var DragAndDropHelper_1 = __webpack_require__(/*! ../../../pluginUtils/DragAndDrop/DragAndDropHelper */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/DragAndDrop/DragAndDropHelper.ts");
29876
31135
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
29877
31136
  var CELL_RESIZER_WIDTH = 4;
31137
+ /**
31138
+ * @internal
31139
+ */
31140
+ exports.HORIZONTAL_RESIZER_ID = 'horizontalResizer';
31141
+ /**
31142
+ * @internal
31143
+ */
31144
+ exports.VERTICAL_RESIZER_ID = 'verticalResizer';
29878
31145
  /**
29879
31146
  * @internal
29880
31147
  */
@@ -30016,7 +31283,7 @@ function setHorizontalPosition(context, trigger) {
30016
31283
  var td = context.td;
30017
31284
  var rect = (0, roosterjs_content_model_dom_1.normalizeRect)(td.getBoundingClientRect());
30018
31285
  if (rect) {
30019
- trigger.id = 'horizontalResizer';
31286
+ trigger.id = exports.HORIZONTAL_RESIZER_ID;
30020
31287
  trigger.style.top = rect.bottom - CELL_RESIZER_WIDTH + 'px';
30021
31288
  trigger.style.left = rect.left + 'px';
30022
31289
  trigger.style.width = rect.right - rect.left + 'px';
@@ -30027,7 +31294,7 @@ function setVerticalPosition(context, trigger) {
30027
31294
  var td = context.td, isRTL = context.isRTL;
30028
31295
  var rect = (0, roosterjs_content_model_dom_1.normalizeRect)(td.getBoundingClientRect());
30029
31296
  if (rect) {
30030
- trigger.id = 'verticalResizer';
31297
+ trigger.id = exports.VERTICAL_RESIZER_ID;
30031
31298
  trigger.style.top = rect.top + 'px';
30032
31299
  trigger.style.left = (isRTL ? rect.left : rect.right) - CELL_RESIZER_WIDTH + 1 + 'px';
30033
31300
  trigger.style.width = CELL_RESIZER_WIDTH + 'px';
@@ -30051,13 +31318,13 @@ exports.disposeTableEditFeature = void 0;
30051
31318
  /**
30052
31319
  * @internal
30053
31320
  */
30054
- function disposeTableEditFeature(resizer) {
31321
+ function disposeTableEditFeature(feature) {
30055
31322
  var _a, _b, _c;
30056
- if (resizer) {
30057
- (_b = (_a = resizer.div) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(resizer.div);
30058
- resizer.div = null;
30059
- (_c = resizer.featureHandler) === null || _c === void 0 ? void 0 : _c.dispose();
30060
- resizer.featureHandler = null;
31323
+ if (feature) {
31324
+ (_a = feature.featureHandler) === null || _a === void 0 ? void 0 : _a.dispose();
31325
+ feature.featureHandler = null;
31326
+ (_c = (_b = feature.div) === null || _b === void 0 ? void 0 : _b.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(feature.div);
31327
+ feature.div = null;
30061
31328
  }
30062
31329
  }
30063
31330
  exports.disposeTableEditFeature = disposeTableEditFeature;
@@ -30074,7 +31341,7 @@ exports.disposeTableEditFeature = disposeTableEditFeature;
30074
31341
  "use strict";
30075
31342
 
30076
31343
  Object.defineProperty(exports, "__esModule", ({ value: true }));
30077
- exports.createTableInserter = void 0;
31344
+ exports.createTableInserter = exports.VERTICAL_INSERTER_ID = exports.HORIZONTAL_INSERTER_ID = void 0;
30078
31345
  var createElement_1 = __webpack_require__(/*! ../../../pluginUtils/CreateElement/createElement */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/CreateElement/createElement.ts");
30079
31346
  var getIntersectedRect_1 = __webpack_require__(/*! ../../../pluginUtils/Rect/getIntersectedRect */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/Rect/getIntersectedRect.ts");
30080
31347
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
@@ -30086,7 +31353,15 @@ var INSERTER_BORDER_SIZE = 1;
30086
31353
  /**
30087
31354
  * @internal
30088
31355
  */
30089
- function createTableInserter(editor, td, table, isRTL, isHorizontal, onInsert, getOnMouseOut, anchorContainer) {
31356
+ exports.HORIZONTAL_INSERTER_ID = 'horizontalInserter';
31357
+ /**
31358
+ * @internal
31359
+ */
31360
+ exports.VERTICAL_INSERTER_ID = 'verticalInserter';
31361
+ /**
31362
+ * @internal
31363
+ */
31364
+ function createTableInserter(editor, td, table, isRTL, isHorizontal, onInsert, anchorContainer, onTableEditorCreated) {
30090
31365
  var tdRect = (0, roosterjs_content_model_dom_1.normalizeRect)(td.getBoundingClientRect());
30091
31366
  var viewPort = editor.getVisibleViewport();
30092
31367
  var tableRect = table && viewPort ? (0, getIntersectedRect_1.getIntersectedRect)([table], [viewPort]) : null;
@@ -30097,7 +31372,7 @@ function createTableInserter(editor, td, table, isRTL, isHorizontal, onInsert, g
30097
31372
  var div = (0, createElement_1.createElement)(createElementData, document_1);
30098
31373
  if (isHorizontal) {
30099
31374
  // tableRect.left/right is used because the Inserter is always intended to be on the side
30100
- div.id = 'horizontalInserter';
31375
+ div.id = exports.HORIZONTAL_INSERTER_ID;
30101
31376
  div.style.left = (isRTL
30102
31377
  ? tableRect.right
30103
31378
  : tableRect.left - (INSERTER_SIDE_LENGTH - 1 + 2 * INSERTER_BORDER_SIZE)) + "px";
@@ -30105,21 +31380,21 @@ function createTableInserter(editor, td, table, isRTL, isHorizontal, onInsert, g
30105
31380
  div.firstChild.style.width = tableRect.right - tableRect.left + "px";
30106
31381
  }
30107
31382
  else {
30108
- div.id = 'verticalInserter';
31383
+ div.id = exports.VERTICAL_INSERTER_ID;
30109
31384
  div.style.left = (isRTL ? tdRect.left - 8 : tdRect.right - 8) + "px";
30110
31385
  // tableRect.top is used because the Inserter is always intended to be on top
30111
31386
  div.style.top = tableRect.top - (INSERTER_SIDE_LENGTH - 1 + 2 * INSERTER_BORDER_SIZE) + "px";
30112
31387
  div.firstChild.style.height = tableRect.bottom - tableRect.top + "px";
30113
31388
  }
30114
31389
  (anchorContainer || document_1.body).appendChild(div);
30115
- var handler = new TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, getOnMouseOut);
31390
+ var handler = new TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, onTableEditorCreated);
30116
31391
  return { div: div, featureHandler: handler, node: td };
30117
31392
  }
30118
31393
  return null;
30119
31394
  }
30120
31395
  exports.createTableInserter = createTableInserter;
30121
31396
  var TableInsertHandler = /** @class */ (function () {
30122
- function TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, getOnMouseOut) {
31397
+ function TableInsertHandler(div, td, table, isHorizontal, editor, onInsert, onTableEditorCreated) {
30123
31398
  var _this = this;
30124
31399
  this.div = div;
30125
31400
  this.td = td;
@@ -30154,15 +31429,13 @@ var TableInsertHandler = /** @class */ (function () {
30154
31429
  _this.onInsert();
30155
31430
  };
30156
31431
  this.div.addEventListener('click', this.insertTd);
30157
- this.onMouseOutEvent = getOnMouseOut(div);
30158
- this.div.addEventListener('mouseout', this.onMouseOutEvent);
31432
+ this.disposer = onTableEditorCreated === null || onTableEditorCreated === void 0 ? void 0 : onTableEditorCreated(isHorizontal ? 'HorizontalTableInserter' : 'VerticalTableInserter', div);
30159
31433
  }
30160
31434
  TableInsertHandler.prototype.dispose = function () {
31435
+ var _a;
30161
31436
  this.div.removeEventListener('click', this.insertTd);
30162
- if (this.onMouseOutEvent) {
30163
- this.div.removeEventListener('mouseout', this.onMouseOutEvent);
30164
- }
30165
- this.onMouseOutEvent = null;
31437
+ (_a = this.disposer) === null || _a === void 0 ? void 0 : _a.call(this);
31438
+ this.disposer = undefined;
30166
31439
  };
30167
31440
  return TableInsertHandler;
30168
31441
  }());
@@ -30197,19 +31470,24 @@ function getInsertElementData(isHorizontal, isDark, isRTL, backgroundColor) {
30197
31470
  "use strict";
30198
31471
 
30199
31472
  Object.defineProperty(exports, "__esModule", ({ value: true }));
30200
- exports.createTableMover = void 0;
31473
+ exports.onDragEnd = exports.onDragging = exports.onDragStart = exports.createTableMover = exports.TABLE_MOVER_ID = void 0;
30201
31474
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
30202
31475
  var createElement_1 = __webpack_require__(/*! ../../../pluginUtils/CreateElement/createElement */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/CreateElement/createElement.ts");
30203
31476
  var DragAndDropHelper_1 = __webpack_require__(/*! ../../../pluginUtils/DragAndDrop/DragAndDropHelper */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/DragAndDrop/DragAndDropHelper.ts");
31477
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
30204
31478
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
30205
31479
  var TABLE_MOVER_LENGTH = 12;
30206
- var TABLE_MOVER_ID = '_Table_Mover';
30207
31480
  /**
30208
31481
  * @internal
31482
+ */
31483
+ exports.TABLE_MOVER_ID = '_Table_Mover';
31484
+ var TABLE_MOVER_STYLE_KEY = '_TableMoverCursorStyle';
31485
+ /**
31486
+ * @internal
31487
+ * Allows user to move table to another position
30209
31488
  * Contains the function to select whole table
30210
- * Moving behavior not implemented yet
30211
31489
  */
30212
- function createTableMover(table, editor, isRTL, onFinishDragging, getOnMouseOut, contentDiv, anchorContainer) {
31490
+ function createTableMover(table, editor, isRTL, onFinishDragging, onStart, onEnd, contentDiv, anchorContainer, onTableEditorCreated, disableMovement) {
30213
31491
  var rect = (0, roosterjs_content_model_dom_1.normalizeRect)(table.getBoundingClientRect());
30214
31492
  if (!isTableTopVisible(editor, rect, contentDiv)) {
30215
31493
  return null;
@@ -30218,10 +31496,10 @@ function createTableMover(table, editor, isRTL, onFinishDragging, getOnMouseOut,
30218
31496
  var document = table.ownerDocument;
30219
31497
  var createElementData = {
30220
31498
  tag: 'div',
30221
- style: 'position: fixed; cursor: all-scroll; user-select: none; border: 1px solid #808080',
31499
+ style: 'position: fixed; cursor: move; user-select: none; border: 1px solid #808080',
30222
31500
  };
30223
31501
  var div = (0, createElement_1.createElement)(createElementData, document);
30224
- div.id = TABLE_MOVER_ID;
31502
+ div.id = exports.TABLE_MOVER_ID;
30225
31503
  div.style.width = TABLE_MOVER_LENGTH + "px";
30226
31504
  div.style.height = TABLE_MOVER_LENGTH + "px";
30227
31505
  (anchorContainer || document.body).appendChild(div);
@@ -30230,35 +31508,36 @@ function createTableMover(table, editor, isRTL, onFinishDragging, getOnMouseOut,
30230
31508
  zoomScale: zoomScale,
30231
31509
  rect: rect,
30232
31510
  isRTL: isRTL,
31511
+ editor: editor,
31512
+ div: div,
31513
+ onFinishDragging: onFinishDragging,
31514
+ onStart: onStart,
31515
+ onEnd: onEnd,
31516
+ disableMovement: disableMovement,
30233
31517
  };
30234
31518
  setDivPosition(context, div);
30235
- var onDragEnd = function (context, event) {
30236
- if (event.target == div) {
30237
- onFinishDragging(context.table);
30238
- }
30239
- return false;
30240
- };
30241
- var featureHandler = new TableMoverFeature(div, context, setDivPosition, {
30242
- onDragEnd: onDragEnd,
30243
- }, context.zoomScale, getOnMouseOut);
30244
- return { div: div, featureHandler: featureHandler, node: table };
31519
+ var featureHandler = new TableMoverFeature(div, context, function () { }, disableMovement
31520
+ ? { onDragEnd: onDragEnd }
31521
+ : {
31522
+ onDragStart: onDragStart,
31523
+ onDragging: onDragging,
31524
+ onDragEnd: onDragEnd,
31525
+ }, context.zoomScale, onTableEditorCreated, editor.getEnvironment().isMobileOrTablet);
31526
+ return { node: table, div: div, featureHandler: featureHandler };
30245
31527
  }
30246
31528
  exports.createTableMover = createTableMover;
30247
31529
  var TableMoverFeature = /** @class */ (function (_super) {
30248
31530
  (0, tslib_1.__extends)(TableMoverFeature, _super);
30249
- function TableMoverFeature(div, context, onSubmit, handler, zoomScale, getOnMouseOut, forceMobile, container) {
31531
+ function TableMoverFeature(div, context, onSubmit, handler, zoomScale, onTableEditorCreated, forceMobile) {
30250
31532
  var _this = _super.call(this, div, context, onSubmit, handler, zoomScale, forceMobile) || this;
30251
- _this.div = div;
30252
- _this.onMouseOut = getOnMouseOut(div);
30253
- div.addEventListener('mouseout', _this.onMouseOut);
31533
+ _this.disposer = onTableEditorCreated === null || onTableEditorCreated === void 0 ? void 0 : onTableEditorCreated('TableMover', div);
30254
31534
  return _this;
30255
31535
  }
30256
31536
  TableMoverFeature.prototype.dispose = function () {
31537
+ var _a;
31538
+ (_a = this.disposer) === null || _a === void 0 ? void 0 : _a.call(this);
31539
+ this.disposer = undefined;
30257
31540
  _super.prototype.dispose.call(this);
30258
- if (this.onMouseOut) {
30259
- this.div.removeEventListener('mouseout', this.onMouseOut);
30260
- }
30261
- this.onMouseOut = null;
30262
31541
  };
30263
31542
  return TableMoverFeature;
30264
31543
  }(DragAndDropHelper_1.DragAndDropHelper));
@@ -30277,6 +31556,188 @@ function isTableTopVisible(editor, rect, contentDiv) {
30277
31556
  }
30278
31557
  return true;
30279
31558
  }
31559
+ function setTableMoverCursor(editor, state, type) {
31560
+ var _a;
31561
+ editor === null || editor === void 0 ? void 0 : editor.setEditorStyle(TABLE_MOVER_STYLE_KEY, state ? (_a = 'cursor: ' + type) !== null && _a !== void 0 ? _a : 'move' : null);
31562
+ }
31563
+ // Get insertion point from coordinate.
31564
+ function getNodePositionFromEvent(editor, x, y) {
31565
+ var doc = editor.getDocument();
31566
+ var domHelper = editor.getDOMHelper();
31567
+ if (doc.caretRangeFromPoint) {
31568
+ // Chrome, Edge, Safari, Opera
31569
+ var range = doc.caretRangeFromPoint(x, y);
31570
+ if (range && domHelper.isNodeInEditor(range.startContainer)) {
31571
+ return { node: range.startContainer, offset: range.startOffset };
31572
+ }
31573
+ }
31574
+ if ('caretPositionFromPoint' in doc) {
31575
+ // Firefox
31576
+ var pos = doc.caretPositionFromPoint(x, y);
31577
+ if (pos && domHelper.isNodeInEditor(pos.offsetNode)) {
31578
+ return { node: pos.offsetNode, offset: pos.offset };
31579
+ }
31580
+ }
31581
+ if (doc.elementFromPoint) {
31582
+ // Fallback
31583
+ var element = doc.elementFromPoint(x, y);
31584
+ if (element && domHelper.isNodeInEditor(element)) {
31585
+ return { node: element, offset: 0 };
31586
+ }
31587
+ }
31588
+ return null;
31589
+ }
31590
+ /**
31591
+ * @internal
31592
+ * Exported for testing
31593
+ */
31594
+ function onDragStart(context) {
31595
+ var _a;
31596
+ context.onStart();
31597
+ var editor = context.editor, table = context.table, div = context.div;
31598
+ setTableMoverCursor(editor, true, 'move');
31599
+ // Create table outline rectangle
31600
+ var trect = table.getBoundingClientRect();
31601
+ var createElementData = {
31602
+ tag: 'div',
31603
+ style: 'position: fixed; user-select: none; border: 1px solid #808080',
31604
+ };
31605
+ var tableRect = (0, createElement_1.createElement)(createElementData, document);
31606
+ tableRect.style.width = trect.width + "px";
31607
+ tableRect.style.height = trect.height + "px";
31608
+ tableRect.style.top = trect.top + "px";
31609
+ tableRect.style.left = trect.left + "px";
31610
+ (_a = div.parentNode) === null || _a === void 0 ? void 0 : _a.appendChild(tableRect);
31611
+ // Get current selection
31612
+ var initialSelection = editor.getDOMSelection();
31613
+ // Select first cell of the table
31614
+ editor.setDOMSelection({
31615
+ type: 'table',
31616
+ firstColumn: 0,
31617
+ firstRow: 0,
31618
+ lastColumn: 0,
31619
+ lastRow: 0,
31620
+ table: table,
31621
+ });
31622
+ // Get the table content model
31623
+ var _b = (0, tslib_1.__read)((0, roosterjs_content_model_dom_1.getFirstSelectedTable)(editor.getContentModelCopy('disconnected')), 1), cmTable = _b[0];
31624
+ // Restore selection
31625
+ editor.setDOMSelection(initialSelection);
31626
+ return {
31627
+ cmTable: cmTable,
31628
+ initialSelection: initialSelection,
31629
+ tableRect: tableRect,
31630
+ };
31631
+ }
31632
+ exports.onDragStart = onDragStart;
31633
+ /**
31634
+ * @internal
31635
+ * Exported for testing
31636
+ */
31637
+ function onDragging(context, event, initValue) {
31638
+ var tableRect = initValue.tableRect;
31639
+ var editor = context.editor;
31640
+ // Move table outline rectangle
31641
+ tableRect.style.top = event.clientY + TABLE_MOVER_LENGTH + "px";
31642
+ tableRect.style.left = event.clientX + TABLE_MOVER_LENGTH + "px";
31643
+ var pos = getNodePositionFromEvent(editor, event.clientX, event.clientY);
31644
+ if (pos) {
31645
+ var range = editor.getDocument().createRange();
31646
+ range.setStart(pos.node, pos.offset);
31647
+ range.collapse(true);
31648
+ editor.setDOMSelection({ type: 'range', range: range, isReverted: false });
31649
+ return true;
31650
+ }
31651
+ return false;
31652
+ }
31653
+ exports.onDragging = onDragging;
31654
+ /**
31655
+ * @internal
31656
+ * Exported for testing
31657
+ */
31658
+ function onDragEnd(context, event, initValue) {
31659
+ var _a, _b;
31660
+ var editor = context.editor, table = context.table, selectWholeTable = context.onFinishDragging, disableMovement = context.disableMovement;
31661
+ var element = event.target;
31662
+ // Remove table outline rectangle
31663
+ initValue === null || initValue === void 0 ? void 0 : initValue.tableRect.remove();
31664
+ // Reset cursor
31665
+ setTableMoverCursor(editor, false);
31666
+ if (element == context.div) {
31667
+ // Table mover was only clicked, select whole table
31668
+ selectWholeTable(table);
31669
+ context.onEnd();
31670
+ return true;
31671
+ }
31672
+ else {
31673
+ // Check if table was dragged on itself, element is not in editor, or movement is disabled
31674
+ if (table.contains(element) ||
31675
+ !editor.getDOMHelper().isNodeInEditor(element) ||
31676
+ disableMovement) {
31677
+ editor.setDOMSelection((_a = initValue === null || initValue === void 0 ? void 0 : initValue.initialSelection) !== null && _a !== void 0 ? _a : null);
31678
+ context.onEnd();
31679
+ return false;
31680
+ }
31681
+ var insertionSuccess_1 = false;
31682
+ // Get position to insert table
31683
+ var insertPosition = getNodePositionFromEvent(editor, event.clientX, event.clientY);
31684
+ if (insertPosition) {
31685
+ // Move table to new position
31686
+ (0, roosterjs_content_model_api_1.formatInsertPointWithContentModel)(editor, insertPosition, function (model, context, ip) {
31687
+ var _a;
31688
+ // Remove old table
31689
+ var _b = (0, tslib_1.__read)((0, roosterjs_content_model_dom_1.getFirstSelectedTable)(model), 2), oldTable = _b[0], path = _b[1];
31690
+ if (oldTable) {
31691
+ var index = path[0].blocks.indexOf(oldTable);
31692
+ path[0].blocks.splice(index, 1);
31693
+ }
31694
+ if (ip && (initValue === null || initValue === void 0 ? void 0 : initValue.cmTable)) {
31695
+ // Insert new table
31696
+ var doc = (0, roosterjs_content_model_dom_1.createContentModelDocument)();
31697
+ doc.blocks.push(initValue.cmTable);
31698
+ insertionSuccess_1 = !!(0, roosterjs_content_model_dom_1.mergeModel)(model, doc, context, {
31699
+ mergeFormat: 'none',
31700
+ insertPosition: ip,
31701
+ });
31702
+ if (insertionSuccess_1) {
31703
+ // After mergeModel, the new table should be selected
31704
+ var finalTable = (_a = (0, roosterjs_content_model_dom_1.getFirstSelectedTable)(model)[0]) !== null && _a !== void 0 ? _a : initValue.cmTable;
31705
+ if (finalTable) {
31706
+ // Add selection marker to the first cell of the table
31707
+ var FirstCell = finalTable.rows[0].cells[0];
31708
+ var markerParagraph = FirstCell === null || FirstCell === void 0 ? void 0 : FirstCell.blocks[0];
31709
+ if ((markerParagraph === null || markerParagraph === void 0 ? void 0 : markerParagraph.blockType) == 'Paragraph') {
31710
+ var marker = (0, roosterjs_content_model_dom_1.createSelectionMarker)(model.format);
31711
+ markerParagraph.segments.unshift(marker);
31712
+ (0, roosterjs_content_model_dom_1.setParagraphNotImplicit)(markerParagraph);
31713
+ (0, roosterjs_content_model_dom_1.setSelection)(FirstCell, marker);
31714
+ }
31715
+ }
31716
+ }
31717
+ return insertionSuccess_1;
31718
+ }
31719
+ }, {
31720
+ // Select first cell of the old table
31721
+ selectionOverride: {
31722
+ type: 'table',
31723
+ firstColumn: 0,
31724
+ firstRow: 0,
31725
+ lastColumn: 0,
31726
+ lastRow: 0,
31727
+ table: table,
31728
+ },
31729
+ apiName: 'TableMover',
31730
+ });
31731
+ }
31732
+ else {
31733
+ // No movement, restore initial selection
31734
+ editor.setDOMSelection((_b = initValue === null || initValue === void 0 ? void 0 : initValue.initialSelection) !== null && _b !== void 0 ? _b : null);
31735
+ }
31736
+ context.onEnd();
31737
+ return insertionSuccess_1;
31738
+ }
31739
+ }
31740
+ exports.onDragEnd = onDragEnd;
30280
31741
 
30281
31742
 
30282
31743
  /***/ }),
@@ -30290,16 +31751,20 @@ function isTableTopVisible(editor, rect, contentDiv) {
30290
31751
  "use strict";
30291
31752
 
30292
31753
  Object.defineProperty(exports, "__esModule", ({ value: true }));
30293
- exports.createTableResizer = void 0;
31754
+ exports.createTableResizer = exports.TABLE_RESIZER_ID = void 0;
31755
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
30294
31756
  var createElement_1 = __webpack_require__(/*! ../../../pluginUtils/CreateElement/createElement */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/CreateElement/createElement.ts");
30295
31757
  var DragAndDropHelper_1 = __webpack_require__(/*! ../../../pluginUtils/DragAndDrop/DragAndDropHelper */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/DragAndDrop/DragAndDropHelper.ts");
30296
31758
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
30297
31759
  var TABLE_RESIZER_LENGTH = 12;
30298
- var TABLE_RESIZER_ID = '_Table_Resizer';
30299
31760
  /**
30300
31761
  * @internal
30301
31762
  */
30302
- function createTableResizer(table, editor, isRTL, onStart, onEnd, contentDiv, anchorContainer) {
31763
+ exports.TABLE_RESIZER_ID = '_Table_Resizer';
31764
+ /**
31765
+ * @internal
31766
+ */
31767
+ function createTableResizer(table, editor, isRTL, onStart, onEnd, contentDiv, anchorContainer, onTableEditorCreated) {
30303
31768
  var rect = (0, roosterjs_content_model_dom_1.normalizeRect)(table.getBoundingClientRect());
30304
31769
  if (!isTableBottomVisible(editor, rect, contentDiv)) {
30305
31770
  return null;
@@ -30311,7 +31776,7 @@ function createTableResizer(table, editor, isRTL, onStart, onEnd, contentDiv, an
30311
31776
  style: "position: fixed; cursor: " + (isRTL ? 'ne' : 'nw') + "-resize; user-select: none; border: 1px solid #808080",
30312
31777
  };
30313
31778
  var div = (0, createElement_1.createElement)(createElementData, document);
30314
- div.id = TABLE_RESIZER_ID;
31779
+ div.id = exports.TABLE_RESIZER_ID;
30315
31780
  div.style.width = TABLE_RESIZER_LENGTH + "px";
30316
31781
  div.style.height = TABLE_RESIZER_LENGTH + "px";
30317
31782
  (anchorContainer || document.body).appendChild(div);
@@ -30326,15 +31791,30 @@ function createTableResizer(table, editor, isRTL, onStart, onEnd, contentDiv, an
30326
31791
  contentDiv: contentDiv,
30327
31792
  };
30328
31793
  setDivPosition(context, div);
30329
- var featureHandler = new DragAndDropHelper_1.DragAndDropHelper(div, context, hideResizer, // Resizer is hidden while dragging only
31794
+ var featureHandler = new TableResizer(div, context, hideResizer, // Resizer is hidden while dragging only
30330
31795
  {
30331
31796
  onDragStart: onDragStart,
30332
31797
  onDragging: onDragging,
30333
31798
  onDragEnd: onDragEnd,
30334
- }, zoomScale, editor.getEnvironment().isMobileOrTablet);
31799
+ }, zoomScale, editor.getEnvironment().isMobileOrTablet, onTableEditorCreated);
30335
31800
  return { node: table, div: div, featureHandler: featureHandler };
30336
31801
  }
30337
31802
  exports.createTableResizer = createTableResizer;
31803
+ var TableResizer = /** @class */ (function (_super) {
31804
+ (0, tslib_1.__extends)(TableResizer, _super);
31805
+ function TableResizer(trigger, context, onSubmit, handler, zoomScale, forceMobile, onTableEditorCreated) {
31806
+ var _this = _super.call(this, trigger, context, onSubmit, handler, zoomScale, forceMobile) || this;
31807
+ _this.disposer = onTableEditorCreated === null || onTableEditorCreated === void 0 ? void 0 : onTableEditorCreated('TableResizer', trigger);
31808
+ return _this;
31809
+ }
31810
+ TableResizer.prototype.dispose = function () {
31811
+ var _a;
31812
+ (_a = this.disposer) === null || _a === void 0 ? void 0 : _a.call(this);
31813
+ this.disposer = undefined;
31814
+ _super.prototype.dispose.call(this);
31815
+ };
31816
+ return TableResizer;
31817
+ }(DragAndDropHelper_1.DragAndDropHelper));
30338
31818
  function onDragStart(context, event) {
30339
31819
  context.onStart();
30340
31820
  var editor = context.editor, table = context.table;
@@ -30520,7 +32000,8 @@ var WatermarkPlugin = /** @class */ (function () {
30520
32000
  if (!editor) {
30521
32001
  return;
30522
32002
  }
30523
- if (event.eventType == 'input' && event.rawEvent.inputType == 'insertText') {
32003
+ if ((event.eventType == 'input' && event.rawEvent.inputType == 'insertText') ||
32004
+ event.eventType == 'compositionEnd') {
30524
32005
  // When input text, editor must not be empty, so we can do hide watermark now without checking content model
30525
32006
  this.showHide(editor, false /*isEmpty*/);
30526
32007
  }
@@ -30601,6 +32082,10 @@ function isModelEmptyFast(model) {
30601
32082
  })) {
30602
32083
  return false; // Has meaningful segments, it is not empty
30603
32084
  }
32085
+ else if ((firstBlock.format.marginRight && parseFloat(firstBlock.format.marginRight) > 0) ||
32086
+ (firstBlock.format.marginLeft && parseFloat(firstBlock.format.marginLeft) > 0)) {
32087
+ return false; // Has margin (indentation is changed), it is not empty
32088
+ }
30604
32089
  else {
30605
32090
  return firstBlock.segments.filter(function (x) { return x.segmentType == 'Br'; }).length <= 1; // If there are more than one BR, it is not empty, otherwise it is empty
30606
32091
  }