roosterjs 9.51.0 → 9.53.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
@@ -9057,9 +9057,12 @@ function getContentForCopy(editor, isCut, event) {
9057
9057
  rawEvent: event,
9058
9058
  isCut: isCut,
9059
9059
  }).clonedRoot;
9060
+ // Build the text content from the (possibly modified) cloned root DOM tree so that any
9061
+ // changes made by beforeCutCopy event handlers are reflected in the plain text result as well
9062
+ var textModel = (0, roosterjs_content_model_dom_1.domToContentModel)(clonedRoot, (0, roosterjs_content_model_dom_1.createDomToModelContext)());
9060
9063
  return {
9061
9064
  htmlContent: clonedRoot,
9062
- textContent: (0, roosterjs_content_model_dom_1.contentModelToText)(pasteModel),
9065
+ textContent: (0, roosterjs_content_model_dom_1.contentModelToText)(textModel),
9063
9066
  };
9064
9067
  }
9065
9068
  }
@@ -9319,6 +9322,7 @@ function generatePasteOptionFromPlugins(editor, clipboardData, fragment, htmlFro
9319
9322
  pasteType: pasteType,
9320
9323
  domToModelOption: domToModelOption,
9321
9324
  containsBlockElements: !!htmlFromClipboard.containsBlockElements,
9325
+ globalCssRules: htmlFromClipboard.globalCssRules,
9322
9326
  };
9323
9327
  return editor.triggerEvent('beforePaste', event, true /* broadcast */);
9324
9328
  }
@@ -9926,6 +9930,7 @@ var announce = function (core, announceData) {
9926
9930
  var textToAnnounce = formatString(template || text, formatStrings);
9927
9931
  if (!core.lifecycle.announceContainer) {
9928
9932
  core.lifecycle.announceContainer = (0, createAriaLiveElement_1.createAriaLiveElement)(core.physicalRoot.ownerDocument);
9933
+ core.domHelper.appendToRoot(core.lifecycle.announceContainer);
9929
9934
  }
9930
9935
  if (textToAnnounce && core.lifecycle.announceContainer) {
9931
9936
  var announceContainer = core.lifecycle.announceContainer;
@@ -10417,16 +10422,19 @@ var getDOMSelection = function (core) {
10417
10422
  exports.getDOMSelection = getDOMSelection;
10418
10423
  function getNewSelection(core) {
10419
10424
  var _a;
10425
+ var range = core.domHelper.getSelectionRange();
10426
+ if (!range || !core.logicalRoot.contains(range.commonAncestorContainer)) {
10427
+ return null;
10428
+ }
10420
10429
  var selection = (_a = core.logicalRoot.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
10421
- var range = selection && selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
10422
- return selection && range && core.logicalRoot.contains(range.commonAncestorContainer)
10423
- ? {
10424
- type: 'range',
10425
- range: range,
10426
- isReverted: selection.focusNode != range.endContainer ||
10427
- selection.focusOffset != range.endOffset,
10428
- }
10429
- : null;
10430
+ var isReverted = selection
10431
+ ? selection.focusNode != range.endContainer || selection.focusOffset != range.endOffset
10432
+ : false;
10433
+ return {
10434
+ type: 'range',
10435
+ range: range,
10436
+ isReverted: isReverted,
10437
+ };
10430
10438
  }
10431
10439
 
10432
10440
 
@@ -10870,43 +10878,6 @@ var setContentModel = function (core, model, option, onNodeCreated, isInitializi
10870
10878
  exports.setContentModel = setContentModel;
10871
10879
 
10872
10880
 
10873
- /***/ },
10874
-
10875
- /***/ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/addRangeToSelection.ts"
10876
- /*!**************************************************************************************************!*\
10877
- !*** ./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/addRangeToSelection.ts ***!
10878
- \**************************************************************************************************/
10879
- (__unused_webpack_module, exports, __webpack_require__) {
10880
-
10881
- "use strict";
10882
-
10883
- Object.defineProperty(exports, "__esModule", ({ value: true }));
10884
- exports.addRangeToSelection = void 0;
10885
- var areSameSelections_1 = __webpack_require__(/*! ../../corePlugin/cache/areSameSelections */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts");
10886
- /**
10887
- * @internal
10888
- */
10889
- function addRangeToSelection(doc, range, isReverted) {
10890
- var _a;
10891
- if (isReverted === void 0) { isReverted = false; }
10892
- var selection = (_a = doc.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
10893
- if (selection) {
10894
- var currentRange = selection.rangeCount > 0 && selection.getRangeAt(0);
10895
- if (currentRange && (0, areSameSelections_1.areSameRanges)(currentRange, range)) {
10896
- return;
10897
- }
10898
- selection.removeAllRanges();
10899
- if (!isReverted) {
10900
- selection.addRange(range);
10901
- }
10902
- else {
10903
- selection.setBaseAndExtent(range.endContainer, range.endOffset, range.startContainer, range.startOffset);
10904
- }
10905
- }
10906
- }
10907
- exports.addRangeToSelection = addRangeToSelection;
10908
-
10909
-
10910
10881
  /***/ },
10911
10882
 
10912
10883
  /***/ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/findLastedCoInMergedCell.ts"
@@ -11008,7 +10979,6 @@ exports.findTableCellElement = findTableCellElement;
11008
10979
 
11009
10980
  Object.defineProperty(exports, "__esModule", ({ value: true }));
11010
10981
  exports.setDOMSelection = void 0;
11011
- var addRangeToSelection_1 = __webpack_require__(/*! ./addRangeToSelection */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/addRangeToSelection.ts");
11012
10982
  var areSameSelections_1 = __webpack_require__(/*! ../../corePlugin/cache/areSameSelections */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts");
11013
10983
  var ensureUniqueId_1 = __webpack_require__(/*! ../setEditorStyle/ensureUniqueId */ "./packages/roosterjs-content-model-core/lib/coreApi/setEditorStyle/ensureUniqueId.ts");
11014
10984
  var findLastedCoInMergedCell_1 = __webpack_require__(/*! ./findLastedCoInMergedCell */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/findLastedCoInMergedCell.ts");
@@ -11034,7 +11004,6 @@ var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
11034
11004
  // We are applying a new selection, so we don't need to apply cached selection in DOMEventPlugin.
11035
11005
  // Set skipReselectOnFocus to skip this behavior
11036
11006
  var skipReselectOnFocus = core.selection.skipReselectOnFocus;
11037
- var doc = core.physicalRoot.ownerDocument;
11038
11007
  var isDarkMode = core.lifecycle.isDarkMode;
11039
11008
  core.selection.skipReselectOnFocus = true;
11040
11009
  core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, null /*cssRule*/);
@@ -11050,7 +11019,7 @@ var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
11050
11019
  : core.selection.imageSelectionBorderColor;
11051
11020
  core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, "outline-style:solid!important; outline-color:" + (imageSelectionColor || DEFAULT_SELECTION_BORDER_COLOR) + "!important;", [(0, roosterjs_content_model_dom_1.getSafeIdSelector)((0, ensureUniqueId_1.ensureUniqueId)(image, IMAGE_ID))]);
11052
11021
  core.api.setEditorStyle(core, HIDE_SELECTION_CSS_KEY, TRANSPARENT_SELECTION_CSS_RULE, [SELECTION_SELECTOR]);
11053
- setRangeSelection(doc, image, false /* collapse */);
11022
+ setRangeSelection(core, image, false /* collapse */);
11054
11023
  break;
11055
11024
  case 'table':
11056
11025
  var table = selection.table, firstColumn = selection.firstColumn, firstRow = selection.firstRow, lastColumn = selection.lastColumn, lastRow = selection.lastRow;
@@ -11087,11 +11056,11 @@ var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
11087
11056
  (0, toggleCaret_1.toggleCaret)(core, true /* hide */);
11088
11057
  var nodeToSelect = ((_a = firstCell.cell) === null || _a === void 0 ? void 0 : _a.firstElementChild) || firstCell.cell;
11089
11058
  if (nodeToSelect) {
11090
- setRangeSelection(doc, nodeToSelect || undefined, true /* collapse */);
11059
+ setRangeSelection(core, nodeToSelect || undefined, true /* collapse */);
11091
11060
  }
11092
11061
  break;
11093
11062
  case 'range':
11094
- (0, addRangeToSelection_1.addRangeToSelection)(doc, selection.range, selection.isReverted);
11063
+ core.domHelper.setSelectionRange(selection.range, selection.isReverted);
11095
11064
  core.selection.selection = core.domHelper.hasFocus() ? null : selection;
11096
11065
  break;
11097
11066
  default:
@@ -11111,9 +11080,10 @@ var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
11111
11080
  }
11112
11081
  };
11113
11082
  exports.setDOMSelection = setDOMSelection;
11114
- function setRangeSelection(doc, element, collapse) {
11083
+ function setRangeSelection(core, element, collapse) {
11115
11084
  var _a;
11116
- if (element && doc.contains(element)) {
11085
+ if (element && core.domHelper.isNodeInEditor(element)) {
11086
+ var doc = core.physicalRoot.ownerDocument;
11117
11087
  var range = doc.createRange();
11118
11088
  var isReverted = undefined;
11119
11089
  range.selectNode(element);
@@ -11129,7 +11099,7 @@ function setRangeSelection(doc, element, collapse) {
11129
11099
  selection.focusOffset != range_1.endOffset;
11130
11100
  }
11131
11101
  }
11132
- (0, addRangeToSelection_1.addRangeToSelection)(doc, range, isReverted);
11102
+ core.domHelper.setSelectionRange(range, isReverted);
11133
11103
  }
11134
11104
  }
11135
11105
 
@@ -11316,9 +11286,9 @@ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-mo
11316
11286
  */
11317
11287
  function ensureUniqueId(element, idPrefix) {
11318
11288
  idPrefix = element.id || idPrefix;
11319
- var doc = element.ownerDocument;
11289
+ var root = element.getRootNode();
11320
11290
  var i = 0;
11321
- while (!element.id || doc.querySelectorAll((0, roosterjs_content_model_dom_1.getSafeIdSelector)(element.id)).length > 1) {
11291
+ while (!element.id || root.querySelectorAll((0, roosterjs_content_model_dom_1.getSafeIdSelector)(element.id)).length > 1) {
11322
11292
  element.id = idPrefix + '_' + i++;
11323
11293
  }
11324
11294
  return element.id;
@@ -11351,7 +11321,7 @@ var setEditorStyle = function (core, key, cssRule, subSelectors, maxRuleLength)
11351
11321
  if (!styleElement && cssRule) {
11352
11322
  var doc = core.physicalRoot.ownerDocument;
11353
11323
  styleElement = doc.createElement('style');
11354
- doc.head.appendChild(styleElement);
11324
+ core.domHelper.appendToRoot(styleElement);
11355
11325
  styleElement.dataset.roosterjsStyleKey = key;
11356
11326
  core.lifecycle.styleElements[key] = styleElement;
11357
11327
  }
@@ -11829,12 +11799,13 @@ exports.createParagraphMap = createParagraphMap;
11829
11799
  /*!*****************************************************************************************!*\
11830
11800
  !*** ./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts ***!
11831
11801
  \*****************************************************************************************/
11832
- (__unused_webpack_module, exports) {
11802
+ (__unused_webpack_module, exports, __webpack_require__) {
11833
11803
 
11834
11804
  "use strict";
11835
11805
 
11836
11806
  Object.defineProperty(exports, "__esModule", ({ value: true }));
11837
- exports.areSameRanges = exports.areSameTableSelections = exports.areSameSelections = void 0;
11807
+ exports.areSameTableSelections = exports.areSameSelections = void 0;
11808
+ var areSameRanges_1 = __webpack_require__(/*! ../../utils/areSameRanges */ "./packages/roosterjs-content-model-core/lib/utils/areSameRanges.ts");
11838
11809
  /**
11839
11810
  * @internal
11840
11811
  * Check if the given selections are the same
@@ -11860,7 +11831,7 @@ function areSameSelections(sel1, sel2) {
11860
11831
  range1.endOffset == end.offset);
11861
11832
  }
11862
11833
  else {
11863
- return areSameRanges(range1, sel2.range);
11834
+ return (0, areSameRanges_1.areSameRanges)(range1, sel2.range);
11864
11835
  }
11865
11836
  }
11866
11837
  else {
@@ -11879,7 +11850,6 @@ var TableSelectionKeys = [
11879
11850
  'firstRow',
11880
11851
  'lastRow',
11881
11852
  ];
11882
- var RangeKeys = ['startContainer', 'endContainer', 'startOffset', 'endOffset'];
11883
11853
  /**
11884
11854
  * @internal
11885
11855
  */
@@ -11887,13 +11857,6 @@ function areSameTableSelections(t1, t2) {
11887
11857
  return areSame(t1, t2, TableSelectionKeys);
11888
11858
  }
11889
11859
  exports.areSameTableSelections = areSameTableSelections;
11890
- /**
11891
- * @internal
11892
- */
11893
- function areSameRanges(r1, r2) {
11894
- return areSame(r1, r2, RangeKeys);
11895
- }
11896
- exports.areSameRanges = areSameRanges;
11897
11860
  function isCacheSelection(sel) {
11898
11861
  return !!sel.start;
11899
11862
  }
@@ -12071,7 +12034,13 @@ var DomIndexerImpl = /** @class */ (function () {
12071
12034
  }
12072
12035
  else {
12073
12036
  var marker1 = this.reconcileNodeSelection(startContainer, startOffset);
12074
- var marker2 = this.reconcileNodeSelection(endContainer, endOffset);
12037
+ // Pass marker1 to the second call so its adjacent-marker cleanup
12038
+ // does not consume the SelectionMarker we just inserted. Without
12039
+ // this guard, when marker1 lands directly next to endContainer's
12040
+ // segment in paragraph.segments (e.g. startOffset == startContainer
12041
+ // text length), the second splice would absorb marker1 and leave
12042
+ // setSelection with a dangling reference. See issue #3341.
12043
+ var marker2 = this.reconcileNodeSelection(endContainer, endOffset, undefined, undefined, marker1);
12075
12044
  if (marker1 && marker2) {
12076
12045
  if (newSelection.isReverted) {
12077
12046
  model.hasRevertedRangeSelection = true;
@@ -12147,10 +12116,10 @@ var DomIndexerImpl = /** @class */ (function () {
12147
12116
  var start = selection.start, end = selection.end;
12148
12117
  return start.node == end.node && start.offset == end.offset;
12149
12118
  };
12150
- DomIndexerImpl.prototype.reconcileNodeSelection = function (node, offset, defaultFormat, selectionMarker) {
12119
+ DomIndexerImpl.prototype.reconcileNodeSelection = function (node, offset, defaultFormat, selectionMarker, preserveMarker) {
12151
12120
  if ((0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'TEXT_NODE')) {
12152
12121
  if (isIndexedSegment(node)) {
12153
- return this.reconcileTextSelection(node, offset, undefined, selectionMarker);
12122
+ return this.reconcileTextSelection(node, offset, undefined, selectionMarker, preserveMarker);
12154
12123
  }
12155
12124
  else if (isIndexedDelimiter(node)) {
12156
12125
  return this.reconcileDelimiterSelection(node, defaultFormat);
@@ -12180,7 +12149,7 @@ var DomIndexerImpl = /** @class */ (function () {
12180
12149
  }
12181
12150
  return marker;
12182
12151
  };
12183
- DomIndexerImpl.prototype.reconcileTextSelection = function (textNode, startOffset, endOffset, selectionMarker) {
12152
+ DomIndexerImpl.prototype.reconcileTextSelection = function (textNode, startOffset, endOffset, selectionMarker, preserveMarker) {
12184
12153
  var _a;
12185
12154
  var _b, _c, _d, _e, _f, _g;
12186
12155
  var _h = textNode.__roosterjsContentModel, paragraph = _h.paragraph, segments = _h.segments;
@@ -12233,11 +12202,13 @@ var DomIndexerImpl = /** @class */ (function () {
12233
12202
  var lastIndex = paragraph.segments.indexOf(last);
12234
12203
  if (firstIndex >= 0 && lastIndex >= 0) {
12235
12204
  while (firstIndex > 0 &&
12236
- paragraph.segments[firstIndex - 1].segmentType == 'SelectionMarker') {
12205
+ paragraph.segments[firstIndex - 1].segmentType == 'SelectionMarker' &&
12206
+ paragraph.segments[firstIndex - 1] !== preserveMarker) {
12237
12207
  firstIndex--;
12238
12208
  }
12239
12209
  while (lastIndex < paragraph.segments.length - 1 &&
12240
- paragraph.segments[lastIndex + 1].segmentType == 'SelectionMarker') {
12210
+ paragraph.segments[lastIndex + 1].segmentType == 'SelectionMarker' &&
12211
+ paragraph.segments[lastIndex + 1] !== preserveMarker) {
12241
12212
  lastIndex++;
12242
12213
  }
12243
12214
  (_a = paragraph.segments).splice.apply(_a, (0, tslib_1.__spreadArray)([firstIndex, lastIndex - firstIndex + 1], (0, tslib_1.__read)(newSegments), false));
@@ -14355,6 +14326,7 @@ var LifecyclePlugin = /** @class */ (function () {
14355
14326
  delete this.state.rewriteFromModel;
14356
14327
  // Initialize the Announce container.
14357
14328
  this.state.announceContainer = (0, createAriaLiveElement_1.createAriaLiveElement)(editor.getDocument());
14329
+ editor.getDOMHelper().appendToRoot(this.state.announceContainer);
14358
14330
  };
14359
14331
  /**
14360
14332
  * Dispose this plugin
@@ -14548,20 +14520,23 @@ var SelectionPlugin = /** @class */ (function () {
14548
14520
  }
14549
14521
  };
14550
14522
  this.onSelectionChange = function () {
14551
- var _a;
14523
+ var _a, _b;
14552
14524
  if (((_a = _this.editor) === null || _a === void 0 ? void 0 : _a.hasFocus()) && !_this.editor.isInShadowEdit()) {
14553
14525
  var newSelection = _this.editor.getDOMSelection();
14526
+ var domHelper = _this.editor.getDOMHelper();
14554
14527
  //If am image selection changed to a wider range due a keyboard event, we should update the selection
14555
- var selection = _this.editor.getDocument().getSelection();
14556
- if (selection && selection.focusNode) {
14557
- var image = (0, isSingleImageInSelection_1.isSingleImageInSelection)(selection);
14528
+ var range = domHelper.getSelectionRange();
14529
+ if (range) {
14530
+ var image = (0, isSingleImageInSelection_1.isSingleImageInSelection)(range);
14558
14531
  if ((newSelection === null || newSelection === void 0 ? void 0 : newSelection.type) == 'image' && !image) {
14559
- var range = selection.getRangeAt(0);
14532
+ var sel = (_b = _this.editor.getDocument().defaultView) === null || _b === void 0 ? void 0 : _b.getSelection();
14533
+ var isReverted = sel
14534
+ ? sel.focusNode != range.endContainer || sel.focusOffset != range.endOffset
14535
+ : false;
14560
14536
  _this.editor.setDOMSelection({
14561
14537
  type: 'range',
14562
14538
  range: range,
14563
- isReverted: selection.focusNode != range.endContainer ||
14564
- selection.focusOffset != range.endOffset,
14539
+ isReverted: isReverted,
14565
14540
  });
14566
14541
  }
14567
14542
  else if ((newSelection === null || newSelection === void 0 ? void 0 : newSelection.type) !== 'image' && image) {
@@ -15950,10 +15925,23 @@ exports.Editor = Editor;
15950
15925
 
15951
15926
  Object.defineProperty(exports, "__esModule", ({ value: true }));
15952
15927
  exports.createDOMHelper = void 0;
15928
+ var areSameRanges_1 = __webpack_require__(/*! ../../utils/areSameRanges */ "./packages/roosterjs-content-model-core/lib/utils/areSameRanges.ts");
15953
15929
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
15930
+ function isSelectionWithComposedRanges(sel) {
15931
+ return 'getComposedRanges' in sel;
15932
+ }
15933
+ function isShadowRoot(node) {
15934
+ return 'host' in node;
15935
+ }
15954
15936
  var DOMHelperImpl = /** @class */ (function () {
15955
15937
  function DOMHelperImpl(contentDiv, options) {
15938
+ var _a;
15956
15939
  this.contentDiv = contentDiv;
15940
+ var rootNode = contentDiv.getRootNode();
15941
+ this.shadowRoot = (options === null || options === void 0 ? void 0 : options.useShadowDom) && isShadowRoot(rootNode) ? rootNode : null;
15942
+ this.doc = contentDiv.ownerDocument;
15943
+ var sel = (_a = this.doc.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
15944
+ this.useComposedRanges = !!(this.shadowRoot && sel && 'getComposedRanges' in sel);
15957
15945
  }
15958
15946
  DOMHelperImpl.prototype.queryElements = function (selector) {
15959
15947
  return (0, roosterjs_content_model_dom_1.toArray)(this.contentDiv.querySelectorAll(selector));
@@ -16015,7 +16003,9 @@ var DOMHelperImpl = /** @class */ (function () {
16015
16003
  return this.contentDiv;
16016
16004
  };
16017
16005
  DOMHelperImpl.prototype.hasFocus = function () {
16018
- var activeElement = this.contentDiv.ownerDocument.activeElement;
16006
+ var activeElement = this.shadowRoot
16007
+ ? this.shadowRoot.activeElement
16008
+ : this.doc.activeElement;
16019
16009
  return !!(activeElement && this.contentDiv.contains(activeElement));
16020
16010
  };
16021
16011
  /**
@@ -16082,6 +16072,51 @@ var DOMHelperImpl = /** @class */ (function () {
16082
16072
  DOMHelperImpl.prototype.getRangesByText = function (text, matchCase, wholeWord) {
16083
16073
  return (0, roosterjs_content_model_dom_1.getRangesByText)(this.contentDiv, text, matchCase, wholeWord, true /*editableOnly*/);
16084
16074
  };
16075
+ DOMHelperImpl.prototype.getSelectionRange = function () {
16076
+ var _a;
16077
+ var sel = (_a = this.doc.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
16078
+ if (!sel) {
16079
+ return null;
16080
+ }
16081
+ if (this.useComposedRanges && this.shadowRoot && isSelectionWithComposedRanges(sel)) {
16082
+ var staticRanges = sel.getComposedRanges({
16083
+ shadowRoots: [this.shadowRoot],
16084
+ });
16085
+ if ((staticRanges === null || staticRanges === void 0 ? void 0 : staticRanges.length) > 0) {
16086
+ var sr = staticRanges[0];
16087
+ var range = this.doc.createRange();
16088
+ range.setStart(sr.startContainer, sr.startOffset);
16089
+ range.setEnd(sr.endContainer, sr.endOffset);
16090
+ return range;
16091
+ }
16092
+ return null;
16093
+ }
16094
+ return sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
16095
+ };
16096
+ DOMHelperImpl.prototype.setSelectionRange = function (range, isReverted) {
16097
+ var _a;
16098
+ if (isReverted === void 0) { isReverted = false; }
16099
+ var sel = (_a = this.doc.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
16100
+ var currentRange = this.getSelectionRange();
16101
+ if (!sel || (currentRange && (0, areSameRanges_1.areSameRanges)(range, currentRange))) {
16102
+ return;
16103
+ }
16104
+ var startContainer = range.startContainer, startOffset = range.startOffset, endContainer = range.endContainer, endOffset = range.endOffset;
16105
+ if (!isReverted) {
16106
+ sel.setBaseAndExtent(startContainer, startOffset, endContainer, endOffset);
16107
+ }
16108
+ else {
16109
+ sel.setBaseAndExtent(endContainer, endOffset, startContainer, startOffset);
16110
+ }
16111
+ };
16112
+ DOMHelperImpl.prototype.appendToRoot = function (element) {
16113
+ if (this.shadowRoot) {
16114
+ this.shadowRoot.appendChild(element);
16115
+ }
16116
+ else {
16117
+ this.doc.body.appendChild(element);
16118
+ }
16119
+ };
16085
16120
  return DOMHelperImpl;
16086
16121
  }());
16087
16122
  /**
@@ -16198,7 +16233,10 @@ function createEditorCore(contentDiv, options) {
16198
16233
  corePlugins.lifecycle,
16199
16234
  ], false), environment: createEditorEnvironment(contentDiv, options), darkColorHandler: (0, DarkColorHandlerImpl_1.createDarkColorHandler)(contentDiv, (_b = options.getDarkColor) !== null && _b !== void 0 ? _b : getDarkColorFallback, options.knownColors, options.generateColorKey), trustedHTMLHandler: options.trustedHTMLHandler && !(0, domCreator_1.isDOMCreator)(options.trustedHTMLHandler)
16200
16235
  ? options.trustedHTMLHandler
16201
- : (0, domCreator_1.createTrustedHTMLHandler)(domCreator), domCreator: domCreator, domHelper: (0, DOMHelperImpl_1.createDOMHelper)(contentDiv) }, getPluginState(corePlugins)), { disposeErrorHandler: options.disposeErrorHandler, onFixUpModel: options.onFixUpModel, experimentalFeatures: options.experimentalFeatures ? (0, tslib_1.__spreadArray)([], (0, tslib_1.__read)(options.experimentalFeatures), false) : [] });
16236
+ : (0, domCreator_1.createTrustedHTMLHandler)(domCreator), domCreator: domCreator, domHelper: (0, DOMHelperImpl_1.createDOMHelper)(contentDiv, {
16237
+ useShadowDom: !!options.experimentalFeatures &&
16238
+ options.experimentalFeatures.indexOf('ShadowDom') >= 0,
16239
+ }) }, getPluginState(corePlugins)), { disposeErrorHandler: options.disposeErrorHandler, onFixUpModel: options.onFixUpModel, experimentalFeatures: options.experimentalFeatures ? (0, tslib_1.__spreadArray)([], (0, tslib_1.__read)(options.experimentalFeatures), false) : [] });
16202
16240
  }
16203
16241
  exports.createEditorCore = createEditorCore;
16204
16242
  function createEditorEnvironment(contentDiv, options) {
@@ -16356,6 +16394,8 @@ var containerSizeFormatParser = function (format, element) {
16356
16394
  if (element.tagName == 'DIV' || element.tagName == 'P') {
16357
16395
  delete format.width;
16358
16396
  delete format.height;
16397
+ delete format.maxHeight;
16398
+ delete format.maxWidth;
16359
16399
  }
16360
16400
  };
16361
16401
  exports.containerSizeFormatParser = containerSizeFormatParser;
@@ -16652,6 +16692,29 @@ var pasteWhiteSpaceFormatParser = function (format, element, context, defaultSty
16652
16692
  exports.pasteWhiteSpaceFormatParser = pasteWhiteSpaceFormatParser;
16653
16693
 
16654
16694
 
16695
+ /***/ },
16696
+
16697
+ /***/ "./packages/roosterjs-content-model-core/lib/utils/areSameRanges.ts"
16698
+ /*!**************************************************************************!*\
16699
+ !*** ./packages/roosterjs-content-model-core/lib/utils/areSameRanges.ts ***!
16700
+ \**************************************************************************/
16701
+ (__unused_webpack_module, exports) {
16702
+
16703
+ "use strict";
16704
+
16705
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
16706
+ exports.areSameRanges = void 0;
16707
+ var RangeKeys = ['startContainer', 'endContainer', 'startOffset', 'endOffset'];
16708
+ /**
16709
+ * @internal
16710
+ * Check if two ranges have the same start and end positions.
16711
+ */
16712
+ function areSameRanges(r1, r2) {
16713
+ return RangeKeys.every(function (k) { return r1[k] == r2[k]; });
16714
+ }
16715
+ exports.areSameRanges = areSameRanges;
16716
+
16717
+
16655
16718
  /***/ },
16656
16719
 
16657
16720
  /***/ "./packages/roosterjs-content-model-core/lib/utils/createAriaLiveElement.ts"
@@ -16677,7 +16740,6 @@ function createAriaLiveElement(document) {
16677
16740
  div.style.whiteSpace = 'nowrap';
16678
16741
  div.style.width = '1px';
16679
16742
  div.ariaLive = 'assertive';
16680
- document.body.appendChild(div);
16681
16743
  return div;
16682
16744
  }
16683
16745
  exports.createAriaLiveElement = createAriaLiveElement;
@@ -21168,11 +21230,13 @@ exports.directionFormatHandler = {
21168
21230
  format.direction = dir == 'rtl' ? 'rtl' : 'ltr';
21169
21231
  }
21170
21232
  },
21171
- apply: function (format, element) {
21233
+ apply: function (format, element, context) {
21172
21234
  if (format.direction) {
21173
21235
  element.style.direction = format.direction;
21174
21236
  }
21175
- if (format.direction == 'rtl' && (0, isElementOfType_1.isElementOfType)(element, 'table')) {
21237
+ if (format.direction == 'rtl' &&
21238
+ (0, isElementOfType_1.isElementOfType)(element, 'table') &&
21239
+ context.implicitFormat.direction != 'rtl') {
21176
21240
  element.style.justifySelf = 'flex-end';
21177
21241
  }
21178
21242
  },
@@ -21709,6 +21773,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
21709
21773
  exports.borderFormatHandler = void 0;
21710
21774
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
21711
21775
  var borderKeys_1 = __webpack_require__(/*! ../utils/borderKeys */ "./packages/roosterjs-content-model-dom/lib/formatHandlers/utils/borderKeys.ts");
21776
+ var borderValues_1 = __webpack_require__(/*! ../../domUtils/style/borderValues */ "./packages/roosterjs-content-model-dom/lib/domUtils/style/borderValues.ts");
21712
21777
  // This array needs to match BorderKeys array
21713
21778
  var BorderWidthKeys = [
21714
21779
  'borderTopWidth',
@@ -21737,7 +21802,17 @@ exports.borderFormatHandler = {
21737
21802
  width = '0px';
21738
21803
  }
21739
21804
  if (value && width != defaultWidth) {
21740
- format[key] = value == 'none' ? '' : value;
21805
+ var result = value;
21806
+ if (result.includes('initial')) {
21807
+ // Remove 'initial' from the last part (color) of the border value
21808
+ // since browsers ignore it when setting the inline style property
21809
+ var border = (0, borderValues_1.extractBorderValues)(value);
21810
+ if (border.color === 'initial') {
21811
+ border.color = '';
21812
+ }
21813
+ result = (0, borderValues_1.combineBorderValue)(border);
21814
+ }
21815
+ format[key] = result == 'none' ? '' : result;
21741
21816
  }
21742
21817
  });
21743
21818
  var borderRadius = element.style.borderRadius;
@@ -24139,6 +24214,7 @@ var createText_1 = __webpack_require__(/*! ../creators/createText */ "./packages
24139
24214
  var ensureParagraph_1 = __webpack_require__(/*! ./ensureParagraph */ "./packages/roosterjs-content-model-dom/lib/modelApi/common/ensureParagraph.ts");
24140
24215
  var hasSpacesOnly_1 = __webpack_require__(/*! ./hasSpacesOnly */ "./packages/roosterjs-content-model-dom/lib/modelApi/common/hasSpacesOnly.ts");
24141
24216
  var isWhiteSpacePreserved_1 = __webpack_require__(/*! ../../domUtils/isWhiteSpacePreserved */ "./packages/roosterjs-content-model-dom/lib/domUtils/isWhiteSpacePreserved.ts");
24217
+ var stripInvisibleUnicode_1 = __webpack_require__(/*! ./stripInvisibleUnicode */ "./packages/roosterjs-content-model-dom/lib/modelApi/common/stripInvisibleUnicode.ts");
24142
24218
  /**
24143
24219
  * Add a new text segment to current paragraph
24144
24220
  * @param group Current BlockGroup that the paragraph belong to
@@ -24154,7 +24230,11 @@ function addTextSegment(group, text, context) {
24154
24230
  if (!(0, hasSpacesOnly_1.hasSpacesOnly)(text) ||
24155
24231
  ((_a = paragraph === null || paragraph === void 0 ? void 0 : paragraph.segments.length) !== null && _a !== void 0 ? _a : 0) > 0 ||
24156
24232
  (0, isWhiteSpacePreserved_1.isWhiteSpacePreserved)(paragraph === null || paragraph === void 0 ? void 0 : paragraph.format.whiteSpace)) {
24157
- textModel = (0, createText_1.createText)(text, context.segmentFormat);
24233
+ var filteredText = context.experimentalFeatures &&
24234
+ context.experimentalFeatures.indexOf('FilterInvisibleUnicode') > -1
24235
+ ? (0, stripInvisibleUnicode_1.stripInvisibleUnicode)(text)
24236
+ : text;
24237
+ textModel = (0, createText_1.createText)(filteredText, context.segmentFormat);
24158
24238
  if (context.isInSelection) {
24159
24239
  textModel.isSelected = true;
24160
24240
  }
@@ -24789,6 +24869,34 @@ function normalizeSegmentFormat(format, environment) {
24789
24869
  exports.normalizeSegmentFormat = normalizeSegmentFormat;
24790
24870
 
24791
24871
 
24872
+ /***/ },
24873
+
24874
+ /***/ "./packages/roosterjs-content-model-dom/lib/modelApi/common/stripInvisibleUnicode.ts"
24875
+ /*!*******************************************************************************************!*\
24876
+ !*** ./packages/roosterjs-content-model-dom/lib/modelApi/common/stripInvisibleUnicode.ts ***!
24877
+ \*******************************************************************************************/
24878
+ (__unused_webpack_module, exports) {
24879
+
24880
+ "use strict";
24881
+
24882
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
24883
+ exports.stripInvisibleUnicode = void 0;
24884
+ // According to https://embracethered.com/blog/posts/2024/hiding-and-finding-text-with-unicode-tags/
24885
+ // there are some invisible unicode characters in the range of U+E0000 to U+EFFFF, which are used for hiding text in HTML.
24886
+ // We need to strip them out before processing the pasted content, otherwise they will be treated as normal text and cause unexpected behavior.
24887
+ var INVISIBLE_UNICODE_REGEX = /[\u{E0000}-\u{EFFFF}]/gu;
24888
+ /**
24889
+ * @internal
24890
+ * Strip invisible unicode characters from the given string
24891
+ * @param value The string to be processed
24892
+ * @returns The string with invisible unicode characters removed
24893
+ */
24894
+ function stripInvisibleUnicode(value) {
24895
+ return value.replace(INVISIBLE_UNICODE_REGEX, '');
24896
+ }
24897
+ exports.stripInvisibleUnicode = stripInvisibleUnicode;
24898
+
24899
+
24792
24900
  /***/ },
24793
24901
 
24794
24902
  /***/ "./packages/roosterjs-content-model-dom/lib/modelApi/common/unwrapBlock.ts"
@@ -25247,16 +25355,25 @@ exports.createParagraphDecorator = createParagraphDecorator;
25247
25355
 
25248
25356
  Object.defineProperty(exports, "__esModule", ({ value: true }));
25249
25357
  exports.createSelectionMarker = void 0;
25250
- var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
25358
+ var EmptySegmentFormat_1 = __webpack_require__(/*! ../../constants/EmptySegmentFormat */ "./packages/roosterjs-content-model-dom/lib/constants/EmptySegmentFormat.ts");
25359
+ var getObjectKeys_1 = __webpack_require__(/*! ../../domUtils/getObjectKeys */ "./packages/roosterjs-content-model-dom/lib/domUtils/getObjectKeys.ts");
25251
25360
  /**
25252
25361
  * Create a ContentModelSelectionMarker model
25253
25362
  * @param format @optional The format of this model
25254
25363
  */
25255
25364
  function createSelectionMarker(format) {
25365
+ var filteredFormat = {};
25366
+ if (format) {
25367
+ (0, getObjectKeys_1.getObjectKeys)(EmptySegmentFormat_1.EmptySegmentFormat).forEach(function (key) {
25368
+ if (key in format) {
25369
+ filteredFormat[key] = format[key];
25370
+ }
25371
+ });
25372
+ }
25256
25373
  return {
25257
25374
  segmentType: 'SelectionMarker',
25258
25375
  isSelected: true,
25259
- format: (0, tslib_1.__assign)({}, format),
25376
+ format: filteredFormat,
25260
25377
  };
25261
25378
  }
25262
25379
  exports.createSelectionMarker = createSelectionMarker;
@@ -29331,14 +29448,16 @@ var handleFormatContainer = function (doc, parent, container, context, refNode)
29331
29448
  (0, applyFormat_1.applyFormat)(containerNode_1, context.formatAppliers.segmentOnBlock, container.format, context);
29332
29449
  (0, applyFormat_1.applyFormat)(containerNode_1, context.formatAppliers.container, container.format, context);
29333
29450
  });
29334
- if (container.tagName == 'pre') {
29335
- (0, stackFormat_1.stackFormat)(context, PreChildFormat, function () {
29451
+ (0, stackFormat_1.stackFormat)(context, container.format.direction ? { direction: container.format.direction } : null, function () {
29452
+ if (container.tagName == 'pre') {
29453
+ (0, stackFormat_1.stackFormat)(context, PreChildFormat, function () {
29454
+ context.modelHandlers.blockGroupChildren(doc, containerNode_1, container, context);
29455
+ });
29456
+ }
29457
+ else {
29336
29458
  context.modelHandlers.blockGroupChildren(doc, containerNode_1, container, context);
29337
- });
29338
- }
29339
- else {
29340
- context.modelHandlers.blockGroupChildren(doc, containerNode_1, container, context);
29341
- }
29459
+ }
29460
+ });
29342
29461
  element = containerNode_1;
29343
29462
  }
29344
29463
  if (element) {
@@ -29628,7 +29747,9 @@ var handleListItem = function (doc, parent, listItem, context, refNode) {
29628
29747
  // Need to apply listItemElement formats after applying metadata since the list numbers value relies on the result of metadata handling
29629
29748
  (0, applyFormat_1.applyFormat)(li, context.formatAppliers.listItemElement, listItem.format, context);
29630
29749
  (0, stackFormat_1.stackFormat)(context, listItem.formatHolder.format, function () {
29631
- context.modelHandlers.blockGroupChildren(doc, li, listItem, context);
29750
+ (0, stackFormat_1.stackFormat)(context, listItem.format.direction ? { direction: listItem.format.direction } : null, function () {
29751
+ context.modelHandlers.blockGroupChildren(doc, li, listItem, context);
29752
+ });
29632
29753
  });
29633
29754
  }
29634
29755
  else {
@@ -30000,7 +30121,9 @@ var handleTable = function (doc, parent, table, context, refNode) {
30000
30121
  (0, applyFormat_1.applyFormat)(td_1, context.formatAppliers.tableCellBorder, cell.format, context);
30001
30122
  (0, applyFormat_1.applyFormat)(td_1, context.formatAppliers.dataset, cell.dataset, context);
30002
30123
  }
30003
- context.modelHandlers.blockGroupChildren(doc, td_1, cell, context);
30124
+ (0, stackFormat_1.stackFormat)(context, cell.format.direction ? { direction: cell.format.direction } : null, function () {
30125
+ context.modelHandlers.blockGroupChildren(doc, td_1, cell, context);
30126
+ });
30004
30127
  });
30005
30128
  (_f = context.onNodeCreated) === null || _f === void 0 ? void 0 : _f.call(context, cell, td_1);
30006
30129
  }
@@ -30526,35 +30649,6 @@ var convertContentModelToMarkdown_1 = __webpack_require__(/*! ./modelToMarkdown/
30526
30649
  Object.defineProperty(exports, "convertContentModelToMarkdown", ({ enumerable: true, get: function () { return convertContentModelToMarkdown_1.convertContentModelToMarkdown; } }));
30527
30650
 
30528
30651
 
30529
- /***/ },
30530
-
30531
- /***/ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/appliers/applyLink.ts"
30532
- /*!*********************************************************************************************!*\
30533
- !*** ./packages/roosterjs-content-model-markdown/lib/markdownToModel/appliers/applyLink.ts ***!
30534
- \*********************************************************************************************/
30535
- (__unused_webpack_module, exports) {
30536
-
30537
- "use strict";
30538
-
30539
- Object.defineProperty(exports, "__esModule", ({ value: true }));
30540
- exports.applyLink = void 0;
30541
- /**
30542
- * @internal
30543
- */
30544
- function applyLink(textSegment, text, url) {
30545
- textSegment.text = text;
30546
- textSegment.link = {
30547
- dataset: {},
30548
- format: {
30549
- href: url,
30550
- underline: true,
30551
- },
30552
- };
30553
- return textSegment;
30554
- }
30555
- exports.applyLink = applyLink;
30556
-
30557
-
30558
30652
  /***/ },
30559
30653
 
30560
30654
  /***/ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/appliers/applySegmentFormatting.ts"
@@ -30569,46 +30663,39 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
30569
30663
  exports.applySegmentFormatting = void 0;
30570
30664
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
30571
30665
  var adjustHeading_1 = __webpack_require__(/*! ../utils/adjustHeading */ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/utils/adjustHeading.ts");
30572
- var applyLink_1 = __webpack_require__(/*! ./applyLink */ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/appliers/applyLink.ts");
30573
- var applyTextFormatting_1 = __webpack_require__(/*! ./applyTextFormatting */ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/appliers/applyTextFormatting.ts");
30574
30666
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
30575
- var createImageSegment_1 = __webpack_require__(/*! ../creators/createImageSegment */ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/creators/createImageSegment.ts");
30576
- var splitParagraphSegments_1 = __webpack_require__(/*! ../utils/splitParagraphSegments */ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/utils/splitParagraphSegments.ts");
30667
+ var parseInlineSegments_1 = __webpack_require__(/*! ../utils/parseInlineSegments */ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/utils/parseInlineSegments.ts");
30577
30668
  /**
30578
30669
  * @internal
30579
30670
  */
30580
30671
  function applySegmentFormatting(text, paragraph, decorator) {
30581
- var e_1, _a, _b;
30672
+ var e_1, _a;
30582
30673
  if (text.length === 0) {
30583
30674
  var br = (0, roosterjs_content_model_dom_1.createBr)();
30584
30675
  paragraph.segments.push(br);
30585
30676
  }
30586
30677
  else {
30587
- var textSegments = (0, splitParagraphSegments_1.splitParagraphSegments)(text);
30678
+ var segments = [];
30679
+ (0, parseInlineSegments_1.parseInlineSegments)(text, segments);
30680
+ // Apply heading adjustment to the first text-bearing segment, if any.
30681
+ var headingAdjusted = false;
30588
30682
  try {
30589
- for (var textSegments_1 = (0, tslib_1.__values)(textSegments), textSegments_1_1 = textSegments_1.next(); !textSegments_1_1.done; textSegments_1_1 = textSegments_1.next()) {
30590
- var segment = textSegments_1_1.value;
30591
- var formattedSegment = (0, roosterjs_content_model_dom_1.createText)(segment.text);
30592
- if (segment.type === 'image') {
30593
- var image = (0, createImageSegment_1.createImageSegment)(segment.text, segment.url);
30594
- paragraph.segments.push(image);
30595
- }
30596
- else {
30597
- if (segment.type === 'link') {
30598
- (0, applyLink_1.applyLink)(formattedSegment, segment.text, segment.url);
30599
- }
30600
- var segmentWithAdjustedHeading = (0, adjustHeading_1.adjustHeading)(formattedSegment, decorator);
30601
- if (segmentWithAdjustedHeading) {
30602
- var formattedSegments = (0, applyTextFormatting_1.applyTextFormatting)(formattedSegment);
30603
- (_b = paragraph.segments).push.apply(_b, (0, tslib_1.__spreadArray)([], (0, tslib_1.__read)(formattedSegments), false));
30683
+ for (var segments_1 = (0, tslib_1.__values)(segments), segments_1_1 = segments_1.next(); !segments_1_1.done; segments_1_1 = segments_1.next()) {
30684
+ var segment = segments_1_1.value;
30685
+ if (!headingAdjusted && segment.segmentType === 'Text') {
30686
+ var adjusted = (0, adjustHeading_1.adjustHeading)(segment, decorator);
30687
+ headingAdjusted = true;
30688
+ if (!adjusted) {
30689
+ continue;
30604
30690
  }
30605
30691
  }
30692
+ paragraph.segments.push(segment);
30606
30693
  }
30607
30694
  }
30608
30695
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
30609
30696
  finally {
30610
30697
  try {
30611
- if (textSegments_1_1 && !textSegments_1_1.done && (_a = textSegments_1.return)) _a.call(textSegments_1);
30698
+ if (segments_1_1 && !segments_1_1.done && (_a = segments_1.return)) _a.call(segments_1);
30612
30699
  }
30613
30700
  finally { if (e_1) throw e_1.error; }
30614
30701
  }
@@ -30618,148 +30705,6 @@ function applySegmentFormatting(text, paragraph, decorator) {
30618
30705
  exports.applySegmentFormatting = applySegmentFormatting;
30619
30706
 
30620
30707
 
30621
- /***/ },
30622
-
30623
- /***/ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/appliers/applyTextFormatting.ts"
30624
- /*!*******************************************************************************************************!*\
30625
- !*** ./packages/roosterjs-content-model-markdown/lib/markdownToModel/appliers/applyTextFormatting.ts ***!
30626
- \*******************************************************************************************************/
30627
- (__unused_webpack_module, exports, __webpack_require__) {
30628
-
30629
- "use strict";
30630
-
30631
- Object.defineProperty(exports, "__esModule", ({ value: true }));
30632
- exports.applyTextFormatting = void 0;
30633
- var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
30634
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
30635
- /**
30636
- * @internal
30637
- */
30638
- function applyTextFormatting(textSegment) {
30639
- var text = textSegment.text;
30640
- // Quick check: if the text contains only formatting markers, return original
30641
- if (isOnlyFormattingMarkers(text)) {
30642
- return [textSegment];
30643
- }
30644
- var textSegments = [];
30645
- var currentState = { bold: false, italic: false, strikethrough: false };
30646
- var currentText = '';
30647
- var i = 0;
30648
- while (i < text.length) {
30649
- var marker = parseMarkerAt(text, i);
30650
- if (marker) {
30651
- // Check if this marker should be treated as formatting or as literal text
30652
- if (shouldToggleFormatting(text, i, marker, currentState)) {
30653
- // If we have accumulated text, create a segment for it
30654
- if (currentText.length > 0) {
30655
- textSegments.push(createFormattedSegment(currentText, textSegment.format, currentState, textSegment.link));
30656
- currentText = '';
30657
- }
30658
- // Toggle the formatting state
30659
- toggleFormatting(currentState, marker.type);
30660
- // Skip the marker characters
30661
- i += marker.length;
30662
- }
30663
- else {
30664
- // Treat as regular text if marker is not valid in this context
30665
- currentText += text[i];
30666
- i++;
30667
- }
30668
- }
30669
- else {
30670
- // Regular character, add to current text
30671
- currentText += text[i];
30672
- i++;
30673
- }
30674
- }
30675
- // Add any remaining text as a final segment
30676
- if (currentText.length > 0) {
30677
- textSegments.push(createFormattedSegment(currentText, textSegment.format, currentState, textSegment.link));
30678
- }
30679
- // If no meaningful formatting was applied, return the original segment
30680
- if (textSegments.length === 0 ||
30681
- (textSegments.length === 1 && textSegments[0].text === textSegment.text)) {
30682
- return [textSegment];
30683
- }
30684
- return textSegments;
30685
- }
30686
- exports.applyTextFormatting = applyTextFormatting;
30687
- function isOnlyFormattingMarkers(text) {
30688
- // Remove all potential formatting markers and see if anything remains
30689
- var remaining = text;
30690
- remaining = remaining.replace(/\*\*/g, ''); // Remove **
30691
- remaining = remaining.replace(/~~/g, ''); // Remove ~~
30692
- remaining = remaining.replace(/\*/g, ''); // Remove *
30693
- // If nothing remains after removing all markers, it was only markers
30694
- return remaining.length === 0;
30695
- }
30696
- function parseMarkerAt(text, index) {
30697
- var remaining = text.substring(index);
30698
- if (remaining.startsWith('~~')) {
30699
- return { type: 'strikethrough', length: 2 };
30700
- }
30701
- if (remaining.startsWith('**')) {
30702
- return { type: 'bold', length: 2 };
30703
- }
30704
- if (remaining.startsWith('*')) {
30705
- return { type: 'italic', length: 1 };
30706
- }
30707
- return null;
30708
- }
30709
- function shouldToggleFormatting(text, index, marker, currentState) {
30710
- var nextChar = index + marker.length < text.length ? text.charAt(index + marker.length) : '';
30711
- var isCurrentlyActive = getCurrentFormatState(currentState, marker.type);
30712
- if (isCurrentlyActive) {
30713
- // We're currently in this format, so any marker can close it
30714
- return true;
30715
- }
30716
- else {
30717
- // We're not in this format, so this marker would open it
30718
- // Opening markers must be followed by non-whitespace
30719
- return nextChar.length > 0 && !isWhitespace(nextChar);
30720
- }
30721
- }
30722
- function isWhitespace(char) {
30723
- return /\s/.test(char);
30724
- }
30725
- function toggleFormatting(state, type) {
30726
- switch (type) {
30727
- case 'bold':
30728
- state.bold = !state.bold;
30729
- break;
30730
- case 'italic':
30731
- state.italic = !state.italic;
30732
- break;
30733
- case 'strikethrough':
30734
- state.strikethrough = !state.strikethrough;
30735
- break;
30736
- }
30737
- }
30738
- function getCurrentFormatState(state, type) {
30739
- switch (type) {
30740
- case 'bold':
30741
- return state.bold;
30742
- case 'italic':
30743
- return state.italic;
30744
- case 'strikethrough':
30745
- return state.strikethrough;
30746
- }
30747
- }
30748
- function createFormattedSegment(text, baseFormat, state, link) {
30749
- var format = (0, tslib_1.__assign)({}, baseFormat);
30750
- if (state.bold) {
30751
- format.fontWeight = 'bold';
30752
- }
30753
- if (state.italic) {
30754
- format.italic = true;
30755
- }
30756
- if (state.strikethrough) {
30757
- format.strikethrough = true;
30758
- }
30759
- return (0, roosterjs_content_model_dom_1.createText)(text, format, link);
30760
- }
30761
-
30762
-
30763
30708
  /***/ },
30764
30709
 
30765
30710
  /***/ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/convertMarkdownToContentModel.ts"
@@ -31357,29 +31302,143 @@ exports.isMarkdownTable = isMarkdownTable;
31357
31302
 
31358
31303
  /***/ },
31359
31304
 
31360
- /***/ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/utils/splitParagraphSegments.ts"
31361
- /*!*******************************************************************************************************!*\
31362
- !*** ./packages/roosterjs-content-model-markdown/lib/markdownToModel/utils/splitParagraphSegments.ts ***!
31363
- \*******************************************************************************************************/
31364
- (__unused_webpack_module, exports) {
31305
+ /***/ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/utils/parseInlineSegments.ts"
31306
+ /*!****************************************************************************************************!*\
31307
+ !*** ./packages/roosterjs-content-model-markdown/lib/markdownToModel/utils/parseInlineSegments.ts ***!
31308
+ \****************************************************************************************************/
31309
+ (__unused_webpack_module, exports, __webpack_require__) {
31365
31310
 
31366
31311
  "use strict";
31367
31312
 
31368
31313
  Object.defineProperty(exports, "__esModule", ({ value: true }));
31369
- exports.splitParagraphSegments = void 0;
31370
- // Matches markdown links and images in a string.
31371
- // Group 1 (full link): [text](url) e.g. [Click here](https://example.com)
31372
- // Group 2: link text e.g. "Click here"
31373
- // Group 3: link url e.g. "https://example.com"
31374
- // Group 4 (full image): ![alt](url) e.g. ![Logo](https://example.com/logo.png)
31375
- // Group 5: alt text e.g. "Logo"
31376
- // Group 6: image url e.g. "https://example.com/logo.png"
31377
- var linkRegex = /(\[([^\[]+)\]\(([^\)]+)\))|(\!\[([^\[]+)\]\(([^\)]+)\))/g;
31378
- var isValidUrl = function (url) {
31314
+ exports.parseInlineSegments = void 0;
31315
+ var createImageSegment_1 = __webpack_require__(/*! ../creators/createImageSegment */ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/creators/createImageSegment.ts");
31316
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
31317
+ // Matches a markdown link [text](url) anchored at the start of the input.
31318
+ var linkPattern = /^\[([^\[\]]+)\]\(([^\)]+)\)/;
31319
+ // Matches a markdown image ![alt](url) anchored at the start of the input.
31320
+ var imagePattern = /^!\[([^\[\]]+)\]\(([^\)]+)\)/;
31321
+ /**
31322
+ * @internal
31323
+ * Parse a markdown inline string into Content Model segments. Supports bold/italic/
31324
+ * strikethrough markers, links, and images, and keeps formatting state active across
31325
+ * link boundaries (e.g. **[link](url)**).
31326
+ */
31327
+ function parseInlineSegments(text, segments, state, link) {
31328
+ if (state === void 0) { state = { bold: false, italic: false, strikethrough: false }; }
31329
+ var buffer = '';
31330
+ var i = 0;
31331
+ var flushBuffer = function () {
31332
+ if (buffer.length > 0) {
31333
+ segments.push(createFormattedSegment(buffer, state, link));
31334
+ buffer = '';
31335
+ }
31336
+ };
31337
+ while (i < text.length) {
31338
+ var remaining = text.substring(i);
31339
+ // Image: ![alt](url)
31340
+ var imgMatch = imagePattern.exec(remaining);
31341
+ if (imgMatch && isValidUrl(imgMatch[2])) {
31342
+ flushBuffer();
31343
+ segments.push((0, createImageSegment_1.createImageSegment)(imgMatch[1], imgMatch[2]));
31344
+ i += imgMatch[0].length;
31345
+ continue;
31346
+ }
31347
+ // Link: [text](url) — keep outer formatting state active inside the link
31348
+ var linkMatch = linkPattern.exec(remaining);
31349
+ if (linkMatch && isValidUrl(linkMatch[2])) {
31350
+ flushBuffer();
31351
+ var innerLink = {
31352
+ dataset: {},
31353
+ format: { href: linkMatch[2], underline: true },
31354
+ };
31355
+ parseInlineSegments(linkMatch[1], segments, state, innerLink);
31356
+ i += linkMatch[0].length;
31357
+ continue;
31358
+ }
31359
+ // Formatting marker
31360
+ var marker = parseMarkerAt(text, i);
31361
+ if (marker && shouldToggleFormatting(text, i, marker, state)) {
31362
+ flushBuffer();
31363
+ toggleFormatting(state, marker.type);
31364
+ i += marker.length;
31365
+ continue;
31366
+ }
31367
+ buffer += text[i];
31368
+ i++;
31369
+ }
31370
+ flushBuffer();
31371
+ }
31372
+ exports.parseInlineSegments = parseInlineSegments;
31373
+ function parseMarkerAt(text, index) {
31374
+ var remaining = text.substring(index);
31375
+ if (remaining.startsWith('~~')) {
31376
+ return { type: 'strikethrough', length: 2 };
31377
+ }
31378
+ if (remaining.startsWith('**')) {
31379
+ return { type: 'bold', length: 2 };
31380
+ }
31381
+ if (remaining.startsWith('*')) {
31382
+ return { type: 'italic', length: 1 };
31383
+ }
31384
+ return null;
31385
+ }
31386
+ function shouldToggleFormatting(text, index, marker, currentState) {
31387
+ var isCurrentlyActive = getCurrentFormatState(currentState, marker.type);
31388
+ if (isCurrentlyActive) {
31389
+ return true;
31390
+ }
31391
+ // Opening marker must be followed by a non-whitespace character.
31392
+ var nextIndex = index + marker.length;
31393
+ var nextChar = nextIndex < text.length ? text.charAt(nextIndex) : '';
31394
+ if (nextChar.length === 0 || isWhitespace(nextChar)) {
31395
+ return false;
31396
+ }
31397
+ return true;
31398
+ }
31399
+ function isWhitespace(char) {
31400
+ return /\s/.test(char);
31401
+ }
31402
+ function toggleFormatting(state, type) {
31403
+ switch (type) {
31404
+ case 'bold':
31405
+ state.bold = !state.bold;
31406
+ break;
31407
+ case 'italic':
31408
+ state.italic = !state.italic;
31409
+ break;
31410
+ case 'strikethrough':
31411
+ state.strikethrough = !state.strikethrough;
31412
+ break;
31413
+ }
31414
+ }
31415
+ function getCurrentFormatState(state, type) {
31416
+ switch (type) {
31417
+ case 'bold':
31418
+ return state.bold;
31419
+ case 'italic':
31420
+ return state.italic;
31421
+ case 'strikethrough':
31422
+ return state.strikethrough;
31423
+ }
31424
+ }
31425
+ function createFormattedSegment(text, state, link) {
31426
+ var format = {};
31427
+ if (state.bold) {
31428
+ format.fontWeight = 'bold';
31429
+ }
31430
+ if (state.italic) {
31431
+ format.italic = true;
31432
+ }
31433
+ if (state.strikethrough) {
31434
+ format.strikethrough = true;
31435
+ }
31436
+ return (0, roosterjs_content_model_dom_1.createText)(text, format, link);
31437
+ }
31438
+ function isValidUrl(url) {
31379
31439
  if (!url) {
31380
31440
  return false;
31381
31441
  }
31382
- // Accept common non-http schemes and relative paths
31383
31442
  if (url.startsWith('data:') ||
31384
31443
  url.startsWith('blob:') ||
31385
31444
  url.startsWith('/') ||
@@ -31394,51 +31453,7 @@ var isValidUrl = function (url) {
31394
31453
  catch (_) {
31395
31454
  return false;
31396
31455
  }
31397
- };
31398
- function pushText(result, text) {
31399
- var last = result[result.length - 1];
31400
- if (last && last.type === 'text') {
31401
- last.text += text;
31402
- }
31403
- else {
31404
- result.push({ type: 'text', text: text, url: '' });
31405
- }
31406
31456
  }
31407
- /**
31408
- * @internal
31409
- */
31410
- function splitParagraphSegments(text) {
31411
- var result = [];
31412
- var lastIndex = 0;
31413
- var match = null;
31414
- while ((match = linkRegex.exec(text)) !== null) {
31415
- if (match.index > lastIndex) {
31416
- pushText(result, text.slice(lastIndex, match.index));
31417
- }
31418
- if (match[2] && match[3]) {
31419
- if (isValidUrl(match[3])) {
31420
- result.push({ type: 'link', text: match[2], url: match[3] });
31421
- }
31422
- else {
31423
- pushText(result, match[0]);
31424
- }
31425
- }
31426
- else if (match[5] && match[6]) {
31427
- if (isValidUrl(match[6])) {
31428
- result.push({ type: 'image', text: match[5], url: match[6] });
31429
- }
31430
- else {
31431
- pushText(result, match[0]);
31432
- }
31433
- }
31434
- lastIndex = linkRegex.lastIndex;
31435
- }
31436
- if (lastIndex < text.length) {
31437
- pushText(result, text.slice(lastIndex));
31438
- }
31439
- return result;
31440
- }
31441
- exports.splitParagraphSegments = splitParagraphSegments;
31442
31457
 
31443
31458
 
31444
31459
  /***/ },
@@ -31699,20 +31714,30 @@ function createMarkdownParagraph(paragraph, context) {
31699
31714
  }
31700
31715
  exports.createMarkdownParagraph = createMarkdownParagraph;
31701
31716
  function textProcessor(text) {
31702
- var markdownString = text.text;
31703
- if (text.link) {
31704
- markdownString = "[" + text.text + "](" + text.link.format.href + ")";
31705
- }
31706
- if (text.format.fontWeight == 'bold') {
31707
- markdownString = "**" + markdownString + "**";
31708
- }
31709
- if (text.format.strikethrough) {
31710
- markdownString = "~~" + markdownString + "~~";
31717
+ var _a = text.format, fontWeight = _a.fontWeight, italic = _a.italic, strikethrough = _a.strikethrough;
31718
+ var hasInlineFormat = fontWeight == 'bold' || italic || strikethrough;
31719
+ if (!hasInlineFormat) {
31720
+ return text.link ? "[" + text.text + "](" + text.link.format.href + ")" : text.text;
31721
+ }
31722
+ // Move leading/trailing whitespace outside the markers so the emitted
31723
+ // markdown is valid (CommonMark requires emphasis markers to hug
31724
+ // non-whitespace), e.g. "world " with <b> => " " + "**world**".
31725
+ var match = /^(\s*)([\s\S]*?)(\s*)$/.exec(text.text);
31726
+ var _b = (0, tslib_1.__read)(match ? match : ['', '', text.text, ''], 4), leading = _b[1], core = _b[2], trailing = _b[3];
31727
+ if (!core) {
31728
+ return text.text;
31729
+ }
31730
+ var inner = text.link ? "[" + core + "](" + text.link.format.href + ")" : core;
31731
+ if (fontWeight == 'bold') {
31732
+ inner = "**" + inner + "**";
31733
+ }
31734
+ if (strikethrough) {
31735
+ inner = "~~" + inner + "~~";
31711
31736
  }
31712
- if (text.format.italic) {
31713
- markdownString = "*" + markdownString + "*";
31737
+ if (italic) {
31738
+ inner = "*" + inner + "*";
31714
31739
  }
31715
- return markdownString;
31740
+ return "" + leading + inner + trailing;
31716
31741
  }
31717
31742
 
31718
31743
 
@@ -33633,7 +33658,11 @@ var EditPlugin = /** @class */ (function () {
33633
33658
  if (!hasCtrlOrMetaKey &&
33634
33659
  !event.rawEvent.isComposing &&
33635
33660
  event.rawEvent.keyCode !== DEAD_KEY) {
33636
- (0, keyboardEnter_1.keyboardEnter)(editor, rawEvent, this.options.formatsToPreserveOnMerge);
33661
+ var shouldHandleEnterKey = this.options.shouldHandleEnterKey;
33662
+ var handleNormalEnter = typeof shouldHandleEnterKey === 'function'
33663
+ ? shouldHandleEnterKey(editor)
33664
+ : shouldHandleEnterKey !== false;
33665
+ (0, keyboardEnter_1.keyboardEnter)(editor, rawEvent, handleNormalEnter, this.options.formatsToPreserveOnMerge);
33637
33666
  }
33638
33667
  break;
33639
33668
  default:
@@ -34628,11 +34657,11 @@ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-mo
34628
34657
  /**
34629
34658
  * @internal
34630
34659
  */
34631
- function keyboardEnter(editor, rawEvent, formatsToPreserveOnMerge) {
34660
+ function keyboardEnter(editor, rawEvent, handleNormalEnter, formatsToPreserveOnMerge) {
34632
34661
  if (formatsToPreserveOnMerge === void 0) { formatsToPreserveOnMerge = []; }
34633
34662
  var selection = editor.getDOMSelection();
34634
34663
  editor.formatContentModel(function (model, context) {
34635
- var _a;
34664
+ var _a, _b;
34636
34665
  // 1. delete the expanded selection if any, then merge paragraph
34637
34666
  var result = (0, roosterjs_content_model_dom_1.deleteSelection)(model, [], context);
34638
34667
  // 2. Add line break
@@ -34643,12 +34672,14 @@ function keyboardEnter(editor, rawEvent, formatsToPreserveOnMerge) {
34643
34672
  var steps = rawEvent.shiftKey
34644
34673
  ? []
34645
34674
  : [handleAutoLink_1.handleAutoLink, handleEnterOnList_1.handleEnterOnList, deleteEmptyQuote_1.deleteEmptyQuote];
34646
- steps.push((0, handleEnterOnParagraph_1.handleEnterOnParagraph)(formatsToPreserveOnMerge));
34675
+ if (handleNormalEnter || handleEnterForEntity((_a = result.insertPoint) === null || _a === void 0 ? void 0 : _a.paragraph)) {
34676
+ steps.push((0, handleEnterOnParagraph_1.handleEnterOnParagraph)(formatsToPreserveOnMerge));
34677
+ }
34647
34678
  (0, roosterjs_content_model_dom_1.runEditSteps)(steps, result);
34648
34679
  }
34649
34680
  if (result.deleteResult == 'range') {
34650
34681
  // We have deleted something, next input should inherit the segment format from deleted content, so set pending format here
34651
- context.newPendingFormat = (_a = result.insertPoint) === null || _a === void 0 ? void 0 : _a.marker.format;
34682
+ context.newPendingFormat = (_b = result.insertPoint) === null || _b === void 0 ? void 0 : _b.marker.format;
34652
34683
  (0, roosterjs_content_model_dom_1.normalizeContentModel)(model);
34653
34684
  rawEvent.preventDefault();
34654
34685
  return true;
@@ -34665,6 +34696,10 @@ function keyboardEnter(editor, rawEvent, formatsToPreserveOnMerge) {
34665
34696
  });
34666
34697
  }
34667
34698
  exports.keyboardEnter = keyboardEnter;
34699
+ function handleEnterForEntity(paragraph) {
34700
+ return (paragraph &&
34701
+ (paragraph.isImplicit || paragraph.segments.some(function (x) { return x.segmentType == 'Entity'; })));
34702
+ }
34668
34703
 
34669
34704
 
34670
34705
  /***/ },
@@ -39045,7 +39080,7 @@ var PastePlugin = /** @class */ (function () {
39045
39080
  var pasteType = event.pasteType;
39046
39081
  switch (pasteSource) {
39047
39082
  case 'wordDesktop':
39048
- (0, processPastedContentFromWordDesktop_1.processPastedContentFromWordDesktop)(event.domToModelOption, event.htmlBefore || event.clipboardData.rawHtml || '');
39083
+ (0, processPastedContentFromWordDesktop_1.processPastedContentFromWordDesktop)(event.domToModelOption, event.htmlBefore || event.clipboardData.rawHtml || '', event.globalCssRules);
39049
39084
  break;
39050
39085
  case 'wacComponents':
39051
39086
  (0, processPastedContentWacComponents_1.processPastedContentWacComponents)(event);
@@ -39682,13 +39717,17 @@ var removeNegativeTextIndentParser_1 = __webpack_require__(/*! ../parsers/remove
39682
39717
  var setProcessor_1 = __webpack_require__(/*! ../utils/setProcessor */ "./packages/roosterjs-content-model-plugins/lib/paste/utils/setProcessor.ts");
39683
39718
  var wordContainerParser_1 = __webpack_require__(/*! ../parsers/wordContainerParser */ "./packages/roosterjs-content-model-plugins/lib/paste/parsers/wordContainerParser.ts");
39684
39719
  var wordTableParser_1 = __webpack_require__(/*! ../parsers/wordTableParser */ "./packages/roosterjs-content-model-plugins/lib/paste/parsers/wordTableParser.ts");
39720
+ var removeListParagraphMargins_1 = __webpack_require__(/*! ./removeListParagraphMargins */ "./packages/roosterjs-content-model-plugins/lib/paste/WordDesktop/removeListParagraphMargins.ts");
39685
39721
  /**
39686
39722
  * @internal
39687
39723
  * Handles pasted content when the source is Word Desktop.
39688
39724
  * @param domToModelOption Options for DOM to Content Model conversion
39689
39725
  * @param htmlString The HTML string to process
39726
+ * @param globalCssRules Global CSS rules extracted from the pasted document
39690
39727
  */
39691
- function processPastedContentFromWordDesktop(domToModelOption, htmlString) {
39728
+ function processPastedContentFromWordDesktop(domToModelOption, htmlString, globalCssRules) {
39729
+ if (globalCssRules === void 0) { globalCssRules = []; }
39730
+ (0, removeListParagraphMargins_1.removeListParagraphMargins)(globalCssRules);
39692
39731
  var metadataMap = (0, getStyleMetadata_1.getStyleMetadata)(htmlString);
39693
39732
  (0, setProcessor_1.setProcessor)(domToModelOption, 'element', wordDesktopElementProcessor(metadataMap));
39694
39733
  (0, addParser_1.addParser)(domToModelOption, 'block', adjustPercentileLineHeightParser_1.adjustPercentileLineHeight);
@@ -39959,6 +39998,96 @@ function getBulletElement(element) {
39959
39998
  }
39960
39999
 
39961
40000
 
40001
+ /***/ },
40002
+
40003
+ /***/ "./packages/roosterjs-content-model-plugins/lib/paste/WordDesktop/removeListParagraphMargins.ts"
40004
+ /*!******************************************************************************************************!*\
40005
+ !*** ./packages/roosterjs-content-model-plugins/lib/paste/WordDesktop/removeListParagraphMargins.ts ***!
40006
+ \******************************************************************************************************/
40007
+ (__unused_webpack_module, exports) {
40008
+
40009
+ "use strict";
40010
+
40011
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
40012
+ exports.removeListParagraphMargins = void 0;
40013
+ /**
40014
+ * CSS class selectors used by Word Desktop to mark list paragraph elements.
40015
+ * Word emits global CSS rules that apply margins to these classes, which we want
40016
+ * to suppress so that RoosterJS list indentation logic is used instead.
40017
+ */
40018
+ var WORD_LIST_PARAGRAPH_SELECTORS = new Set([
40019
+ 'p.MsoListParagraph',
40020
+ 'p.MsoListParagraphCxSpFirst',
40021
+ 'p.MsoListParagraphCxSpMiddle',
40022
+ 'p.MsoListParagraphCxSpLast',
40023
+ 'div.MsoListParagraph',
40024
+ 'div.MsoListParagraphCxSpFirst',
40025
+ 'div.MsoListParagraphCxSpMiddle',
40026
+ 'div.MsoListParagraphCxSpLast',
40027
+ ]);
40028
+ /**
40029
+ * @internal
40030
+ * Strips all margin-* properties from a CSS property string.
40031
+ * Empty tokens produced by a trailing semicolon are preserved so that the
40032
+ * resulting string still ends with ";" and remains safe to concatenate.
40033
+ * For example, "margin-top: 0pt; color: red;" becomes " color: red;".
40034
+ */
40035
+ function removeMarginProperties(cssText) {
40036
+ return cssText
40037
+ .split(';')
40038
+ .filter(function (prop) {
40039
+ var name = prop.split(':')[0].trim().toLowerCase();
40040
+ // Keep empty tokens (the trailing ';' produces one) and any non-margin property.
40041
+ return !name || !/^margin/.test(name);
40042
+ })
40043
+ .join(';');
40044
+ }
40045
+ /**
40046
+ * @internal
40047
+ * Removes margin properties from global CSS rules that target Word list paragraph
40048
+ * classes (p.MsoListParagraph, p.MsoListParagraphCxSpFirst, etc.).
40049
+ *
40050
+ * Word Desktop pastes a global stylesheet that typically includes rules like:
40051
+ * p.MsoListParagraph { margin: 0in; margin-bottom: .0001pt; ... }
40052
+ * These margins conflict with RoosterJS's own list indentation, causing double
40053
+ * indentation when the CSS is converted to inline styles via convertInlineCss.
40054
+ *
40055
+ * When a rule's selectors are exclusively list paragraph classes the margins are
40056
+ * removed in place. When a rule groups list paragraph classes with other selectors
40057
+ * the rule is split: the non-list selectors keep the original text, and a new rule
40058
+ * is inserted for the list paragraph selectors with margins stripped.
40059
+ *
40060
+ * The array is mutated in place so the changes are reflected when convertInlineCss
40061
+ * subsequently processes the same array reference.
40062
+ */
40063
+ function removeListParagraphMargins(globalCssRules) {
40064
+ // Iterate in reverse so that splice insertions don't shift unvisited indices.
40065
+ for (var i = globalCssRules.length - 1; i >= 0; i--) {
40066
+ var rule = globalCssRules[i];
40067
+ var matchingSelectors = rule.selectors.filter(function (s) { return WORD_LIST_PARAGRAPH_SELECTORS.has(s); });
40068
+ if (matchingSelectors.length === 0) {
40069
+ continue;
40070
+ }
40071
+ var nonMatchingSelectors = rule.selectors.filter(function (s) { return !WORD_LIST_PARAGRAPH_SELECTORS.has(s); });
40072
+ if (nonMatchingSelectors.length === 0) {
40073
+ // All selectors target list paragraphs — strip margins directly.
40074
+ rule.text = removeMarginProperties(rule.text);
40075
+ }
40076
+ else {
40077
+ // Mixed rule: keep the non-list selectors on the original entry, then
40078
+ // insert a new entry immediately after for the list paragraph selectors
40079
+ // with margins removed.
40080
+ rule.selectors = nonMatchingSelectors;
40081
+ globalCssRules.splice(i + 1, 0, {
40082
+ selectors: matchingSelectors,
40083
+ text: removeMarginProperties(rule.text),
40084
+ });
40085
+ }
40086
+ }
40087
+ }
40088
+ exports.removeListParagraphMargins = removeListParagraphMargins;
40089
+
40090
+
39962
40091
  /***/ },
39963
40092
 
39964
40093
  /***/ "./packages/roosterjs-content-model-plugins/lib/paste/oneNote/processPastedContentFromOneNote.ts"