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