roosterjs 9.51.0 → 9.52.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
@@ -9319,6 +9319,7 @@ function generatePasteOptionFromPlugins(editor, clipboardData, fragment, htmlFro
9319
9319
  pasteType: pasteType,
9320
9320
  domToModelOption: domToModelOption,
9321
9321
  containsBlockElements: !!htmlFromClipboard.containsBlockElements,
9322
+ globalCssRules: htmlFromClipboard.globalCssRules,
9322
9323
  };
9323
9324
  return editor.triggerEvent('beforePaste', event, true /* broadcast */);
9324
9325
  }
@@ -33633,7 +33634,11 @@ var EditPlugin = /** @class */ (function () {
33633
33634
  if (!hasCtrlOrMetaKey &&
33634
33635
  !event.rawEvent.isComposing &&
33635
33636
  event.rawEvent.keyCode !== DEAD_KEY) {
33636
- (0, keyboardEnter_1.keyboardEnter)(editor, rawEvent, this.options.formatsToPreserveOnMerge);
33637
+ var shouldHandleEnterKey = this.options.shouldHandleEnterKey;
33638
+ var handleNormalEnter = typeof shouldHandleEnterKey === 'function'
33639
+ ? shouldHandleEnterKey(editor)
33640
+ : shouldHandleEnterKey !== false;
33641
+ (0, keyboardEnter_1.keyboardEnter)(editor, rawEvent, handleNormalEnter, this.options.formatsToPreserveOnMerge);
33637
33642
  }
33638
33643
  break;
33639
33644
  default:
@@ -34628,11 +34633,11 @@ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-mo
34628
34633
  /**
34629
34634
  * @internal
34630
34635
  */
34631
- function keyboardEnter(editor, rawEvent, formatsToPreserveOnMerge) {
34636
+ function keyboardEnter(editor, rawEvent, handleNormalEnter, formatsToPreserveOnMerge) {
34632
34637
  if (formatsToPreserveOnMerge === void 0) { formatsToPreserveOnMerge = []; }
34633
34638
  var selection = editor.getDOMSelection();
34634
34639
  editor.formatContentModel(function (model, context) {
34635
- var _a;
34640
+ var _a, _b;
34636
34641
  // 1. delete the expanded selection if any, then merge paragraph
34637
34642
  var result = (0, roosterjs_content_model_dom_1.deleteSelection)(model, [], context);
34638
34643
  // 2. Add line break
@@ -34643,12 +34648,14 @@ function keyboardEnter(editor, rawEvent, formatsToPreserveOnMerge) {
34643
34648
  var steps = rawEvent.shiftKey
34644
34649
  ? []
34645
34650
  : [handleAutoLink_1.handleAutoLink, handleEnterOnList_1.handleEnterOnList, deleteEmptyQuote_1.deleteEmptyQuote];
34646
- steps.push((0, handleEnterOnParagraph_1.handleEnterOnParagraph)(formatsToPreserveOnMerge));
34651
+ if (handleNormalEnter || handleEnterForEntity((_a = result.insertPoint) === null || _a === void 0 ? void 0 : _a.paragraph)) {
34652
+ steps.push((0, handleEnterOnParagraph_1.handleEnterOnParagraph)(formatsToPreserveOnMerge));
34653
+ }
34647
34654
  (0, roosterjs_content_model_dom_1.runEditSteps)(steps, result);
34648
34655
  }
34649
34656
  if (result.deleteResult == 'range') {
34650
34657
  // 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;
34658
+ context.newPendingFormat = (_b = result.insertPoint) === null || _b === void 0 ? void 0 : _b.marker.format;
34652
34659
  (0, roosterjs_content_model_dom_1.normalizeContentModel)(model);
34653
34660
  rawEvent.preventDefault();
34654
34661
  return true;
@@ -34665,6 +34672,10 @@ function keyboardEnter(editor, rawEvent, formatsToPreserveOnMerge) {
34665
34672
  });
34666
34673
  }
34667
34674
  exports.keyboardEnter = keyboardEnter;
34675
+ function handleEnterForEntity(paragraph) {
34676
+ return (paragraph &&
34677
+ (paragraph.isImplicit || paragraph.segments.some(function (x) { return x.segmentType == 'Entity'; })));
34678
+ }
34668
34679
 
34669
34680
 
34670
34681
  /***/ },
@@ -39045,7 +39056,7 @@ var PastePlugin = /** @class */ (function () {
39045
39056
  var pasteType = event.pasteType;
39046
39057
  switch (pasteSource) {
39047
39058
  case 'wordDesktop':
39048
- (0, processPastedContentFromWordDesktop_1.processPastedContentFromWordDesktop)(event.domToModelOption, event.htmlBefore || event.clipboardData.rawHtml || '');
39059
+ (0, processPastedContentFromWordDesktop_1.processPastedContentFromWordDesktop)(event.domToModelOption, event.htmlBefore || event.clipboardData.rawHtml || '', event.globalCssRules);
39049
39060
  break;
39050
39061
  case 'wacComponents':
39051
39062
  (0, processPastedContentWacComponents_1.processPastedContentWacComponents)(event);
@@ -39682,13 +39693,17 @@ var removeNegativeTextIndentParser_1 = __webpack_require__(/*! ../parsers/remove
39682
39693
  var setProcessor_1 = __webpack_require__(/*! ../utils/setProcessor */ "./packages/roosterjs-content-model-plugins/lib/paste/utils/setProcessor.ts");
39683
39694
  var wordContainerParser_1 = __webpack_require__(/*! ../parsers/wordContainerParser */ "./packages/roosterjs-content-model-plugins/lib/paste/parsers/wordContainerParser.ts");
39684
39695
  var wordTableParser_1 = __webpack_require__(/*! ../parsers/wordTableParser */ "./packages/roosterjs-content-model-plugins/lib/paste/parsers/wordTableParser.ts");
39696
+ var removeListParagraphMargins_1 = __webpack_require__(/*! ./removeListParagraphMargins */ "./packages/roosterjs-content-model-plugins/lib/paste/WordDesktop/removeListParagraphMargins.ts");
39685
39697
  /**
39686
39698
  * @internal
39687
39699
  * Handles pasted content when the source is Word Desktop.
39688
39700
  * @param domToModelOption Options for DOM to Content Model conversion
39689
39701
  * @param htmlString The HTML string to process
39702
+ * @param globalCssRules Global CSS rules extracted from the pasted document
39690
39703
  */
39691
- function processPastedContentFromWordDesktop(domToModelOption, htmlString) {
39704
+ function processPastedContentFromWordDesktop(domToModelOption, htmlString, globalCssRules) {
39705
+ if (globalCssRules === void 0) { globalCssRules = []; }
39706
+ (0, removeListParagraphMargins_1.removeListParagraphMargins)(globalCssRules);
39692
39707
  var metadataMap = (0, getStyleMetadata_1.getStyleMetadata)(htmlString);
39693
39708
  (0, setProcessor_1.setProcessor)(domToModelOption, 'element', wordDesktopElementProcessor(metadataMap));
39694
39709
  (0, addParser_1.addParser)(domToModelOption, 'block', adjustPercentileLineHeightParser_1.adjustPercentileLineHeight);
@@ -39959,6 +39974,96 @@ function getBulletElement(element) {
39959
39974
  }
39960
39975
 
39961
39976
 
39977
+ /***/ },
39978
+
39979
+ /***/ "./packages/roosterjs-content-model-plugins/lib/paste/WordDesktop/removeListParagraphMargins.ts"
39980
+ /*!******************************************************************************************************!*\
39981
+ !*** ./packages/roosterjs-content-model-plugins/lib/paste/WordDesktop/removeListParagraphMargins.ts ***!
39982
+ \******************************************************************************************************/
39983
+ (__unused_webpack_module, exports) {
39984
+
39985
+ "use strict";
39986
+
39987
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
39988
+ exports.removeListParagraphMargins = void 0;
39989
+ /**
39990
+ * CSS class selectors used by Word Desktop to mark list paragraph elements.
39991
+ * Word emits global CSS rules that apply margins to these classes, which we want
39992
+ * to suppress so that RoosterJS list indentation logic is used instead.
39993
+ */
39994
+ var WORD_LIST_PARAGRAPH_SELECTORS = new Set([
39995
+ 'p.MsoListParagraph',
39996
+ 'p.MsoListParagraphCxSpFirst',
39997
+ 'p.MsoListParagraphCxSpMiddle',
39998
+ 'p.MsoListParagraphCxSpLast',
39999
+ 'div.MsoListParagraph',
40000
+ 'div.MsoListParagraphCxSpFirst',
40001
+ 'div.MsoListParagraphCxSpMiddle',
40002
+ 'div.MsoListParagraphCxSpLast',
40003
+ ]);
40004
+ /**
40005
+ * @internal
40006
+ * Strips all margin-* properties from a CSS property string.
40007
+ * Empty tokens produced by a trailing semicolon are preserved so that the
40008
+ * resulting string still ends with ";" and remains safe to concatenate.
40009
+ * For example, "margin-top: 0pt; color: red;" becomes " color: red;".
40010
+ */
40011
+ function removeMarginProperties(cssText) {
40012
+ return cssText
40013
+ .split(';')
40014
+ .filter(function (prop) {
40015
+ var name = prop.split(':')[0].trim().toLowerCase();
40016
+ // Keep empty tokens (the trailing ';' produces one) and any non-margin property.
40017
+ return !name || !/^margin/.test(name);
40018
+ })
40019
+ .join(';');
40020
+ }
40021
+ /**
40022
+ * @internal
40023
+ * Removes margin properties from global CSS rules that target Word list paragraph
40024
+ * classes (p.MsoListParagraph, p.MsoListParagraphCxSpFirst, etc.).
40025
+ *
40026
+ * Word Desktop pastes a global stylesheet that typically includes rules like:
40027
+ * p.MsoListParagraph { margin: 0in; margin-bottom: .0001pt; ... }
40028
+ * These margins conflict with RoosterJS's own list indentation, causing double
40029
+ * indentation when the CSS is converted to inline styles via convertInlineCss.
40030
+ *
40031
+ * When a rule's selectors are exclusively list paragraph classes the margins are
40032
+ * removed in place. When a rule groups list paragraph classes with other selectors
40033
+ * the rule is split: the non-list selectors keep the original text, and a new rule
40034
+ * is inserted for the list paragraph selectors with margins stripped.
40035
+ *
40036
+ * The array is mutated in place so the changes are reflected when convertInlineCss
40037
+ * subsequently processes the same array reference.
40038
+ */
40039
+ function removeListParagraphMargins(globalCssRules) {
40040
+ // Iterate in reverse so that splice insertions don't shift unvisited indices.
40041
+ for (var i = globalCssRules.length - 1; i >= 0; i--) {
40042
+ var rule = globalCssRules[i];
40043
+ var matchingSelectors = rule.selectors.filter(function (s) { return WORD_LIST_PARAGRAPH_SELECTORS.has(s); });
40044
+ if (matchingSelectors.length === 0) {
40045
+ continue;
40046
+ }
40047
+ var nonMatchingSelectors = rule.selectors.filter(function (s) { return !WORD_LIST_PARAGRAPH_SELECTORS.has(s); });
40048
+ if (nonMatchingSelectors.length === 0) {
40049
+ // All selectors target list paragraphs — strip margins directly.
40050
+ rule.text = removeMarginProperties(rule.text);
40051
+ }
40052
+ else {
40053
+ // Mixed rule: keep the non-list selectors on the original entry, then
40054
+ // insert a new entry immediately after for the list paragraph selectors
40055
+ // with margins removed.
40056
+ rule.selectors = nonMatchingSelectors;
40057
+ globalCssRules.splice(i + 1, 0, {
40058
+ selectors: matchingSelectors,
40059
+ text: removeMarginProperties(rule.text),
40060
+ });
40061
+ }
40062
+ }
40063
+ }
40064
+ exports.removeListParagraphMargins = removeListParagraphMargins;
40065
+
40066
+
39962
40067
  /***/ },
39963
40068
 
39964
40069
  /***/ "./packages/roosterjs-content-model-plugins/lib/paste/oneNote/processPastedContentFromOneNote.ts"