roosterjs 9.0.0 → 9.1.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.
@@ -2093,8 +2093,8 @@ exports["default"] = getDarkColor;
2093
2093
  "use strict";
2094
2094
 
2095
2095
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2096
- exports.setModelListStyle = exports.setListType = exports.formatSegmentWithContentModel = exports.formatParagraphWithContentModel = exports.formatImageWithContentModel = exports.formatTableWithContentModel = exports.insertTableColumn = exports.insertTableRow = exports.insertEntity = exports.toggleCode = exports.setParagraphMargin = exports.adjustImageSelection = exports.setImageAltText = exports.adjustLinkSelection = exports.removeLink = exports.insertLink = exports.clearFormat = exports.getFormatState = exports.changeImage = exports.setImageBoxShadow = exports.setImageBorder = exports.setSpacing = exports.toggleBlockQuote = exports.setHeadingLevel = exports.setDirection = exports.setAlignment = exports.setIndentation = exports.setListStartNumber = exports.setListStyle = exports.insertImage = exports.changeCapitalization = exports.applySegmentFormat = exports.changeFontSize = exports.setTextColor = exports.setFontSize = exports.setFontName = exports.setBackgroundColor = exports.toggleSuperscript = exports.toggleSubscript = exports.toggleStrikethrough = exports.toggleUnderline = exports.toggleItalic = exports.toggleBold = exports.toggleNumbering = exports.toggleBullet = exports.applyTableBorderFormat = exports.editTable = exports.setTableCellShade = exports.formatTable = exports.insertTable = void 0;
2097
- exports.matchLink = exports.setModelIndentation = exports.findListItemsInSameThread = exports.setModelListStartNumber = void 0;
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;
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");
@@ -2183,6 +2183,8 @@ var insertTableRow_1 = __webpack_require__(/*! ./modelApi/table/insertTableRow *
2183
2183
  Object.defineProperty(exports, "insertTableRow", ({ enumerable: true, get: function () { return insertTableRow_1.insertTableRow; } }));
2184
2184
  var insertTableColumn_1 = __webpack_require__(/*! ./modelApi/table/insertTableColumn */ "./packages/roosterjs-content-model-api/lib/modelApi/table/insertTableColumn.ts");
2185
2185
  Object.defineProperty(exports, "insertTableColumn", ({ enumerable: true, get: function () { return insertTableColumn_1.insertTableColumn; } }));
2186
+ var clearSelectedCells_1 = __webpack_require__(/*! ./modelApi/table/clearSelectedCells */ "./packages/roosterjs-content-model-api/lib/modelApi/table/clearSelectedCells.ts");
2187
+ Object.defineProperty(exports, "clearSelectedCells", ({ enumerable: true, get: function () { return clearSelectedCells_1.clearSelectedCells; } }));
2186
2188
  var formatTableWithContentModel_1 = __webpack_require__(/*! ./publicApi/utils/formatTableWithContentModel */ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatTableWithContentModel.ts");
2187
2189
  Object.defineProperty(exports, "formatTableWithContentModel", ({ enumerable: true, get: function () { return formatTableWithContentModel_1.formatTableWithContentModel; } }));
2188
2190
  var formatImageWithContentModel_1 = __webpack_require__(/*! ./publicApi/utils/formatImageWithContentModel */ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatImageWithContentModel.ts");
@@ -2191,6 +2193,8 @@ var formatParagraphWithContentModel_1 = __webpack_require__(/*! ./publicApi/util
2191
2193
  Object.defineProperty(exports, "formatParagraphWithContentModel", ({ enumerable: true, get: function () { return formatParagraphWithContentModel_1.formatParagraphWithContentModel; } }));
2192
2194
  var formatSegmentWithContentModel_1 = __webpack_require__(/*! ./publicApi/utils/formatSegmentWithContentModel */ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatSegmentWithContentModel.ts");
2193
2195
  Object.defineProperty(exports, "formatSegmentWithContentModel", ({ enumerable: true, get: function () { return formatSegmentWithContentModel_1.formatSegmentWithContentModel; } }));
2196
+ var formatTextSegmentBeforeSelectionMarker_1 = __webpack_require__(/*! ./publicApi/utils/formatTextSegmentBeforeSelectionMarker */ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatTextSegmentBeforeSelectionMarker.ts");
2197
+ Object.defineProperty(exports, "formatTextSegmentBeforeSelectionMarker", ({ enumerable: true, get: function () { return formatTextSegmentBeforeSelectionMarker_1.formatTextSegmentBeforeSelectionMarker; } }));
2194
2198
  var setListType_1 = __webpack_require__(/*! ./modelApi/list/setListType */ "./packages/roosterjs-content-model-api/lib/modelApi/list/setListType.ts");
2195
2199
  Object.defineProperty(exports, "setListType", ({ enumerable: true, get: function () { return setListType_1.setListType; } }));
2196
2200
  var setModelListStyle_1 = __webpack_require__(/*! ./modelApi/list/setModelListStyle */ "./packages/roosterjs-content-model-api/lib/modelApi/list/setModelListStyle.ts");
@@ -3881,7 +3885,6 @@ exports.clearSelectedCells = void 0;
3881
3885
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
3882
3886
  /**
3883
3887
  * Clear selection of a table.
3884
- * @internal
3885
3888
  * @param table The table model where the selection is to be cleared
3886
3889
  * @param sel The selection coordinates to be cleared
3887
3890
  */
@@ -6821,6 +6824,44 @@ function formatTableWithContentModel(editor, apiName, callback, selectionOverrid
6821
6824
  exports.formatTableWithContentModel = formatTableWithContentModel;
6822
6825
 
6823
6826
 
6827
+ /***/ }),
6828
+
6829
+ /***/ "./packages/roosterjs-content-model-api/lib/publicApi/utils/formatTextSegmentBeforeSelectionMarker.ts":
6830
+ /*!************************************************************************************************************!*\
6831
+ !*** ./packages/roosterjs-content-model-api/lib/publicApi/utils/formatTextSegmentBeforeSelectionMarker.ts ***!
6832
+ \************************************************************************************************************/
6833
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
6834
+
6835
+ "use strict";
6836
+
6837
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
6838
+ exports.formatTextSegmentBeforeSelectionMarker = void 0;
6839
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
6840
+ /**
6841
+ * Invoke a callback to format the text segment before the selection marker using Content Model
6842
+ * @param editor The editor object
6843
+ * @param callback The callback to format the text segment.
6844
+ */
6845
+ function formatTextSegmentBeforeSelectionMarker(editor, callback) {
6846
+ editor.formatContentModel(function (model, context) {
6847
+ var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /*includeFormatHolder*/);
6848
+ if (selectedSegmentsAndParagraphs.length > 0 && selectedSegmentsAndParagraphs[0][1]) {
6849
+ var marker = selectedSegmentsAndParagraphs[0][0];
6850
+ var paragraph = selectedSegmentsAndParagraphs[0][1];
6851
+ var markerIndex = paragraph.segments.indexOf(marker);
6852
+ if (marker.segmentType === 'SelectionMarker' && markerIndex > 0) {
6853
+ var previousSegment = paragraph.segments[markerIndex - 1];
6854
+ if (previousSegment && previousSegment.segmentType === 'Text') {
6855
+ return callback(model, previousSegment, paragraph, marker.format, context);
6856
+ }
6857
+ }
6858
+ }
6859
+ return false;
6860
+ });
6861
+ }
6862
+ exports.formatTextSegmentBeforeSelectionMarker = formatTextSegmentBeforeSelectionMarker;
6863
+
6864
+
6824
6865
  /***/ }),
6825
6866
 
6826
6867
  /***/ "./packages/roosterjs-content-model-core/lib/command/createModelFromHtml/convertInlineCss.ts":
@@ -8945,6 +8986,14 @@ function addRangeToSelection(doc, range, isReverted) {
8945
8986
  if (isReverted === void 0) { isReverted = false; }
8946
8987
  var selection = (_a = doc.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
8947
8988
  if (selection) {
8989
+ var currentRange = selection.rangeCount > 0 && selection.getRangeAt(0);
8990
+ if (currentRange &&
8991
+ currentRange.startContainer == range.startContainer &&
8992
+ currentRange.endContainer == range.endContainer &&
8993
+ currentRange.startOffset == range.startOffset &&
8994
+ currentRange.endOffset == range.endOffset) {
8995
+ return;
8996
+ }
8948
8997
  selection.removeAllRanges();
8949
8998
  if (!isReverted) {
8950
8999
  selection.addRange(range);
@@ -9065,11 +9114,14 @@ var findTableCellElement_1 = __webpack_require__(/*! ./findTableCellElement */ "
9065
9114
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
9066
9115
  var DOM_SELECTION_CSS_KEY = '_DOMSelection';
9067
9116
  var HIDE_CURSOR_CSS_KEY = '_DOMSelectionHideCursor';
9117
+ var HIDE_SELECTION_CSS_KEY = '_DOMSelectionHideSelection';
9068
9118
  var IMAGE_ID = 'image';
9069
9119
  var TABLE_ID = 'table';
9070
9120
  var DEFAULT_SELECTION_BORDER_COLOR = '#DB626C';
9071
9121
  var TABLE_CSS_RULE = 'background-color:#C6C6C6!important;';
9072
9122
  var CARET_CSS_RULE = 'caret-color: transparent';
9123
+ var TRANSPARENT_SELECTION_CSS_RULE = 'background-color: transparent !important';
9124
+ var SELECTION_SELECTOR = '*::selection';
9073
9125
  /**
9074
9126
  * @internal
9075
9127
  */
@@ -9082,14 +9134,15 @@ var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
9082
9134
  core.selection.skipReselectOnFocus = true;
9083
9135
  core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, null /*cssRule*/);
9084
9136
  core.api.setEditorStyle(core, HIDE_CURSOR_CSS_KEY, null /*cssRule*/);
9137
+ core.api.setEditorStyle(core, HIDE_SELECTION_CSS_KEY, null /*cssRule*/);
9085
9138
  try {
9086
9139
  switch (selection === null || selection === void 0 ? void 0 : selection.type) {
9087
9140
  case 'image':
9088
9141
  var image = selection.image;
9089
9142
  core.selection.selection = selection;
9090
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)]);
9091
- core.api.setEditorStyle(core, HIDE_CURSOR_CSS_KEY, CARET_CSS_RULE);
9092
- setRangeSelection(doc, image);
9144
+ core.api.setEditorStyle(core, HIDE_SELECTION_CSS_KEY, TRANSPARENT_SELECTION_CSS_RULE, [SELECTION_SELECTOR]);
9145
+ setRangeSelection(doc, image, false /* collapse */);
9093
9146
  break;
9094
9147
  case 'table':
9095
9148
  var table = selection.table, firstColumn = selection.firstColumn, firstRow = selection.firstRow, lastColumn = selection.lastColumn, lastRow = selection.lastRow;
@@ -9131,7 +9184,7 @@ var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
9131
9184
  core.api.setEditorStyle(core, HIDE_CURSOR_CSS_KEY, CARET_CSS_RULE);
9132
9185
  var nodeToSelect = ((_c = firstCell.cell) === null || _c === void 0 ? void 0 : _c.firstElementChild) || firstCell.cell;
9133
9186
  if (nodeToSelect) {
9134
- setRangeSelection(doc, nodeToSelect || undefined);
9187
+ setRangeSelection(doc, nodeToSelect || undefined, true /* collapse */);
9135
9188
  }
9136
9189
  break;
9137
9190
  case 'range':
@@ -9197,12 +9250,25 @@ function handleTableSelected(parsedTable, tableId, table, firstCell, lastCell) {
9197
9250
  });
9198
9251
  return selectors;
9199
9252
  }
9200
- function setRangeSelection(doc, element) {
9253
+ function setRangeSelection(doc, element, collapse) {
9254
+ var _a;
9201
9255
  if (element && doc.contains(element)) {
9202
9256
  var range = doc.createRange();
9257
+ var isReverted = undefined;
9203
9258
  range.selectNode(element);
9204
- range.collapse();
9205
- (0, addRangeToSelection_1.addRangeToSelection)(doc, range);
9259
+ if (collapse) {
9260
+ range.collapse();
9261
+ }
9262
+ else {
9263
+ var selection = (_a = doc.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
9264
+ var range_1 = selection && selection.rangeCount > 0 && selection.getRangeAt(0);
9265
+ if (selection && range_1) {
9266
+ isReverted =
9267
+ selection.focusNode != range_1.endContainer ||
9268
+ selection.focusOffset != range_1.endOffset;
9269
+ }
9270
+ }
9271
+ (0, addRangeToSelection_1.addRangeToSelection)(doc, range, isReverted);
9206
9272
  }
9207
9273
  }
9208
9274
 
@@ -11696,6 +11762,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
11696
11762
  exports.createSelectionPlugin = void 0;
11697
11763
  var findCoordinate_1 = __webpack_require__(/*! ./findCoordinate */ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/findCoordinate.ts");
11698
11764
  var findTableCellElement_1 = __webpack_require__(/*! ../../coreApi/setDOMSelection/findTableCellElement */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/findTableCellElement.ts");
11765
+ var isSingleImageInSelection_1 = __webpack_require__(/*! ./isSingleImageInSelection */ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/isSingleImageInSelection.ts");
11699
11766
  var normalizePos_1 = __webpack_require__(/*! ./normalizePos */ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/normalizePos.ts");
11700
11767
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
11701
11768
  var MouseLeftButton = 0;
@@ -11705,6 +11772,7 @@ var Up = 'ArrowUp';
11705
11772
  var Down = 'ArrowDown';
11706
11773
  var Left = 'ArrowLeft';
11707
11774
  var Right = 'ArrowRight';
11775
+ var Tab = 'Tab';
11708
11776
  var SelectionPlugin = /** @class */ (function () {
11709
11777
  function SelectionPlugin(options) {
11710
11778
  var _this = this;
@@ -11712,6 +11780,7 @@ var SelectionPlugin = /** @class */ (function () {
11712
11780
  this.disposer = null;
11713
11781
  this.isSafari = false;
11714
11782
  this.isMac = false;
11783
+ this.scrollTopCache = 0;
11715
11784
  this.onMouseMove = function (event) {
11716
11785
  var _a, _b, _c;
11717
11786
  if (_this.editor && _this.state.tableSelection) {
@@ -11782,20 +11851,45 @@ var SelectionPlugin = /** @class */ (function () {
11782
11851
  // Editor is focused, now we can get live selection. So no need to keep a selection if the selection type is range.
11783
11852
  _this.state.selection = null;
11784
11853
  }
11854
+ if (_this.scrollTopCache && _this.editor) {
11855
+ var sc = _this.editor.getScrollContainer();
11856
+ sc.scrollTop = _this.scrollTopCache;
11857
+ _this.scrollTopCache = 0;
11858
+ }
11785
11859
  };
11786
11860
  this.onBlur = function () {
11787
- if (!_this.state.selection && _this.editor) {
11788
- _this.state.selection = _this.editor.getDOMSelection();
11861
+ if (_this.editor) {
11862
+ if (!_this.state.selection) {
11863
+ _this.state.selection = _this.editor.getDOMSelection();
11864
+ }
11865
+ var sc = _this.editor.getScrollContainer();
11866
+ _this.scrollTopCache = sc.scrollTop;
11789
11867
  }
11790
11868
  };
11791
- this.onSelectionChangeSafari = function () {
11869
+ this.onSelectionChange = function () {
11792
11870
  var _a;
11793
11871
  if (((_a = _this.editor) === null || _a === void 0 ? void 0 : _a.hasFocus()) && !_this.editor.isInShadowEdit()) {
11872
+ var newSelection = _this.editor.getDOMSelection();
11873
+ //If am image selection changed to a wider range due a keyboard event, we should update the selection
11874
+ var selection = _this.editor.getDocument().getSelection();
11875
+ if ((newSelection === null || newSelection === void 0 ? void 0 : newSelection.type) == 'image' && selection) {
11876
+ if (selection && !(0, isSingleImageInSelection_1.isSingleImageInSelection)(selection)) {
11877
+ var range = selection.getRangeAt(0);
11878
+ _this.editor.setDOMSelection({
11879
+ type: 'range',
11880
+ range: range,
11881
+ isReverted: selection.focusNode != range.endContainer ||
11882
+ selection.focusOffset != range.endOffset,
11883
+ });
11884
+ }
11885
+ }
11794
11886
  // Safari has problem to handle onBlur event. When blur, we cannot get the original selection from editor.
11795
11887
  // So we always save a selection whenever editor has focus. Then after blur, we can still use this cached selection.
11796
- var newSelection = _this.editor.getDOMSelection();
11797
11888
  if ((newSelection === null || newSelection === void 0 ? void 0 : newSelection.type) == 'range') {
11798
- _this.state.selection = newSelection;
11889
+ if (_this.isSafari) {
11890
+ _this.state.selection = newSelection;
11891
+ }
11892
+ _this.trySelectSingleImage(newSelection);
11799
11893
  }
11800
11894
  }
11801
11895
  };
@@ -11814,8 +11908,8 @@ var SelectionPlugin = /** @class */ (function () {
11814
11908
  var document = this.editor.getDocument();
11815
11909
  this.isSafari = !!env.isSafari;
11816
11910
  this.isMac = !!env.isMac;
11911
+ document.addEventListener('selectionchange', this.onSelectionChange);
11817
11912
  if (this.isSafari) {
11818
- document.addEventListener('selectionchange', this.onSelectionChangeSafari);
11819
11913
  this.disposer = this.editor.attachDomEvent({
11820
11914
  focus: { beforeDispatch: this.onFocus },
11821
11915
  drop: { beforeDispatch: this.onDrop },
@@ -11831,7 +11925,7 @@ var SelectionPlugin = /** @class */ (function () {
11831
11925
  };
11832
11926
  SelectionPlugin.prototype.dispose = function () {
11833
11927
  var _a;
11834
- (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDocument().removeEventListener('selectionchange', this.onSelectionChangeSafari);
11928
+ (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDocument().removeEventListener('selectionchange', this.onSelectionChange);
11835
11929
  if (this.disposer) {
11836
11930
  this.disposer();
11837
11931
  this.disposer = null;
@@ -11859,6 +11953,11 @@ var SelectionPlugin = /** @class */ (function () {
11859
11953
  case 'contentChanged':
11860
11954
  this.state.tableSelection = null;
11861
11955
  break;
11956
+ case 'scroll':
11957
+ if (!this.editor.hasFocus()) {
11958
+ this.scrollTopCache = event.scrollContainer.scrollTop;
11959
+ }
11960
+ break;
11862
11961
  }
11863
11962
  };
11864
11963
  SelectionPlugin.prototype.onMouseDown = function (editor, rawEvent) {
@@ -11870,11 +11969,11 @@ var SelectionPlugin = /** @class */ (function () {
11870
11969
  (image =
11871
11970
  (_a = this.getClickingImage(rawEvent)) !== null && _a !== void 0 ? _a : this.getContainedTargetImage(rawEvent, selection)) &&
11872
11971
  image.isContentEditable) {
11873
- this.selectImage(image);
11972
+ this.selectImageWithRange(image, rawEvent);
11874
11973
  return;
11875
11974
  }
11876
11975
  else if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'image' && selection.image !== rawEvent.target) {
11877
- this.selectBeforeImage(editor, selection.image);
11976
+ this.selectBeforeOrAfterElement(editor, selection.image);
11878
11977
  return;
11879
11978
  }
11880
11979
  // Table selection
@@ -11903,6 +12002,22 @@ var SelectionPlugin = /** @class */ (function () {
11903
12002
  });
11904
12003
  }
11905
12004
  };
12005
+ SelectionPlugin.prototype.selectImageWithRange = function (image, event) {
12006
+ var _a;
12007
+ var range = image.ownerDocument.createRange();
12008
+ range.selectNode(image);
12009
+ var domSelection = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDOMSelection();
12010
+ if ((domSelection === null || domSelection === void 0 ? void 0 : domSelection.type) == 'image' && image == domSelection.image) {
12011
+ event.preventDefault();
12012
+ }
12013
+ else {
12014
+ this.setDOMSelection({
12015
+ type: 'range',
12016
+ isReverted: false,
12017
+ range: range,
12018
+ }, null);
12019
+ }
12020
+ };
11906
12021
  SelectionPlugin.prototype.onMouseUp = function (event) {
11907
12022
  var image;
11908
12023
  if ((image = this.getClickingImage(event.rawEvent)) &&
@@ -11911,7 +12026,7 @@ var SelectionPlugin = /** @class */ (function () {
11911
12026
  (event.rawEvent.button ==
11912
12027
  MouseRightButton /* it's not possible to drag using right click */ ||
11913
12028
  event.isClicking)) {
11914
- this.selectImage(image);
12029
+ this.selectImageWithRange(image, event.rawEvent);
11915
12030
  }
11916
12031
  this.detachMouseEvent();
11917
12032
  };
@@ -11925,20 +12040,21 @@ var SelectionPlugin = /** @class */ (function () {
11925
12040
  case 'image':
11926
12041
  if (!(0, roosterjs_content_model_dom_1.isModifierKey)(rawEvent) && !rawEvent.shiftKey && selection.image.parentNode) {
11927
12042
  if (key === 'Escape') {
11928
- this.selectBeforeImage(editor, selection.image);
12043
+ this.selectBeforeOrAfterElement(editor, selection.image);
11929
12044
  rawEvent.stopPropagation();
11930
12045
  }
11931
12046
  else if (key !== 'Delete' && key !== 'Backspace') {
11932
- this.selectBeforeImage(editor, selection.image);
12047
+ this.selectBeforeOrAfterElement(editor, selection.image);
11933
12048
  }
11934
12049
  }
11935
12050
  break;
11936
12051
  case 'range':
11937
- if (key == Up || key == Down || key == Left || key == Right) {
12052
+ if (key == Up || key == Down || key == Left || key == Right || key == Tab) {
11938
12053
  var start = selection.range.startContainer;
11939
12054
  this.state.tableSelection = this.parseTableSelection(start, start, editor.getDOMHelper());
12055
+ var rangeKey_1 = key == Tab ? this.getTabKey(rawEvent) : key;
11940
12056
  if (this.state.tableSelection) {
11941
- win === null || win === void 0 ? void 0 : win.requestAnimationFrame(function () { return _this.handleSelectionInTable(key); });
12057
+ win === null || win === void 0 ? void 0 : win.requestAnimationFrame(function () { return _this.handleSelectionInTable(rangeKey_1); });
11942
12058
  }
11943
12059
  }
11944
12060
  break;
@@ -11965,15 +12081,18 @@ var SelectionPlugin = /** @class */ (function () {
11965
12081
  break;
11966
12082
  }
11967
12083
  };
12084
+ SelectionPlugin.prototype.getTabKey = function (rawEvent) {
12085
+ return rawEvent.shiftKey ? 'TabLeft' : 'TabRight';
12086
+ };
11968
12087
  SelectionPlugin.prototype.handleSelectionInTable = function (key) {
11969
- var _a, _b;
12088
+ var _a, _b, _c, _d;
11970
12089
  if (!this.editor || !this.state.tableSelection) {
11971
12090
  return;
11972
12091
  }
11973
12092
  var selection = this.editor.getDOMSelection();
11974
12093
  var domHelper = this.editor.getDOMHelper();
11975
12094
  if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'range') {
11976
- var _c = selection.range, collapsed = _c.collapsed, startContainer = _c.startContainer, endContainer = _c.endContainer, commonAncestorContainer = _c.commonAncestorContainer, isReverted = selection.isReverted;
12095
+ var _e = selection.range, collapsed = _e.collapsed, startContainer = _e.startContainer, endContainer = _e.endContainer, commonAncestorContainer = _e.commonAncestorContainer, isReverted = selection.isReverted;
11977
12096
  var start = isReverted ? endContainer : startContainer;
11978
12097
  var end = isReverted ? startContainer : endContainer;
11979
12098
  var tableSel = this.parseTableSelection(commonAncestorContainer, start, domHelper);
@@ -11981,9 +12100,9 @@ var SelectionPlugin = /** @class */ (function () {
11981
12100
  return;
11982
12101
  }
11983
12102
  var lastCo = (0, findCoordinate_1.findCoordinate)(tableSel === null || tableSel === void 0 ? void 0 : tableSel.parsedTable, end, domHelper);
11984
- var _d = this.state.tableSelection, parsedTable = _d.parsedTable, oldCo = _d.firstCo, table = _d.table;
11985
- if (lastCo && tableSel.table == table && lastCo.col != oldCo.col) {
11986
- if (key == Up || key == Down) {
12103
+ var _f = this.state.tableSelection, parsedTable = _f.parsedTable, oldCo = _f.firstCo, table = _f.table;
12104
+ if (lastCo && tableSel.table == table) {
12105
+ if (lastCo.col != oldCo.col && (key == Up || key == Down)) {
11987
12106
  var change = key == Up ? -1 : 1;
11988
12107
  var originalTd = (_a = (0, findTableCellElement_1.findTableCellElement)(parsedTable, oldCo)) === null || _a === void 0 ? void 0 : _a.cell;
11989
12108
  var td = null;
@@ -11998,15 +12117,29 @@ var SelectionPlugin = /** @class */ (function () {
11998
12117
  }
11999
12118
  }
12000
12119
  if (collapsed && td) {
12001
- var _e = (0, normalizePos_1.normalizePos)(td, key == Up ? td.childNodes.length : 0), node = _e.node, offset = _e.offset;
12002
- var range = this.editor.getDocument().createRange();
12003
- range.setStart(node, offset);
12004
- range.collapse(true /*toStart*/);
12005
- this.setDOMSelection({
12006
- type: 'range',
12007
- range: range,
12008
- isReverted: false,
12009
- }, null /*tableSelection*/);
12120
+ this.setRangeSelectionInTable(td, key == Up ? td.childNodes.length : 0, this.editor);
12121
+ }
12122
+ }
12123
+ else if (key == 'TabLeft' || key == 'TabRight') {
12124
+ var reverse = key == 'TabLeft';
12125
+ for (var step = reverse ? -1 : 1, row = (_c = lastCo.row) !== null && _c !== void 0 ? _c : 0, col = ((_d = lastCo.col) !== null && _d !== void 0 ? _d : 0) + step;; col += step) {
12126
+ if (col < 0 || col >= parsedTable[row].length) {
12127
+ row += step;
12128
+ if (row < 0) {
12129
+ this.selectBeforeOrAfterElement(this.editor, tableSel.table);
12130
+ break;
12131
+ }
12132
+ else if (row >= parsedTable.length) {
12133
+ this.selectBeforeOrAfterElement(this.editor, tableSel.table, true /*after*/);
12134
+ break;
12135
+ }
12136
+ col = reverse ? parsedTable[row].length - 1 : 0;
12137
+ }
12138
+ var cell = parsedTable[row][col];
12139
+ if (typeof cell != 'string') {
12140
+ this.setRangeSelectionInTable(cell, 0, this.editor);
12141
+ break;
12142
+ }
12010
12143
  }
12011
12144
  }
12012
12145
  else {
@@ -12019,6 +12152,18 @@ var SelectionPlugin = /** @class */ (function () {
12019
12152
  }
12020
12153
  }
12021
12154
  };
12155
+ SelectionPlugin.prototype.setRangeSelectionInTable = function (cell, nodeOffset, editor) {
12156
+ // Get deepest editable position in the cell
12157
+ var _a = (0, normalizePos_1.normalizePos)(cell, nodeOffset), node = _a.node, offset = _a.offset;
12158
+ var range = editor.getDocument().createRange();
12159
+ range.setStart(node, offset);
12160
+ range.collapse(true /*toStart*/);
12161
+ this.setDOMSelection({
12162
+ type: 'range',
12163
+ range: range,
12164
+ isReverted: false,
12165
+ }, null /*tableSelection*/);
12166
+ };
12022
12167
  SelectionPlugin.prototype.updateTableSelectionFromKeyboard = function (rowChange, colChange) {
12023
12168
  var _a;
12024
12169
  if (((_a = this.state.tableSelection) === null || _a === void 0 ? void 0 : _a.lastCo) && this.editor) {
@@ -12030,19 +12175,13 @@ var SelectionPlugin = /** @class */ (function () {
12030
12175
  }
12031
12176
  }
12032
12177
  };
12033
- SelectionPlugin.prototype.selectImage = function (image) {
12034
- this.setDOMSelection({
12035
- type: 'image',
12036
- image: image,
12037
- }, null /*tableSelection*/);
12038
- };
12039
- SelectionPlugin.prototype.selectBeforeImage = function (editor, image) {
12178
+ SelectionPlugin.prototype.selectBeforeOrAfterElement = function (editor, element, after) {
12040
12179
  var doc = editor.getDocument();
12041
- var parent = image.parentNode;
12042
- var index = parent && (0, roosterjs_content_model_dom_1.toArray)(parent.childNodes).indexOf(image);
12180
+ var parent = element.parentNode;
12181
+ var index = parent && (0, roosterjs_content_model_dom_1.toArray)(parent.childNodes).indexOf(element);
12043
12182
  if (parent && index !== null && index >= 0) {
12044
12183
  var range = doc.createRange();
12045
- range.setStart(parent, index);
12184
+ range.setStart(parent, index + (after ? 1 : 0));
12046
12185
  range.collapse();
12047
12186
  this.setDOMSelection({
12048
12187
  type: 'range',
@@ -12099,6 +12238,17 @@ var SelectionPlugin = /** @class */ (function () {
12099
12238
  this.state.mouseDisposer = undefined;
12100
12239
  }
12101
12240
  };
12241
+ SelectionPlugin.prototype.trySelectSingleImage = function (selection) {
12242
+ if (!selection.range.collapsed) {
12243
+ var image = (0, isSingleImageInSelection_1.isSingleImageInSelection)(selection.range);
12244
+ if (image) {
12245
+ this.setDOMSelection({
12246
+ type: 'image',
12247
+ image: image,
12248
+ }, null /*tableSelection*/);
12249
+ }
12250
+ }
12251
+ };
12102
12252
  return SelectionPlugin;
12103
12253
  }());
12104
12254
  /**
@@ -12151,6 +12301,58 @@ function findCoordinate(parsedTable, element, domHelper) {
12151
12301
  exports.findCoordinate = findCoordinate;
12152
12302
 
12153
12303
 
12304
+ /***/ }),
12305
+
12306
+ /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/isSingleImageInSelection.ts":
12307
+ /*!****************************************************************************************************!*\
12308
+ !*** ./packages/roosterjs-content-model-core/lib/corePlugin/selection/isSingleImageInSelection.ts ***!
12309
+ \****************************************************************************************************/
12310
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
12311
+
12312
+ "use strict";
12313
+
12314
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
12315
+ exports.isSingleImageInSelection = void 0;
12316
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
12317
+ /**
12318
+ * @internal
12319
+ */
12320
+ function isSingleImageInSelection(selection) {
12321
+ var _a = getProps(selection), startNode = _a.startNode, endNode = _a.endNode, startOffset = _a.startOffset, endOffset = _a.endOffset;
12322
+ var max = Math.max(startOffset, endOffset);
12323
+ var min = Math.min(startOffset, endOffset);
12324
+ if (startNode && endNode && startNode == endNode && max - min == 1) {
12325
+ var node = startNode === null || startNode === void 0 ? void 0 : startNode.childNodes.item(min);
12326
+ if ((0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'ELEMENT_NODE') && (0, roosterjs_content_model_dom_1.isElementOfType)(node, 'img')) {
12327
+ return node;
12328
+ }
12329
+ }
12330
+ return null;
12331
+ }
12332
+ exports.isSingleImageInSelection = isSingleImageInSelection;
12333
+ function getProps(selection) {
12334
+ if (isSelection(selection)) {
12335
+ return {
12336
+ startNode: selection.anchorNode,
12337
+ endNode: selection.focusNode,
12338
+ startOffset: selection.anchorOffset,
12339
+ endOffset: selection.focusOffset,
12340
+ };
12341
+ }
12342
+ else {
12343
+ return {
12344
+ startNode: selection.startContainer,
12345
+ endNode: selection.endContainer,
12346
+ startOffset: selection.startOffset,
12347
+ endOffset: selection.endOffset,
12348
+ };
12349
+ }
12350
+ }
12351
+ function isSelection(selection) {
12352
+ return !!selection.getRangeAt;
12353
+ }
12354
+
12355
+
12154
12356
  /***/ }),
12155
12357
 
12156
12358
  /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/normalizePos.ts":
@@ -12164,6 +12366,30 @@ exports.findCoordinate = findCoordinate;
12164
12366
  Object.defineProperty(exports, "__esModule", ({ value: true }));
12165
12367
  exports.normalizePos = void 0;
12166
12368
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
12369
+ /**
12370
+ * HTML void elements
12371
+ * Per https://www.w3.org/TR/html/syntax.html#syntax-elements, cannot have child nodes
12372
+ * This regex is used when we move focus to very begin of editor. We should avoid putting focus inside
12373
+ * void elements so users don't accidentally create child nodes in them
12374
+ */
12375
+ var HTML_VOID_ELEMENTS = [
12376
+ 'AREA',
12377
+ 'BASE',
12378
+ 'BR',
12379
+ 'COL',
12380
+ 'COMMAND',
12381
+ 'EMBED',
12382
+ 'HR',
12383
+ 'IMG',
12384
+ 'INPUT',
12385
+ 'KEYGEN',
12386
+ 'LINK',
12387
+ 'META',
12388
+ 'PARAM',
12389
+ 'SOURCE',
12390
+ 'TRACK',
12391
+ 'WBR',
12392
+ ];
12167
12393
  /**
12168
12394
  * @internal
12169
12395
  */
@@ -12181,8 +12407,15 @@ function normalizePos(node, offset) {
12181
12407
  : node.childNodes.length;
12182
12408
  }
12183
12409
  else {
12184
- node = node.childNodes[offset];
12185
- offset = 0;
12410
+ var nextNode = node.childNodes[offset];
12411
+ if ((0, roosterjs_content_model_dom_1.isNodeOfType)(nextNode, 'ELEMENT_NODE') &&
12412
+ HTML_VOID_ELEMENTS.indexOf(nextNode.tagName) >= 0) {
12413
+ break;
12414
+ }
12415
+ else {
12416
+ node = node.childNodes[offset];
12417
+ offset = 0;
12418
+ }
12186
12419
  }
12187
12420
  }
12188
12421
  return { node: node, offset: offset };
@@ -13609,6 +13842,7 @@ exports.defaultContentModelFormatMap = void 0;
13609
13842
  exports.defaultContentModelFormatMap = {
13610
13843
  a: {
13611
13844
  underline: true,
13845
+ textColor: undefined, // Set to undefined to force override color from parent element so we can write correct link color if any, because browser will assign a default color for link if it doesn't have one
13612
13846
  },
13613
13847
  blockquote: {
13614
13848
  marginTop: '1em',
@@ -24551,6 +24785,7 @@ exports.stackFormat = stackFormat;
24551
24785
 
24552
24786
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24553
24787
  exports.contentModelToText = void 0;
24788
+ var TextForHR = '________________________________________';
24554
24789
  /**
24555
24790
  * Convert Content Model to plain text
24556
24791
  * @param model The source Content Model
@@ -24588,9 +24823,13 @@ function contentModelToTextArray(group, textArray) {
24588
24823
  break;
24589
24824
  }
24590
24825
  });
24591
- textArray.push(text_1);
24826
+ if (text_1) {
24827
+ textArray.push(text_1);
24828
+ }
24592
24829
  break;
24593
24830
  case 'Divider':
24831
+ textArray.push(block.tagName == 'hr' ? TextForHR : '');
24832
+ break;
24594
24833
  case 'Entity':
24595
24834
  textArray.push('');
24596
24835
  break;
@@ -24623,7 +24862,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
24623
24862
  exports.AutoFormatPlugin = void 0;
24624
24863
  var createLink_1 = __webpack_require__(/*! ./link/createLink */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLink.ts");
24625
24864
  var createLinkAfterSpace_1 = __webpack_require__(/*! ./link/createLinkAfterSpace */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLinkAfterSpace.ts");
24865
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
24626
24866
  var keyboardListTrigger_1 = __webpack_require__(/*! ./list/keyboardListTrigger */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/list/keyboardListTrigger.ts");
24867
+ var transformHyphen_1 = __webpack_require__(/*! ./hyphen/transformHyphen */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/hyphen/transformHyphen.ts");
24627
24868
  var unlink_1 = __webpack_require__(/*! ./link/unlink */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/unlink.ts");
24628
24869
  /**
24629
24870
  * @internal
@@ -24633,6 +24874,7 @@ var DefaultOptions = {
24633
24874
  autoNumbering: false,
24634
24875
  autoUnlink: false,
24635
24876
  autoLink: false,
24877
+ autoHyphen: false,
24636
24878
  };
24637
24879
  /**
24638
24880
  * Auto Format plugin handles auto formatting, such as transforming * characters into a bullet list.
@@ -24645,6 +24887,7 @@ var AutoFormatPlugin = /** @class */ (function () {
24645
24887
  * - autoNumbering: A boolean that enables or disables automatic numbering formatting. Defaults to false.
24646
24888
  * - autoLink: A boolean that enables or disables automatic hyperlink creation when pasting or typing content. Defaults to false.
24647
24889
  * - autoUnlink: A boolean that enables or disables automatic hyperlink removal when pressing backspace. Defaults to false.
24890
+ * - autoHyphen: A boolean that enables or disables automatic hyphen transformation. Defaults to false.
24648
24891
  */
24649
24892
  function AutoFormatPlugin(options) {
24650
24893
  if (options === void 0) { options = DefaultOptions; }
@@ -24696,15 +24939,29 @@ var AutoFormatPlugin = /** @class */ (function () {
24696
24939
  }
24697
24940
  };
24698
24941
  AutoFormatPlugin.prototype.handleEditorInputEvent = function (editor, event) {
24942
+ var _this = this;
24699
24943
  var rawEvent = event.rawEvent;
24700
- if (rawEvent.inputType === 'insertText') {
24944
+ var selection = editor.getDOMSelection();
24945
+ if (rawEvent.inputType === 'insertText' &&
24946
+ selection &&
24947
+ selection.type === 'range' &&
24948
+ selection.range.collapsed) {
24701
24949
  switch (rawEvent.data) {
24702
24950
  case ' ':
24703
- var _a = this.options, autoBullet = _a.autoBullet, autoNumbering = _a.autoNumbering, autoLink = _a.autoLink;
24704
- (0, keyboardListTrigger_1.keyboardListTrigger)(editor, autoBullet, autoNumbering);
24705
- if (autoLink) {
24706
- (0, createLinkAfterSpace_1.createLinkAfterSpace)(editor);
24707
- }
24951
+ (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;
24953
+ var shouldHyphen = false;
24954
+ var shouldLink = false;
24955
+ if (autoLink) {
24956
+ shouldLink = (0, createLinkAfterSpace_1.createLinkAfterSpace)(previousSegment, paragraph, context);
24957
+ }
24958
+ if (autoHyphen) {
24959
+ shouldHyphen = (0, transformHyphen_1.transformHyphen)(previousSegment, paragraph, context);
24960
+ }
24961
+ return ((0, keyboardListTrigger_1.keyboardListTrigger)(model, paragraph, context, autoBullet, autoNumbering) ||
24962
+ shouldHyphen ||
24963
+ shouldLink);
24964
+ });
24708
24965
  break;
24709
24966
  }
24710
24967
  }
@@ -24732,6 +24989,51 @@ var AutoFormatPlugin = /** @class */ (function () {
24732
24989
  exports.AutoFormatPlugin = AutoFormatPlugin;
24733
24990
 
24734
24991
 
24992
+ /***/ }),
24993
+
24994
+ /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/hyphen/transformHyphen.ts":
24995
+ /*!*******************************************************************************************!*\
24996
+ !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/hyphen/transformHyphen.ts ***!
24997
+ \*******************************************************************************************/
24998
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
24999
+
25000
+ "use strict";
25001
+
25002
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
25003
+ exports.transformHyphen = void 0;
25004
+ var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
25005
+ /**
25006
+ * @internal
25007
+ */
25008
+ function transformHyphen(previousSegment, paragraph, context) {
25009
+ var segments = previousSegment.text.split(' ');
25010
+ var dashes = segments[segments.length - 2];
25011
+ if (dashes === '--') {
25012
+ var textIndex = previousSegment.text.lastIndexOf('--');
25013
+ var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + 2);
25014
+ textSegment.text = textSegment.text.replace('--', '—');
25015
+ context.canUndoByBackspace = true;
25016
+ return true;
25017
+ }
25018
+ else {
25019
+ var text = segments.pop();
25020
+ var hasDashes = text && (text === null || text === void 0 ? void 0 : text.indexOf('--')) > -1;
25021
+ if (hasDashes && text.trim() !== '--') {
25022
+ var textIndex = previousSegment.text.indexOf(text);
25023
+ var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + text.length - 1);
25024
+ var textLength = textSegment.text.length;
25025
+ if (textSegment.text[0] !== '-' && textSegment.text[textLength - 1] !== '-') {
25026
+ textSegment.text = textSegment.text.replace('--', '—');
25027
+ context.canUndoByBackspace = true;
25028
+ return true;
25029
+ }
25030
+ }
25031
+ }
25032
+ return false;
25033
+ }
25034
+ exports.transformHyphen = transformHyphen;
25035
+
25036
+
24735
25037
  /***/ }),
24736
25038
 
24737
25039
  /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/createLink.ts":
@@ -24745,17 +25047,17 @@ exports.AutoFormatPlugin = AutoFormatPlugin;
24745
25047
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24746
25048
  exports.createLink = void 0;
24747
25049
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
24748
- var getLinkSegment_1 = __webpack_require__(/*! ./getLinkSegment */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/getLinkSegment.ts");
25050
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
24749
25051
  /**
24750
25052
  * @internal
24751
25053
  */
24752
25054
  function createLink(editor) {
24753
- editor.formatContentModel(function (model) {
24754
- var link = (0, getLinkSegment_1.getLinkSegment)(model);
24755
- if (link && !link.link) {
24756
- (0, roosterjs_content_model_dom_1.addLink)(link, {
25055
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (_model, linkSegment, _paragraph) {
25056
+ var linkData = null;
25057
+ if (!linkSegment.link && (linkData = (0, roosterjs_content_model_api_1.matchLink)(linkSegment.text))) {
25058
+ (0, roosterjs_content_model_dom_1.addLink)(linkSegment, {
24757
25059
  format: {
24758
- href: link.text,
25060
+ href: linkData.normalizedUrl,
24759
25061
  underline: true,
24760
25062
  },
24761
25063
  dataset: {},
@@ -24780,84 +25082,30 @@ exports.createLink = createLink;
24780
25082
 
24781
25083
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24782
25084
  exports.createLinkAfterSpace = void 0;
24783
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
24784
25085
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
24785
25086
  var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
24786
25087
  /**
24787
25088
  * @internal
24788
25089
  */
24789
- function createLinkAfterSpace(editor) {
24790
- editor.formatContentModel(function (model, context) {
24791
- var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /* includingFormatHolder */);
24792
- if (selectedSegmentsAndParagraphs.length > 0 && selectedSegmentsAndParagraphs[0][1]) {
24793
- var markerIndex = selectedSegmentsAndParagraphs[0][1].segments.findIndex(function (segment) { return segment.segmentType == 'SelectionMarker'; });
24794
- var paragraph = selectedSegmentsAndParagraphs[0][1];
24795
- if (markerIndex > 0) {
24796
- var textSegment = paragraph.segments[markerIndex - 1];
24797
- var marker = paragraph.segments[markerIndex];
24798
- if (marker.segmentType == 'SelectionMarker' &&
24799
- textSegment &&
24800
- textSegment.segmentType == 'Text' &&
24801
- !textSegment.link) {
24802
- var link = textSegment.text.split(' ').pop();
24803
- var url = link === null || link === void 0 ? void 0 : link.trim();
24804
- var linkData = null;
24805
- if (url && link && (linkData = (0, roosterjs_content_model_api_1.matchLink)(url))) {
24806
- var linkSegment = (0, splitTextSegment_1.splitTextSegment)(textSegment, paragraph, textSegment.text.length - link.trimLeft().length, textSegment.text.trimRight().length);
24807
- linkSegment.link = {
24808
- format: {
24809
- href: linkData.normalizedUrl,
24810
- underline: true,
24811
- },
24812
- dataset: {},
24813
- };
24814
- context.canUndoByBackspace = true;
24815
- return true;
24816
- }
24817
- }
24818
- }
24819
- }
24820
- return false;
24821
- });
24822
- }
24823
- exports.createLinkAfterSpace = createLinkAfterSpace;
24824
-
24825
-
24826
- /***/ }),
24827
-
24828
- /***/ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/getLinkSegment.ts":
24829
- /*!****************************************************************************************!*\
24830
- !*** ./packages/roosterjs-content-model-plugins/lib/autoFormat/link/getLinkSegment.ts ***!
24831
- \****************************************************************************************/
24832
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
24833
-
24834
- "use strict";
24835
-
24836
- Object.defineProperty(exports, "__esModule", ({ value: true }));
24837
- exports.getLinkSegment = void 0;
24838
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
24839
- var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
24840
- /**
24841
- * @internal
24842
- */
24843
- function getLinkSegment(model) {
24844
- var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /* includingFormatHolder */);
24845
- if (selectedSegmentsAndParagraphs.length == 1 && selectedSegmentsAndParagraphs[0][1]) {
24846
- var selectedParagraph = selectedSegmentsAndParagraphs[0][1];
24847
- var marker = selectedParagraph.segments[selectedParagraph.segments.length - 1];
24848
- var link = selectedParagraph.segments[selectedParagraph.segments.length - 2];
24849
- if (marker &&
24850
- link &&
24851
- marker.segmentType === 'SelectionMarker' &&
24852
- marker.isSelected &&
24853
- link.segmentType === 'Text' &&
24854
- ((0, roosterjs_content_model_api_1.matchLink)(link.text) || link.link)) {
24855
- return link;
24856
- }
25090
+ function createLinkAfterSpace(previousSegment, paragraph, context) {
25091
+ var link = previousSegment.text.split(' ').pop();
25092
+ var url = link === null || link === void 0 ? void 0 : link.trim();
25093
+ var linkData = null;
25094
+ if (url && link && (linkData = (0, roosterjs_content_model_api_1.matchLink)(url))) {
25095
+ var linkSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - link.trimLeft().length, previousSegment.text.trimRight().length);
25096
+ linkSegment.link = {
25097
+ format: {
25098
+ href: linkData.normalizedUrl,
25099
+ underline: true,
25100
+ },
25101
+ dataset: {},
25102
+ };
25103
+ context.canUndoByBackspace = true;
25104
+ return true;
24857
25105
  }
24858
- return undefined;
25106
+ return false;
24859
25107
  }
24860
- exports.getLinkSegment = getLinkSegment;
25108
+ exports.createLinkAfterSpace = createLinkAfterSpace;
24861
25109
 
24862
25110
 
24863
25111
  /***/ }),
@@ -24872,15 +25120,14 @@ exports.getLinkSegment = getLinkSegment;
24872
25120
 
24873
25121
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24874
25122
  exports.unlink = void 0;
24875
- var getLinkSegment_1 = __webpack_require__(/*! ./getLinkSegment */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/link/getLinkSegment.ts");
25123
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
24876
25124
  /**
24877
25125
  * @internal
24878
25126
  */
24879
25127
  function unlink(editor, rawEvent) {
24880
- editor.formatContentModel(function (model) {
24881
- var link = (0, getLinkSegment_1.getLinkSegment)(model);
24882
- if (link === null || link === void 0 ? void 0 : link.link) {
24883
- link.link = undefined;
25128
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (_model, linkSegment, _paragraph) {
25129
+ if (linkSegment === null || linkSegment === void 0 ? void 0 : linkSegment.link) {
25130
+ linkSegment.link = undefined;
24884
25131
  rawEvent.preventDefault();
24885
25132
  return true;
24886
25133
  }
@@ -24979,7 +25226,7 @@ function getListTypeStyle(model, shouldSearchForBullet, shouldSearchForNumbering
24979
25226
  marker.segmentType == 'SelectionMarker' &&
24980
25227
  listMarkerSegment &&
24981
25228
  listMarkerSegment.segmentType == 'Text') {
24982
- var listMarker = listMarkerSegment.text;
25229
+ var listMarker = listMarkerSegment.text.trim();
24983
25230
  var bulletType = bulletListType[listMarker];
24984
25231
  if (bulletType && shouldSearchForBullet) {
24985
25232
  return { listType: 'UL', styleType: bulletType };
@@ -25042,7 +25289,7 @@ var bulletListType = {
25042
25289
  '—': roosterjs_content_model_dom_1.BulletListType.Hyphen,
25043
25290
  };
25044
25291
  var isNewList = function (listMarker) {
25045
- var marker = listMarker.replace(/[^\w\s]/g, '').trim();
25292
+ var marker = listMarker.replace(/[^\w\s]/g, '');
25046
25293
  var pattern = /^[1aAiI]$/;
25047
25294
  return pattern.test(marker);
25048
25295
  };
@@ -25225,32 +25472,24 @@ function canAppendList(index, previousListIndex) {
25225
25472
  Object.defineProperty(exports, "__esModule", ({ value: true }));
25226
25473
  exports.keyboardListTrigger = void 0;
25227
25474
  var getListTypeStyle_1 = __webpack_require__(/*! ./getListTypeStyle */ "./packages/roosterjs-content-model-plugins/lib/autoFormat/list/getListTypeStyle.ts");
25228
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
25229
25475
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
25230
25476
  /**
25231
25477
  * @internal
25232
25478
  */
25233
- function keyboardListTrigger(editor, shouldSearchForBullet, shouldSearchForNumbering) {
25479
+ function keyboardListTrigger(model, paragraph, context, shouldSearchForBullet, shouldSearchForNumbering) {
25234
25480
  if (shouldSearchForBullet === void 0) { shouldSearchForBullet = true; }
25235
25481
  if (shouldSearchForNumbering === void 0) { shouldSearchForNumbering = true; }
25236
25482
  if (shouldSearchForBullet || shouldSearchForNumbering) {
25237
- editor.formatContentModel(function (model, context) {
25238
- var listStyleType = (0, getListTypeStyle_1.getListTypeStyle)(model, shouldSearchForBullet, shouldSearchForNumbering);
25239
- if (listStyleType) {
25240
- var segmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false);
25241
- if (segmentsAndParagraphs[0] && segmentsAndParagraphs[0][1]) {
25242
- segmentsAndParagraphs[0][1].segments.splice(0, 1);
25243
- }
25244
- var listType = listStyleType.listType, styleType = listStyleType.styleType, index = listStyleType.index;
25245
- triggerList(model, listType, styleType, index);
25246
- context.canUndoByBackspace = true;
25247
- return true;
25248
- }
25249
- return false;
25250
- }, {
25251
- apiName: 'autoToggleList',
25252
- });
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
+ }
25253
25491
  }
25492
+ return false;
25254
25493
  }
25255
25494
  exports.keyboardListTrigger = keyboardListTrigger;
25256
25495
  var triggerList = function (model, listType, styleType, index) {
@@ -25743,15 +25982,21 @@ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-mo
25743
25982
  * @internal
25744
25983
  */
25745
25984
  var deleteList = function (context) {
25985
+ if (context.deleteResult != 'notDeleted') {
25986
+ return;
25987
+ }
25746
25988
  var _a = context.insertPoint, paragraph = _a.paragraph, marker = _a.marker, path = _a.path;
25747
- if (context.deleteResult == 'nothingToDelete' || context.deleteResult == 'notDeleted') {
25748
- var index = (0, roosterjs_content_model_dom_1.getClosestAncestorBlockGroupIndex)(path, ['ListItem', 'TableCell']);
25989
+ if (paragraph.segments[0] == marker) {
25990
+ var index = (0, roosterjs_content_model_dom_1.getClosestAncestorBlockGroupIndex)(path, ['ListItem'], ['TableCell', 'FormatContainer']);
25749
25991
  var item = path[index];
25750
- if (item &&
25751
- index >= 0 &&
25752
- paragraph.segments[0] == marker &&
25753
- item.blockGroupType == 'ListItem') {
25754
- item.levels = [];
25992
+ var lastLevel = item === null || item === void 0 ? void 0 : item.levels[item.levels.length - 1];
25993
+ if (lastLevel && (item === null || item === void 0 ? void 0 : item.blocks[0]) == paragraph) {
25994
+ if (lastLevel.format.displayForDummyItem == 'block') {
25995
+ item.levels.pop();
25996
+ }
25997
+ else {
25998
+ lastLevel.format.displayForDummyItem = 'block';
25999
+ }
25755
26000
  context.deleteResult = 'range';
25756
26001
  }
25757
26002
  }
@@ -26095,7 +26340,7 @@ var createNewListItem = function (context, listItem, listParent) {
26095
26340
  };
26096
26341
  var createNewListLevel = function (listItem) {
26097
26342
  return listItem.levels.map(function (level) {
26098
- return (0, roosterjs_content_model_dom_1.createListLevel)(level.listType, (0, tslib_1.__assign)((0, tslib_1.__assign)({}, level.format), { startNumberOverride: undefined }), level.dataset);
26343
+ return (0, roosterjs_content_model_dom_1.createListLevel)(level.listType, (0, tslib_1.__assign)((0, tslib_1.__assign)({}, level.format), { startNumberOverride: undefined, displayForDummyItem: undefined }), level.dataset);
26099
26344
  });
26100
26345
  };
26101
26346
  var createNewParagraph = function (insertPoint) {
@@ -26126,10 +26371,10 @@ var createNewParagraph = function (insertPoint) {
26126
26371
 
26127
26372
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26128
26373
  exports.keyboardDelete = void 0;
26129
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26130
26374
  var deleteAllSegmentBefore_1 = __webpack_require__(/*! ./deleteSteps/deleteAllSegmentBefore */ "./packages/roosterjs-content-model-plugins/lib/edit/deleteSteps/deleteAllSegmentBefore.ts");
26131
26375
  var deleteEmptyQuote_1 = __webpack_require__(/*! ./deleteSteps/deleteEmptyQuote */ "./packages/roosterjs-content-model-plugins/lib/edit/deleteSteps/deleteEmptyQuote.ts");
26132
26376
  var deleteList_1 = __webpack_require__(/*! ./deleteSteps/deleteList */ "./packages/roosterjs-content-model-plugins/lib/edit/deleteSteps/deleteList.ts");
26377
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26133
26378
  var handleKeyboardEventCommon_1 = __webpack_require__(/*! ./handleKeyboardEventCommon */ "./packages/roosterjs-content-model-plugins/lib/edit/handleKeyboardEventCommon.ts");
26134
26379
  var deleteWordSelection_1 = __webpack_require__(/*! ./deleteSteps/deleteWordSelection */ "./packages/roosterjs-content-model-plugins/lib/edit/deleteSteps/deleteWordSelection.ts");
26135
26380
  var deleteCollapsedSelection_1 = __webpack_require__(/*! ./deleteSteps/deleteCollapsedSelection */ "./packages/roosterjs-content-model-plugins/lib/edit/deleteSteps/deleteCollapsedSelection.ts");
@@ -26173,8 +26418,8 @@ function getDeleteSteps(rawEvent, isMac) {
26173
26418
  return [
26174
26419
  deleteAllSegmentBeforeStep,
26175
26420
  deleteWordSelection,
26421
+ isForward ? null : deleteList_1.deleteList,
26176
26422
  deleteCollapsedSelection,
26177
- deleteList_1.deleteList,
26178
26423
  deleteQuote,
26179
26424
  ];
26180
26425
  }
@@ -26287,34 +26532,50 @@ exports.keyboardTab = void 0;
26287
26532
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26288
26533
  var handleTabOnList_1 = __webpack_require__(/*! ./tabUtils/handleTabOnList */ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnList.ts");
26289
26534
  var handleTabOnParagraph_1 = __webpack_require__(/*! ./tabUtils/handleTabOnParagraph */ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnParagraph.ts");
26535
+ var handleTabOnTable_1 = __webpack_require__(/*! ./tabUtils/handleTabOnTable */ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTable.ts");
26536
+ var handleTabOnTableCell_1 = __webpack_require__(/*! ./tabUtils/handleTabOnTableCell */ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTableCell.ts");
26290
26537
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26291
26538
  /**
26292
26539
  * @internal
26293
26540
  */
26294
26541
  function keyboardTab(editor, rawEvent) {
26295
26542
  var selection = editor.getDOMSelection();
26296
- if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'range') {
26297
- editor.formatContentModel(function (model) {
26298
- return handleTab(model, rawEvent);
26299
- }, {
26300
- apiName: 'handleTabKey',
26301
- });
26302
- return true;
26543
+ switch (selection === null || selection === void 0 ? void 0 : selection.type) {
26544
+ case 'range':
26545
+ editor.formatContentModel(function (model) {
26546
+ return handleTab(model, rawEvent);
26547
+ }, {
26548
+ apiName: 'handleTabKey',
26549
+ });
26550
+ return true;
26551
+ case 'table':
26552
+ editor.formatContentModel(function (model) {
26553
+ return (0, handleTabOnTable_1.handleTabOnTable)(model, rawEvent);
26554
+ }, {
26555
+ apiName: 'handleTabKey',
26556
+ });
26557
+ return true;
26303
26558
  }
26304
26559
  }
26305
26560
  exports.keyboardTab = keyboardTab;
26306
26561
  /**
26307
26562
  * If multiple blocks are selected, indent or outdent the selected blocks with setModelIndentation.
26308
- * If only one block is selected, call handleTabOnParagraph or handleTabOnList to handle the tab key.
26563
+ * If only one block is selected:
26564
+ * - If it is a table cell, call handleTabOnTableCell to handle the tab key.
26565
+ * - If it is a paragraph, call handleTabOnParagraph to handle the tab key.
26566
+ * - If it is a list item, call handleTabOnList to handle the tab key.
26309
26567
  */
26310
26568
  function handleTab(model, rawEvent) {
26311
- var blocks = (0, roosterjs_content_model_dom_1.getOperationalBlocks)(model, ['ListItem'], ['TableCell']);
26569
+ var blocks = (0, roosterjs_content_model_dom_1.getOperationalBlocks)(model, ['ListItem', 'TableCell'], []);
26312
26570
  var block = blocks.length > 0 ? blocks[0].block : undefined;
26313
26571
  if (blocks.length > 1) {
26314
26572
  (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
26315
26573
  rawEvent.preventDefault();
26316
26574
  return true;
26317
26575
  }
26576
+ else if ((0, roosterjs_content_model_dom_1.isBlockGroupOfType)(block, 'TableCell')) {
26577
+ return (0, handleTabOnTableCell_1.handleTabOnTableCell)(model, block, rawEvent);
26578
+ }
26318
26579
  else if ((block === null || block === void 0 ? void 0 : block.blockType) === 'Paragraph') {
26319
26580
  return (0, handleTabOnParagraph_1.handleTabOnParagraph)(model, block, rawEvent);
26320
26581
  }
@@ -26467,6 +26728,91 @@ function handleTabOnParagraph(model, paragraph, rawEvent) {
26467
26728
  exports.handleTabOnParagraph = handleTabOnParagraph;
26468
26729
 
26469
26730
 
26731
+ /***/ }),
26732
+
26733
+ /***/ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTable.ts":
26734
+ /*!****************************************************************************************!*\
26735
+ !*** ./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTable.ts ***!
26736
+ \****************************************************************************************/
26737
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26738
+
26739
+ "use strict";
26740
+
26741
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26742
+ exports.handleTabOnTable = void 0;
26743
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26744
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26745
+ /**
26746
+ * When the whole table is selected, indent or outdent the whole table with setModelIndentation.
26747
+ * @internal
26748
+ */
26749
+ function handleTabOnTable(model, rawEvent) {
26750
+ var tableModel = (0, roosterjs_content_model_dom_1.getFirstSelectedTable)(model)[0];
26751
+ if (tableModel && isWholeTableSelected(tableModel)) {
26752
+ (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
26753
+ rawEvent.preventDefault();
26754
+ return true;
26755
+ }
26756
+ return false;
26757
+ }
26758
+ exports.handleTabOnTable = handleTabOnTable;
26759
+ function isWholeTableSelected(tableModel) {
26760
+ var _a, _b, _c, _d;
26761
+ return (((_b = (_a = tableModel.rows[0]) === null || _a === void 0 ? void 0 : _a.cells[0]) === null || _b === void 0 ? void 0 : _b.isSelected) &&
26762
+ ((_d = (_c = tableModel.rows[tableModel.rows.length - 1]) === null || _c === void 0 ? void 0 : _c.cells[tableModel.widths.length - 1]) === null || _d === void 0 ? void 0 : _d.isSelected));
26763
+ }
26764
+
26765
+
26766
+ /***/ }),
26767
+
26768
+ /***/ "./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTableCell.ts":
26769
+ /*!********************************************************************************************!*\
26770
+ !*** ./packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnTableCell.ts ***!
26771
+ \********************************************************************************************/
26772
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26773
+
26774
+ "use strict";
26775
+
26776
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26777
+ exports.handleTabOnTableCell = void 0;
26778
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26779
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26780
+ /**
26781
+ * When the cursor is on the last cell of a table, add new row and focus first new cell.
26782
+ * @internal
26783
+ */
26784
+ function handleTabOnTableCell(model, cell, rawEvent) {
26785
+ var _a, _b, _c;
26786
+ var tableModel = (0, roosterjs_content_model_dom_1.getFirstSelectedTable)(model)[0];
26787
+ // Check if cursor is on last cell of the table
26788
+ if (!rawEvent.shiftKey &&
26789
+ tableModel &&
26790
+ ((_a = tableModel.rows[tableModel.rows.length - 1]) === null || _a === void 0 ? void 0 : _a.cells[tableModel.widths.length - 1]) === cell) {
26791
+ (0, roosterjs_content_model_api_1.insertTableRow)(tableModel, 'insertBelow');
26792
+ // Clear Table selection
26793
+ (0, roosterjs_content_model_api_1.clearSelectedCells)(tableModel, {
26794
+ firstRow: tableModel.rows.length - 1,
26795
+ firstColumn: 0,
26796
+ lastRow: tableModel.rows.length - 1,
26797
+ lastColumn: tableModel.widths.length - 1,
26798
+ });
26799
+ (0, roosterjs_content_model_dom_1.normalizeTable)(tableModel, model.format);
26800
+ // Add selection marker to the first cell of the new row
26801
+ var markerParagraph = (_c = (_b = tableModel.rows[tableModel.rows.length - 1]) === null || _b === void 0 ? void 0 : _b.cells[0]) === null || _c === void 0 ? void 0 : _c.blocks[0];
26802
+ if (markerParagraph.blockType == 'Paragraph') {
26803
+ var marker = (0, roosterjs_content_model_dom_1.createSelectionMarker)(model.format);
26804
+ markerParagraph.segments.unshift(marker);
26805
+ (0, roosterjs_content_model_dom_1.setParagraphNotImplicit)(markerParagraph);
26806
+ (0, roosterjs_content_model_dom_1.setSelection)(tableModel.rows[tableModel.rows.length - 1].cells[0], marker);
26807
+ }
26808
+ rawEvent.preventDefault();
26809
+ return true;
26810
+ }
26811
+ return false;
26812
+ }
26813
+ exports.handleTabOnTableCell = handleTabOnTableCell;
26814
+
26815
+
26470
26816
  /***/ }),
26471
26817
 
26472
26818
  /***/ "./packages/roosterjs-content-model-plugins/lib/edit/utils/getLeafSiblingBlock.ts":
@@ -26553,6 +26899,157 @@ function getLeafSiblingBlock(path, block, isNext) {
26553
26899
  exports.getLeafSiblingBlock = getLeafSiblingBlock;
26554
26900
 
26555
26901
 
26902
+ /***/ }),
26903
+
26904
+ /***/ "./packages/roosterjs-content-model-plugins/lib/hyperlink/HyperlinkPlugin.ts":
26905
+ /*!***********************************************************************************!*\
26906
+ !*** ./packages/roosterjs-content-model-plugins/lib/hyperlink/HyperlinkPlugin.ts ***!
26907
+ \***********************************************************************************/
26908
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26909
+
26910
+ "use strict";
26911
+
26912
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26913
+ exports.HyperlinkPlugin = void 0;
26914
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26915
+ var defaultToolTipCallback = function (url) { return url; };
26916
+ /**
26917
+ * Hyperlink plugin does the following jobs for a hyperlink in editor:
26918
+ * 1. When hover on a link, show a tool tip
26919
+ * 2. When Ctrl+Click on a link, open a new window with the link
26920
+ * 3. When type directly on a link whose text matches its link url, update the link url with the link text
26921
+ */
26922
+ var HyperlinkPlugin = /** @class */ (function () {
26923
+ /**
26924
+ * Create a new instance of HyperLink class
26925
+ * @param tooltip Tooltip to show when mouse hover over a link
26926
+ * Default value is to return the href itself. If null, there will be no tooltip text.
26927
+ * @param target (Optional) Target window name for hyperlink. If null, will use "_blank"
26928
+ * @param onLinkClick (Optional) Open link callback (return false to use default behavior)
26929
+ */
26930
+ function HyperlinkPlugin(tooltip, target, onLinkClick) {
26931
+ var _this = this;
26932
+ if (tooltip === void 0) { tooltip = defaultToolTipCallback; }
26933
+ this.tooltip = tooltip;
26934
+ this.target = target;
26935
+ this.onLinkClick = onLinkClick;
26936
+ this.editor = null;
26937
+ this.domHelper = null;
26938
+ this.isMac = false;
26939
+ this.disposer = null;
26940
+ this.currentNode = null;
26941
+ this.currentLink = null;
26942
+ this.onMouse = function (e) {
26943
+ _this.runWithHyperlink(e.target, function (href, a) {
26944
+ var _a;
26945
+ var tooltip = e.type == 'mouseover'
26946
+ ? typeof _this.tooltip == 'function'
26947
+ ? _this.tooltip(href, a)
26948
+ : _this.tooltip
26949
+ : null;
26950
+ (_a = _this.domHelper) === null || _a === void 0 ? void 0 : _a.setDomAttribute('title', tooltip);
26951
+ });
26952
+ };
26953
+ }
26954
+ /**
26955
+ * Get a friendly name of this plugin
26956
+ */
26957
+ HyperlinkPlugin.prototype.getName = function () {
26958
+ return 'Hyperlink';
26959
+ };
26960
+ /**
26961
+ * Initialize this plugin
26962
+ * @param editor The editor instance
26963
+ */
26964
+ HyperlinkPlugin.prototype.initialize = function (editor) {
26965
+ this.editor = editor;
26966
+ this.domHelper = editor.getDOMHelper();
26967
+ this.isMac = !!editor.getEnvironment().isMac;
26968
+ this.disposer = editor.attachDomEvent({
26969
+ mouseover: { beforeDispatch: this.onMouse },
26970
+ mouseout: { beforeDispatch: this.onMouse },
26971
+ });
26972
+ };
26973
+ /**
26974
+ * Dispose this plugin
26975
+ */
26976
+ HyperlinkPlugin.prototype.dispose = function () {
26977
+ if (this.disposer) {
26978
+ this.disposer();
26979
+ this.disposer = null;
26980
+ }
26981
+ this.currentNode = null;
26982
+ this.currentLink = null;
26983
+ this.editor = null;
26984
+ };
26985
+ /**
26986
+ * Handle events triggered from editor
26987
+ * @param event PluginEvent object
26988
+ */
26989
+ HyperlinkPlugin.prototype.onPluginEvent = function (event) {
26990
+ var _this = this;
26991
+ var _a, _b;
26992
+ var matchedLink;
26993
+ if (event.eventType == 'keyDown') {
26994
+ var selection = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDOMSelection();
26995
+ var node_1 = (selection === null || selection === void 0 ? void 0 : selection.type) == 'range' ? selection.range.commonAncestorContainer : null;
26996
+ if (node_1 && node_1 != this.currentNode) {
26997
+ this.currentNode = node_1;
26998
+ this.currentLink = null;
26999
+ this.runWithHyperlink(node_1, function (href, a) {
27000
+ if (node_1.textContent &&
27001
+ (matchedLink = (0, roosterjs_content_model_api_1.matchLink)(node_1.textContent)) &&
27002
+ matchedLink.normalizedUrl == href) {
27003
+ _this.currentLink = a;
27004
+ }
27005
+ });
27006
+ }
27007
+ }
27008
+ else if (event.eventType == 'keyUp') {
27009
+ var selection = (_b = this.editor) === null || _b === void 0 ? void 0 : _b.getDOMSelection();
27010
+ var node = (selection === null || selection === void 0 ? void 0 : selection.type) == 'range' ? selection.range.commonAncestorContainer : null;
27011
+ if (node &&
27012
+ node == this.currentNode &&
27013
+ this.currentLink &&
27014
+ this.currentLink.contains(node) &&
27015
+ node.textContent &&
27016
+ (matchedLink = (0, roosterjs_content_model_api_1.matchLink)(node.textContent))) {
27017
+ this.currentLink.setAttribute('href', matchedLink.normalizedUrl);
27018
+ }
27019
+ }
27020
+ else if (event.eventType == 'mouseUp' && event.isClicking) {
27021
+ this.runWithHyperlink(event.rawEvent.target, function (href, anchor) {
27022
+ var _a, _b;
27023
+ if (!((_a = _this.onLinkClick) === null || _a === void 0 ? void 0 : _a.call(_this, anchor, event.rawEvent)) &&
27024
+ _this.isCtrlOrMetaPressed(event.rawEvent) &&
27025
+ event.rawEvent.button === 0) {
27026
+ event.rawEvent.preventDefault();
27027
+ var target = _this.target || '_blank';
27028
+ var window_1 = (_b = _this.editor) === null || _b === void 0 ? void 0 : _b.getDocument().defaultView;
27029
+ try {
27030
+ window_1 === null || window_1 === void 0 ? void 0 : window_1.open(href, target);
27031
+ }
27032
+ catch (_c) { }
27033
+ }
27034
+ });
27035
+ }
27036
+ };
27037
+ HyperlinkPlugin.prototype.runWithHyperlink = function (node, callback) {
27038
+ var _a;
27039
+ var a = (_a = this.domHelper) === null || _a === void 0 ? void 0 : _a.findClosestElementAncestor(node, 'a[href]');
27040
+ var href = a === null || a === void 0 ? void 0 : a.getAttribute('href');
27041
+ if (href && a) {
27042
+ callback(href, a);
27043
+ }
27044
+ };
27045
+ HyperlinkPlugin.prototype.isCtrlOrMetaPressed = function (event) {
27046
+ return this.isMac ? event.metaKey : event.ctrlKey;
27047
+ };
27048
+ return HyperlinkPlugin;
27049
+ }());
27050
+ exports.HyperlinkPlugin = HyperlinkPlugin;
27051
+
27052
+
26556
27053
  /***/ }),
26557
27054
 
26558
27055
  /***/ "./packages/roosterjs-content-model-plugins/lib/index.ts":
@@ -26564,7 +27061,7 @@ exports.getLeafSiblingBlock = getLeafSiblingBlock;
26564
27061
  "use strict";
26565
27062
 
26566
27063
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26567
- 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;
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;
26568
27065
  var TableEditPlugin_1 = __webpack_require__(/*! ./tableEdit/TableEditPlugin */ "./packages/roosterjs-content-model-plugins/lib/tableEdit/TableEditPlugin.ts");
26569
27066
  Object.defineProperty(exports, "TableEditPlugin", ({ enumerable: true, get: function () { return TableEditPlugin_1.TableEditPlugin; } }));
26570
27067
  var PastePlugin_1 = __webpack_require__(/*! ./paste/PastePlugin */ "./packages/roosterjs-content-model-plugins/lib/paste/PastePlugin.ts");
@@ -26596,6 +27093,8 @@ var WatermarkPlugin_1 = __webpack_require__(/*! ./watermark/WatermarkPlugin */ "
26596
27093
  Object.defineProperty(exports, "WatermarkPlugin", ({ enumerable: true, get: function () { return WatermarkPlugin_1.WatermarkPlugin; } }));
26597
27094
  var MarkdownPlugin_1 = __webpack_require__(/*! ./markdown/MarkdownPlugin */ "./packages/roosterjs-content-model-plugins/lib/markdown/MarkdownPlugin.ts");
26598
27095
  Object.defineProperty(exports, "MarkdownPlugin", ({ enumerable: true, get: function () { return MarkdownPlugin_1.MarkdownPlugin; } }));
27096
+ var HyperlinkPlugin_1 = __webpack_require__(/*! ./hyperlink/HyperlinkPlugin */ "./packages/roosterjs-content-model-plugins/lib/hyperlink/HyperlinkPlugin.ts");
27097
+ Object.defineProperty(exports, "HyperlinkPlugin", ({ enumerable: true, get: function () { return HyperlinkPlugin_1.HyperlinkPlugin; } }));
26599
27098
 
26600
27099
 
26601
27100
  /***/ }),
@@ -26625,9 +27124,10 @@ var DefaultOptions = {
26625
27124
  var MarkdownPlugin = /** @class */ (function () {
26626
27125
  /**
26627
27126
  * @param options An optional parameter that takes in an object of type MarkdownOptions, which includes the following properties:
26628
- * - strikethrough: If true text between ~ will receive strikethrough format. Defaults to true.
26629
- * - bold: If true text between * will receive bold format. Defaults to true.
26630
- * - italic: If true text between _ will receive italic format. Defaults to true.
27127
+ * - strikethrough: If true text between ~ will receive strikethrough format. Defaults to false.
27128
+ * - bold: If true text between * will receive bold format. Defaults to false.
27129
+ * - italic: If true text between _ will receive italic format. Defaults to false.
27130
+ * - codeFormat: If provided, text between ` will receive code format. Defaults to undefined.
26631
27131
  */
26632
27132
  function MarkdownPlugin(options) {
26633
27133
  if (options === void 0) { options = DefaultOptions; }
@@ -26636,6 +27136,7 @@ var MarkdownPlugin = /** @class */ (function () {
26636
27136
  this.shouldBold = false;
26637
27137
  this.shouldItalic = false;
26638
27138
  this.shouldStrikethrough = false;
27139
+ this.shouldCode = false;
26639
27140
  this.lastKeyTyped = null;
26640
27141
  }
26641
27142
  /**
@@ -26660,9 +27161,7 @@ var MarkdownPlugin = /** @class */ (function () {
26660
27161
  */
26661
27162
  MarkdownPlugin.prototype.dispose = function () {
26662
27163
  this.editor = null;
26663
- this.shouldBold = false;
26664
- this.shouldItalic = false;
26665
- this.shouldStrikethrough = false;
27164
+ this.disableAllFeatures();
26666
27165
  this.lastKeyTyped = null;
26667
27166
  };
26668
27167
  /**
@@ -26728,6 +27227,17 @@ var MarkdownPlugin = /** @class */ (function () {
26728
27227
  }
26729
27228
  }
26730
27229
  break;
27230
+ case '`':
27231
+ if (this.options.codeFormat) {
27232
+ if (this.shouldCode) {
27233
+ (0, setFormat_1.setFormat)(editor, '`', {} /* format */, this.options.codeFormat);
27234
+ this.shouldCode = false;
27235
+ }
27236
+ else {
27237
+ this.shouldCode = true;
27238
+ }
27239
+ }
27240
+ break;
26731
27241
  }
26732
27242
  }
26733
27243
  };
@@ -26736,9 +27246,7 @@ var MarkdownPlugin = /** @class */ (function () {
26736
27246
  if (!event.handledByEditFeature && !rawEvent.defaultPrevented) {
26737
27247
  switch (rawEvent.key) {
26738
27248
  case 'Enter':
26739
- this.shouldBold = false;
26740
- this.shouldItalic = false;
26741
- this.shouldStrikethrough = false;
27249
+ this.disableAllFeatures();
26742
27250
  this.lastKeyTyped = null;
26743
27251
  break;
26744
27252
  case ' ':
@@ -26751,6 +27259,9 @@ var MarkdownPlugin = /** @class */ (function () {
26751
27259
  else if (this.lastKeyTyped === '_' && this.shouldItalic) {
26752
27260
  this.shouldItalic = false;
26753
27261
  }
27262
+ else if (this.lastKeyTyped === '`' && this.shouldCode) {
27263
+ this.shouldCode = false;
27264
+ }
26754
27265
  this.lastKeyTyped = null;
26755
27266
  break;
26756
27267
  default:
@@ -26770,16 +27281,23 @@ var MarkdownPlugin = /** @class */ (function () {
26770
27281
  else if (this.lastKeyTyped === '_' && this.shouldItalic) {
26771
27282
  this.shouldItalic = false;
26772
27283
  }
27284
+ else if (this.lastKeyTyped === '`' && this.shouldCode) {
27285
+ this.shouldCode = false;
27286
+ }
26773
27287
  this.lastKeyTyped = null;
26774
27288
  }
26775
27289
  };
26776
27290
  MarkdownPlugin.prototype.handleContentChangedEvent = function (event) {
26777
27291
  if (event.source == 'Format') {
26778
- this.shouldBold = false;
26779
- this.shouldItalic = false;
26780
- this.shouldStrikethrough = false;
27292
+ this.disableAllFeatures();
26781
27293
  }
26782
27294
  };
27295
+ MarkdownPlugin.prototype.disableAllFeatures = function () {
27296
+ this.shouldBold = false;
27297
+ this.shouldItalic = false;
27298
+ this.shouldStrikethrough = false;
27299
+ this.shouldCode = false;
27300
+ };
26783
27301
  return MarkdownPlugin;
26784
27302
  }());
26785
27303
  exports.MarkdownPlugin = MarkdownPlugin;
@@ -26798,41 +27316,31 @@ exports.MarkdownPlugin = MarkdownPlugin;
26798
27316
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26799
27317
  exports.setFormat = void 0;
26800
27318
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
26801
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
27319
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26802
27320
  var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26803
27321
  /**
26804
27322
  * @internal
26805
27323
  */
26806
- function setFormat(editor, character, format) {
26807
- editor.formatContentModel(function (model, context) {
26808
- var _a;
26809
- var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false /*includeFormatHolder*/);
26810
- if (selectedSegmentsAndParagraphs.length > 0 && selectedSegmentsAndParagraphs[0][1]) {
26811
- var marker = selectedSegmentsAndParagraphs[0][0];
26812
- context.newPendingFormat = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, marker.format), { strikethrough: !!marker.format.strikethrough, italic: !!marker.format.italic, fontWeight: ((_a = marker.format) === null || _a === void 0 ? void 0 : _a.fontWeight) ? 'bold' : undefined });
26813
- var paragraph = selectedSegmentsAndParagraphs[0][1];
26814
- if (marker.segmentType == 'SelectionMarker') {
26815
- var markerIndex = paragraph.segments.indexOf(marker);
26816
- if (markerIndex > 0 && paragraph.segments[markerIndex - 1]) {
26817
- var segmentBeforeMarker = paragraph.segments[markerIndex - 1];
26818
- if (segmentBeforeMarker.segmentType == 'Text' &&
26819
- segmentBeforeMarker.text[segmentBeforeMarker.text.length - 1] == character) {
26820
- var textBeforeMarker = segmentBeforeMarker.text.slice(0, -1);
26821
- if (textBeforeMarker.indexOf(character) > -1) {
26822
- var lastCharIndex = segmentBeforeMarker.text.length;
26823
- var firstCharIndex = segmentBeforeMarker.text
26824
- .substring(0, lastCharIndex - 1)
26825
- .lastIndexOf(character);
26826
- var formattedText = (0, splitTextSegment_1.splitTextSegment)(segmentBeforeMarker, paragraph, firstCharIndex, lastCharIndex);
26827
- formattedText.text = formattedText.text
26828
- .replace(character, '')
26829
- .slice(0, -1);
26830
- formattedText.format = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, formattedText.format), format);
26831
- context.canUndoByBackspace = true;
26832
- return true;
26833
- }
26834
- }
27324
+ function setFormat(editor, character, format, codeFormat) {
27325
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (_model, previousSegment, paragraph, markerFormat, context) {
27326
+ if (previousSegment.text[previousSegment.text.length - 1] == character) {
27327
+ var textBeforeMarker = previousSegment.text.slice(0, -1);
27328
+ context.newPendingFormat = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, markerFormat), { strikethrough: !!markerFormat.strikethrough, italic: !!markerFormat.italic, fontWeight: (markerFormat === null || markerFormat === void 0 ? void 0 : markerFormat.fontWeight) ? 'bold' : undefined });
27329
+ if (textBeforeMarker.indexOf(character) > -1) {
27330
+ var lastCharIndex = previousSegment.text.length;
27331
+ var firstCharIndex = previousSegment.text
27332
+ .substring(0, lastCharIndex - 1)
27333
+ .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
+ };
26835
27341
  }
27342
+ context.canUndoByBackspace = true;
27343
+ return true;
26836
27344
  }
26837
27345
  }
26838
27346
  return false;
@@ -28696,7 +29204,7 @@ exports.ShortcutUnderline = {
28696
29204
  /**
28697
29205
  * Shortcut command for Clear Format
28698
29206
  * Windows: Ctrl + Space
28699
- * MacOS: Meta + Space
29207
+ * MacOS: N/A
28700
29208
  */
28701
29209
  exports.ShortcutClearFormat = {
28702
29210
  shortcutKey: {
@@ -28705,6 +29213,7 @@ exports.ShortcutClearFormat = {
28705
29213
  which: 32 /* SPACE */,
28706
29214
  },
28707
29215
  onClick: function (editor) { return (0, roosterjs_content_model_api_1.clearFormat)(editor); },
29216
+ environment: 'nonMac',
28708
29217
  };
28709
29218
  /**
28710
29219
  * Shortcut command for Undo 1
@@ -28816,7 +29325,7 @@ exports.ShortcutDecreaseFont = {
28816
29325
  /**
28817
29326
  * Shortcut command for Intent list
28818
29327
  * Windows: Alt + Shift + Arrow Right
28819
- * MacOS: Option + Shift+ Arrow Right
29328
+ * MacOS: N/A
28820
29329
  */
28821
29330
  exports.ShortcutIndentList = {
28822
29331
  shortcutKey: {
@@ -28827,11 +29336,12 @@ exports.ShortcutIndentList = {
28827
29336
  onClick: function (editor) {
28828
29337
  (0, setShortcutIndentationCommand_1.setShortcutIndentationCommand)(editor, 'indent');
28829
29338
  },
29339
+ environment: 'nonMac',
28830
29340
  };
28831
29341
  /**
28832
29342
  * Shortcut command for Outdent list
28833
29343
  * Windows: Alt + Shift + Arrow Left
28834
- * MacOS: Option + Shift+ Arrow Left
29344
+ * MacOS: N/A
28835
29345
  */
28836
29346
  exports.ShortcutOutdentList = {
28837
29347
  shortcutKey: {
@@ -28842,6 +29352,7 @@ exports.ShortcutOutdentList = {
28842
29352
  onClick: function (editor) {
28843
29353
  (0, setShortcutIndentationCommand_1.setShortcutIndentationCommand)(editor, 'outdent');
28844
29354
  },
29355
+ environment: 'nonMac',
28845
29356
  };
28846
29357
 
28847
29358