roosterjs-content-model-plugins 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.
Files changed (46) hide show
  1. package/lib/edit/EditOptions.d.ts +0 -1
  2. package/lib/edit/EditOptions.js.map +1 -1
  3. package/lib/edit/EditPlugin.js +5 -1
  4. package/lib/edit/EditPlugin.js.map +1 -1
  5. package/lib/edit/keyboardEnter.d.ts +1 -1
  6. package/lib/edit/keyboardEnter.js +10 -4
  7. package/lib/edit/keyboardEnter.js.map +1 -1
  8. package/lib/paste/PastePlugin.js +1 -1
  9. package/lib/paste/PastePlugin.js.map +1 -1
  10. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.d.ts +3 -2
  11. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.js +5 -1
  12. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  13. package/lib/paste/WordDesktop/removeListParagraphMargins.d.ts +20 -0
  14. package/lib/paste/WordDesktop/removeListParagraphMargins.js +80 -0
  15. package/lib/paste/WordDesktop/removeListParagraphMargins.js.map +1 -0
  16. package/lib-amd/edit/EditOptions.d.ts +0 -1
  17. package/lib-amd/edit/EditOptions.js.map +1 -1
  18. package/lib-amd/edit/EditPlugin.js +5 -1
  19. package/lib-amd/edit/EditPlugin.js.map +1 -1
  20. package/lib-amd/edit/keyboardEnter.d.ts +1 -1
  21. package/lib-amd/edit/keyboardEnter.js +10 -4
  22. package/lib-amd/edit/keyboardEnter.js.map +1 -1
  23. package/lib-amd/paste/PastePlugin.js +1 -1
  24. package/lib-amd/paste/PastePlugin.js.map +1 -1
  25. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.d.ts +3 -2
  26. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.js +5 -2
  27. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  28. package/lib-amd/paste/WordDesktop/removeListParagraphMargins.d.ts +20 -0
  29. package/lib-amd/paste/WordDesktop/removeListParagraphMargins.js +82 -0
  30. package/lib-amd/paste/WordDesktop/removeListParagraphMargins.js.map +1 -0
  31. package/lib-mjs/edit/EditOptions.d.ts +0 -1
  32. package/lib-mjs/edit/EditOptions.js.map +1 -1
  33. package/lib-mjs/edit/EditPlugin.js +5 -1
  34. package/lib-mjs/edit/EditPlugin.js.map +1 -1
  35. package/lib-mjs/edit/keyboardEnter.d.ts +1 -1
  36. package/lib-mjs/edit/keyboardEnter.js +10 -4
  37. package/lib-mjs/edit/keyboardEnter.js.map +1 -1
  38. package/lib-mjs/paste/PastePlugin.js +1 -1
  39. package/lib-mjs/paste/PastePlugin.js.map +1 -1
  40. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.d.ts +3 -2
  41. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.js +5 -1
  42. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  43. package/lib-mjs/paste/WordDesktop/removeListParagraphMargins.d.ts +20 -0
  44. package/lib-mjs/paste/WordDesktop/removeListParagraphMargins.js +76 -0
  45. package/lib-mjs/paste/WordDesktop/removeListParagraphMargins.js.map +1 -0
  46. package/package.json +5 -5
@@ -10,13 +10,17 @@ import { removeNegativeTextIndentParser } from '../parsers/removeNegativeTextInd
10
10
  import { setProcessor } from '../utils/setProcessor';
11
11
  import { wordContainerParser } from '../parsers/wordContainerParser';
12
12
  import { wordTableParser } from '../parsers/wordTableParser';
13
+ import { removeListParagraphMargins } from './removeListParagraphMargins';
13
14
  /**
14
15
  * @internal
15
16
  * Handles pasted content when the source is Word Desktop.
16
17
  * @param domToModelOption Options for DOM to Content Model conversion
17
18
  * @param htmlString The HTML string to process
19
+ * @param globalCssRules Global CSS rules extracted from the pasted document
18
20
  */
19
- export function processPastedContentFromWordDesktop(domToModelOption, htmlString) {
21
+ export function processPastedContentFromWordDesktop(domToModelOption, htmlString, globalCssRules) {
22
+ if (globalCssRules === void 0) { globalCssRules = []; }
23
+ removeListParagraphMargins(globalCssRules);
20
24
  var metadataMap = getStyleMetadata(htmlString);
21
25
  setProcessor(domToModelOption, 'element', wordDesktopElementProcessor(metadataMap));
22
26
  addParser(domToModelOption, 'block', adjustPercentileLineHeight);
@@ -1 +1 @@
1
- {"version":3,"file":"processPastedContentFromWordDesktop.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/WordDesktop/processPastedContentFromWordDesktop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,6CAA6C,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,8BAA8B,EAAE,MAAM,2CAA2C,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAI7D;;;;;GAKG;AACH,MAAM,UAAU,mCAAmC,CAC/C,gBAAkC,EAClC,UAAkB;IAElB,IAAM,WAAW,GAA8B,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAE5E,YAAY,CAAC,gBAAgB,EAAE,SAAS,EAAE,2BAA2B,CAAC,WAAW,CAAC,CAAC,CAAC;IACpF,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,0BAA0B,CAAC,CAAC;IACjE,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,8BAA8B,CAAC,CAAC;IACrE,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,8BAA8B,CAAC,CAAC;IAC/E,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,0BAA0B,CAAC,CAAC;IAC3E,SAAS,CAAC,gBAAgB,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;IAC1D,SAAS,CAAC,gBAAgB,EAAE,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAC9D,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;AAC1D,CAAC;AAED,IAAM,2BAA2B,GAAG,UAChC,WAAsC;IAEtC,OAAO,UAAC,KAAK,EAAE,OAAO,EAAE,OAAO;QAC3B,IAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,4FAA4F;QAC5F,IACI,CAAC,CACG,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC;YAC7D,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CACvC,EACH;YACE,OAAO,CAAC,wBAAwB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SACrE;IACL,CAAC,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { adjustPercentileLineHeight } from '../parsers/adjustPercentileLineHeightParser';\nimport { getStyleMetadata } from './getStyleMetadata';\nimport { getStyles } from '../utils/getStyles';\nimport { listLevelParser } from '../parsers/listLevelParser';\nimport { processWordComments } from './processWordComments';\nimport { processWordList } from './processWordLists';\nimport { adjustWordListMarginParser } from '../parsers/adjustWordListMarginParser';\nimport { removeNegativeTextIndentParser } from '../parsers/removeNegativeTextIndentParser';\nimport { setProcessor } from '../utils/setProcessor';\nimport { wordContainerParser } from '../parsers/wordContainerParser';\nimport { wordTableParser } from '../parsers/wordTableParser';\nimport type { WordMetadata } from './WordMetadata';\nimport type { DomToModelOption, ElementProcessor } from 'roosterjs-content-model-types';\n\n/**\n * @internal\n * Handles pasted content when the source is Word Desktop.\n * @param domToModelOption Options for DOM to Content Model conversion\n * @param htmlString The HTML string to process\n */\nexport function processPastedContentFromWordDesktop(\n domToModelOption: DomToModelOption,\n htmlString: string\n) {\n const metadataMap: Map<string, WordMetadata> = getStyleMetadata(htmlString);\n\n setProcessor(domToModelOption, 'element', wordDesktopElementProcessor(metadataMap));\n addParser(domToModelOption, 'block', adjustPercentileLineHeight);\n addParser(domToModelOption, 'block', removeNegativeTextIndentParser);\n addParser(domToModelOption, 'listItemElement', removeNegativeTextIndentParser);\n addParser(domToModelOption, 'listItemElement', adjustWordListMarginParser);\n addParser(domToModelOption, 'listLevel', listLevelParser);\n addParser(domToModelOption, 'container', wordContainerParser);\n addParser(domToModelOption, 'table', wordTableParser);\n}\n\nconst wordDesktopElementProcessor = (\n metadataKey: Map<string, WordMetadata>\n): ElementProcessor<HTMLElement> => {\n return (group, element, context) => {\n const styles = getStyles(element);\n // Process Word Lists or Word Commands, otherwise use the default processor on this element.\n if (\n !(\n processWordList(styles, group, element, context, metadataKey) ||\n processWordComments(styles, element)\n )\n ) {\n context.defaultElementProcessors.element(group, element, context);\n }\n };\n};\n"]}
1
+ {"version":3,"file":"processPastedContentFromWordDesktop.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/WordDesktop/processPastedContentFromWordDesktop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,6CAA6C,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,8BAA8B,EAAE,MAAM,2CAA2C,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAI1E;;;;;;GAMG;AACH,MAAM,UAAU,mCAAmC,CAC/C,gBAAkC,EAClC,UAAkB,EAClB,cAA8B;IAA9B,+BAAA,EAAA,mBAA8B;IAE9B,0BAA0B,CAAC,cAAc,CAAC,CAAC;IAE3C,IAAM,WAAW,GAA8B,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAE5E,YAAY,CAAC,gBAAgB,EAAE,SAAS,EAAE,2BAA2B,CAAC,WAAW,CAAC,CAAC,CAAC;IACpF,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,0BAA0B,CAAC,CAAC;IACjE,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,8BAA8B,CAAC,CAAC;IACrE,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,8BAA8B,CAAC,CAAC;IAC/E,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,0BAA0B,CAAC,CAAC;IAC3E,SAAS,CAAC,gBAAgB,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;IAC1D,SAAS,CAAC,gBAAgB,EAAE,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAC9D,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;AAC1D,CAAC;AAED,IAAM,2BAA2B,GAAG,UAChC,WAAsC;IAEtC,OAAO,UAAC,KAAK,EAAE,OAAO,EAAE,OAAO;QAC3B,IAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,4FAA4F;QAC5F,IACI,CAAC,CACG,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC;YAC7D,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CACvC,EACH;YACE,OAAO,CAAC,wBAAwB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SACrE;IACL,CAAC,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { adjustPercentileLineHeight } from '../parsers/adjustPercentileLineHeightParser';\nimport { getStyleMetadata } from './getStyleMetadata';\nimport { getStyles } from '../utils/getStyles';\nimport { listLevelParser } from '../parsers/listLevelParser';\nimport { processWordComments } from './processWordComments';\nimport { processWordList } from './processWordLists';\nimport { adjustWordListMarginParser } from '../parsers/adjustWordListMarginParser';\nimport { removeNegativeTextIndentParser } from '../parsers/removeNegativeTextIndentParser';\nimport { setProcessor } from '../utils/setProcessor';\nimport { wordContainerParser } from '../parsers/wordContainerParser';\nimport { wordTableParser } from '../parsers/wordTableParser';\nimport { removeListParagraphMargins } from './removeListParagraphMargins';\nimport type { WordMetadata } from './WordMetadata';\nimport type { CssRule, DomToModelOption, ElementProcessor } from 'roosterjs-content-model-types';\n\n/**\n * @internal\n * Handles pasted content when the source is Word Desktop.\n * @param domToModelOption Options for DOM to Content Model conversion\n * @param htmlString The HTML string to process\n * @param globalCssRules Global CSS rules extracted from the pasted document\n */\nexport function processPastedContentFromWordDesktop(\n domToModelOption: DomToModelOption,\n htmlString: string,\n globalCssRules: CssRule[] = []\n) {\n removeListParagraphMargins(globalCssRules);\n\n const metadataMap: Map<string, WordMetadata> = getStyleMetadata(htmlString);\n\n setProcessor(domToModelOption, 'element', wordDesktopElementProcessor(metadataMap));\n addParser(domToModelOption, 'block', adjustPercentileLineHeight);\n addParser(domToModelOption, 'block', removeNegativeTextIndentParser);\n addParser(domToModelOption, 'listItemElement', removeNegativeTextIndentParser);\n addParser(domToModelOption, 'listItemElement', adjustWordListMarginParser);\n addParser(domToModelOption, 'listLevel', listLevelParser);\n addParser(domToModelOption, 'container', wordContainerParser);\n addParser(domToModelOption, 'table', wordTableParser);\n}\n\nconst wordDesktopElementProcessor = (\n metadataKey: Map<string, WordMetadata>\n): ElementProcessor<HTMLElement> => {\n return (group, element, context) => {\n const styles = getStyles(element);\n // Process Word Lists or Word Commands, otherwise use the default processor on this element.\n if (\n !(\n processWordList(styles, group, element, context, metadataKey) ||\n processWordComments(styles, element)\n )\n ) {\n context.defaultElementProcessors.element(group, element, context);\n }\n };\n};\n"]}
@@ -0,0 +1,20 @@
1
+ import type { CssRule } from 'roosterjs-content-model-types';
2
+ /**
3
+ * @internal
4
+ * Removes margin properties from global CSS rules that target Word list paragraph
5
+ * classes (p.MsoListParagraph, p.MsoListParagraphCxSpFirst, etc.).
6
+ *
7
+ * Word Desktop pastes a global stylesheet that typically includes rules like:
8
+ * p.MsoListParagraph { margin: 0in; margin-bottom: .0001pt; ... }
9
+ * These margins conflict with RoosterJS's own list indentation, causing double
10
+ * indentation when the CSS is converted to inline styles via convertInlineCss.
11
+ *
12
+ * When a rule's selectors are exclusively list paragraph classes the margins are
13
+ * removed in place. When a rule groups list paragraph classes with other selectors
14
+ * the rule is split: the non-list selectors keep the original text, and a new rule
15
+ * is inserted for the list paragraph selectors with margins stripped.
16
+ *
17
+ * The array is mutated in place so the changes are reflected when convertInlineCss
18
+ * subsequently processes the same array reference.
19
+ */
20
+ export declare function removeListParagraphMargins(globalCssRules: CssRule[]): void;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * CSS class selectors used by Word Desktop to mark list paragraph elements.
3
+ * Word emits global CSS rules that apply margins to these classes, which we want
4
+ * to suppress so that RoosterJS list indentation logic is used instead.
5
+ */
6
+ var WORD_LIST_PARAGRAPH_SELECTORS = new Set([
7
+ 'p.MsoListParagraph',
8
+ 'p.MsoListParagraphCxSpFirst',
9
+ 'p.MsoListParagraphCxSpMiddle',
10
+ 'p.MsoListParagraphCxSpLast',
11
+ 'div.MsoListParagraph',
12
+ 'div.MsoListParagraphCxSpFirst',
13
+ 'div.MsoListParagraphCxSpMiddle',
14
+ 'div.MsoListParagraphCxSpLast',
15
+ ]);
16
+ /**
17
+ * @internal
18
+ * Strips all margin-* properties from a CSS property string.
19
+ * Empty tokens produced by a trailing semicolon are preserved so that the
20
+ * resulting string still ends with ";" and remains safe to concatenate.
21
+ * For example, "margin-top: 0pt; color: red;" becomes " color: red;".
22
+ */
23
+ function removeMarginProperties(cssText) {
24
+ return cssText
25
+ .split(';')
26
+ .filter(function (prop) {
27
+ var name = prop.split(':')[0].trim().toLowerCase();
28
+ // Keep empty tokens (the trailing ';' produces one) and any non-margin property.
29
+ return !name || !/^margin/.test(name);
30
+ })
31
+ .join(';');
32
+ }
33
+ /**
34
+ * @internal
35
+ * Removes margin properties from global CSS rules that target Word list paragraph
36
+ * classes (p.MsoListParagraph, p.MsoListParagraphCxSpFirst, etc.).
37
+ *
38
+ * Word Desktop pastes a global stylesheet that typically includes rules like:
39
+ * p.MsoListParagraph { margin: 0in; margin-bottom: .0001pt; ... }
40
+ * These margins conflict with RoosterJS's own list indentation, causing double
41
+ * indentation when the CSS is converted to inline styles via convertInlineCss.
42
+ *
43
+ * When a rule's selectors are exclusively list paragraph classes the margins are
44
+ * removed in place. When a rule groups list paragraph classes with other selectors
45
+ * the rule is split: the non-list selectors keep the original text, and a new rule
46
+ * is inserted for the list paragraph selectors with margins stripped.
47
+ *
48
+ * The array is mutated in place so the changes are reflected when convertInlineCss
49
+ * subsequently processes the same array reference.
50
+ */
51
+ export function removeListParagraphMargins(globalCssRules) {
52
+ // Iterate in reverse so that splice insertions don't shift unvisited indices.
53
+ for (var i = globalCssRules.length - 1; i >= 0; i--) {
54
+ var rule = globalCssRules[i];
55
+ var matchingSelectors = rule.selectors.filter(function (s) { return WORD_LIST_PARAGRAPH_SELECTORS.has(s); });
56
+ if (matchingSelectors.length === 0) {
57
+ continue;
58
+ }
59
+ var nonMatchingSelectors = rule.selectors.filter(function (s) { return !WORD_LIST_PARAGRAPH_SELECTORS.has(s); });
60
+ if (nonMatchingSelectors.length === 0) {
61
+ // All selectors target list paragraphs — strip margins directly.
62
+ rule.text = removeMarginProperties(rule.text);
63
+ }
64
+ else {
65
+ // Mixed rule: keep the non-list selectors on the original entry, then
66
+ // insert a new entry immediately after for the list paragraph selectors
67
+ // with margins removed.
68
+ rule.selectors = nonMatchingSelectors;
69
+ globalCssRules.splice(i + 1, 0, {
70
+ selectors: matchingSelectors,
71
+ text: removeMarginProperties(rule.text),
72
+ });
73
+ }
74
+ }
75
+ }
76
+ //# sourceMappingURL=removeListParagraphMargins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"removeListParagraphMargins.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/WordDesktop/removeListParagraphMargins.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,IAAM,6BAA6B,GAAG,IAAI,GAAG,CAAC;IAC1C,oBAAoB;IACpB,6BAA6B;IAC7B,8BAA8B;IAC9B,4BAA4B;IAC5B,sBAAsB;IACtB,+BAA+B;IAC/B,gCAAgC;IAChC,8BAA8B;CACjC,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,SAAS,sBAAsB,CAAC,OAAe;IAC3C,OAAO,OAAO;SACT,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,UAAA,IAAI;QACR,IAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrD,iFAAiF;QACjF,OAAO,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,0BAA0B,CAAC,cAAyB;IAChE,8EAA8E;IAC9E,KAAK,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;QACjD,IAAM,IAAI,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAA,CAAC,IAAI,OAAA,6BAA6B,CAAC,GAAG,CAAC,CAAC,CAAC,EAApC,CAAoC,CAAC,CAAC;QAE3F,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE;YAChC,SAAS;SACZ;QAED,IAAM,oBAAoB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAC9C,UAAA,CAAC,IAAI,OAAA,CAAC,6BAA6B,CAAC,GAAG,CAAC,CAAC,CAAC,EAArC,CAAqC,CAC7C,CAAC;QAEF,IAAI,oBAAoB,CAAC,MAAM,KAAK,CAAC,EAAE;YACnC,iEAAiE;YACjE,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACjD;aAAM;YACH,sEAAsE;YACtE,wEAAwE;YACxE,wBAAwB;YACxB,IAAI,CAAC,SAAS,GAAG,oBAAoB,CAAC;YACtC,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBAC5B,SAAS,EAAE,iBAAiB;gBAC5B,IAAI,EAAE,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC;aAC1C,CAAC,CAAC;SACN;KACJ;AACL,CAAC","sourcesContent":["import type { CssRule } from 'roosterjs-content-model-types';\n\n/**\n * CSS class selectors used by Word Desktop to mark list paragraph elements.\n * Word emits global CSS rules that apply margins to these classes, which we want\n * to suppress so that RoosterJS list indentation logic is used instead.\n */\nconst WORD_LIST_PARAGRAPH_SELECTORS = new Set([\n 'p.MsoListParagraph',\n 'p.MsoListParagraphCxSpFirst',\n 'p.MsoListParagraphCxSpMiddle',\n 'p.MsoListParagraphCxSpLast',\n 'div.MsoListParagraph',\n 'div.MsoListParagraphCxSpFirst',\n 'div.MsoListParagraphCxSpMiddle',\n 'div.MsoListParagraphCxSpLast',\n]);\n\n/**\n * @internal\n * Strips all margin-* properties from a CSS property string.\n * Empty tokens produced by a trailing semicolon are preserved so that the\n * resulting string still ends with \";\" and remains safe to concatenate.\n * For example, \"margin-top: 0pt; color: red;\" becomes \" color: red;\".\n */\nfunction removeMarginProperties(cssText: string): string {\n return cssText\n .split(';')\n .filter(prop => {\n const name = prop.split(':')[0].trim().toLowerCase();\n // Keep empty tokens (the trailing ';' produces one) and any non-margin property.\n return !name || !/^margin/.test(name);\n })\n .join(';');\n}\n\n/**\n * @internal\n * Removes margin properties from global CSS rules that target Word list paragraph\n * classes (p.MsoListParagraph, p.MsoListParagraphCxSpFirst, etc.).\n *\n * Word Desktop pastes a global stylesheet that typically includes rules like:\n * p.MsoListParagraph { margin: 0in; margin-bottom: .0001pt; ... }\n * These margins conflict with RoosterJS's own list indentation, causing double\n * indentation when the CSS is converted to inline styles via convertInlineCss.\n *\n * When a rule's selectors are exclusively list paragraph classes the margins are\n * removed in place. When a rule groups list paragraph classes with other selectors\n * the rule is split: the non-list selectors keep the original text, and a new rule\n * is inserted for the list paragraph selectors with margins stripped.\n *\n * The array is mutated in place so the changes are reflected when convertInlineCss\n * subsequently processes the same array reference.\n */\nexport function removeListParagraphMargins(globalCssRules: CssRule[]): void {\n // Iterate in reverse so that splice insertions don't shift unvisited indices.\n for (let i = globalCssRules.length - 1; i >= 0; i--) {\n const rule = globalCssRules[i];\n const matchingSelectors = rule.selectors.filter(s => WORD_LIST_PARAGRAPH_SELECTORS.has(s));\n\n if (matchingSelectors.length === 0) {\n continue;\n }\n\n const nonMatchingSelectors = rule.selectors.filter(\n s => !WORD_LIST_PARAGRAPH_SELECTORS.has(s)\n );\n\n if (nonMatchingSelectors.length === 0) {\n // All selectors target list paragraphs — strip margins directly.\n rule.text = removeMarginProperties(rule.text);\n } else {\n // Mixed rule: keep the non-list selectors on the original entry, then\n // insert a new entry immediately after for the list paragraph selectors\n // with margins removed.\n rule.selectors = nonMatchingSelectors;\n globalCssRules.splice(i + 1, 0, {\n selectors: matchingSelectors,\n text: removeMarginProperties(rule.text),\n });\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -3,12 +3,12 @@
3
3
  "description": "Plugins for roosterjs",
4
4
  "dependencies": {
5
5
  "tslib": "^2.3.1",
6
- "roosterjs-content-model-core": "^9.51.0",
7
- "roosterjs-content-model-dom": "^9.51.0",
8
- "roosterjs-content-model-types": "^9.51.0",
9
- "roosterjs-content-model-api": "^9.51.0"
6
+ "roosterjs-content-model-core": "^9.52.0",
7
+ "roosterjs-content-model-dom": "^9.52.0",
8
+ "roosterjs-content-model-types": "^9.52.0",
9
+ "roosterjs-content-model-api": "^9.52.0"
10
10
  },
11
- "version": "9.51.0",
11
+ "version": "9.52.0",
12
12
  "main": "./lib/index.js",
13
13
  "typings": "./lib/index.d.ts",
14
14
  "module": "./lib-mjs/index.js",