roosterjs-content-model-plugins 0.22.0 → 0.23.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 (55) hide show
  1. package/lib/edit/deleteSteps/deleteWordSelection.js +1 -1
  2. package/lib/edit/deleteSteps/deleteWordSelection.js.map +1 -1
  3. package/lib/edit/keyboardInput.js +4 -3
  4. package/lib/edit/keyboardInput.js.map +1 -1
  5. package/lib/paste/ContentModelPastePlugin.d.ts +1 -2
  6. package/lib/paste/ContentModelPastePlugin.js +2 -12
  7. package/lib/paste/ContentModelPastePlugin.js.map +1 -1
  8. package/lib/paste/WacComponents/constants.d.ts +0 -8
  9. package/lib/paste/WacComponents/constants.js +1 -24
  10. package/lib/paste/WacComponents/constants.js.map +1 -1
  11. package/lib/paste/WacComponents/processPastedContentWacComponents.js +4 -6
  12. package/lib/paste/WacComponents/processPastedContentWacComponents.js.map +1 -1
  13. package/lib/paste/WordDesktop/getStyleMetadata.js +1 -1
  14. package/lib/paste/WordDesktop/getStyleMetadata.js.map +1 -1
  15. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.js +6 -19
  16. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  17. package/lib/paste/WordDesktop/processWordLists.js +37 -12
  18. package/lib/paste/WordDesktop/processWordLists.js.map +1 -1
  19. package/lib-amd/edit/deleteSteps/deleteWordSelection.js +1 -1
  20. package/lib-amd/edit/deleteSteps/deleteWordSelection.js.map +1 -1
  21. package/lib-amd/edit/keyboardInput.js +4 -3
  22. package/lib-amd/edit/keyboardInput.js.map +1 -1
  23. package/lib-amd/paste/ContentModelPastePlugin.d.ts +1 -2
  24. package/lib-amd/paste/ContentModelPastePlugin.js +3 -12
  25. package/lib-amd/paste/ContentModelPastePlugin.js.map +1 -1
  26. package/lib-amd/paste/WacComponents/constants.d.ts +0 -8
  27. package/lib-amd/paste/WacComponents/constants.js +1 -24
  28. package/lib-amd/paste/WacComponents/constants.js.map +1 -1
  29. package/lib-amd/paste/WacComponents/processPastedContentWacComponents.js +5 -6
  30. package/lib-amd/paste/WacComponents/processPastedContentWacComponents.js.map +1 -1
  31. package/lib-amd/paste/WordDesktop/getStyleMetadata.js +1 -1
  32. package/lib-amd/paste/WordDesktop/getStyleMetadata.js.map +1 -1
  33. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.js +7 -18
  34. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  35. package/lib-amd/paste/WordDesktop/processWordLists.js +37 -12
  36. package/lib-amd/paste/WordDesktop/processWordLists.js.map +1 -1
  37. package/lib-mjs/edit/deleteSteps/deleteWordSelection.js +1 -1
  38. package/lib-mjs/edit/deleteSteps/deleteWordSelection.js.map +1 -1
  39. package/lib-mjs/edit/keyboardInput.js +4 -3
  40. package/lib-mjs/edit/keyboardInput.js.map +1 -1
  41. package/lib-mjs/paste/ContentModelPastePlugin.d.ts +1 -2
  42. package/lib-mjs/paste/ContentModelPastePlugin.js +2 -12
  43. package/lib-mjs/paste/ContentModelPastePlugin.js.map +1 -1
  44. package/lib-mjs/paste/WacComponents/constants.d.ts +0 -8
  45. package/lib-mjs/paste/WacComponents/constants.js +0 -23
  46. package/lib-mjs/paste/WacComponents/constants.js.map +1 -1
  47. package/lib-mjs/paste/WacComponents/processPastedContentWacComponents.js +5 -7
  48. package/lib-mjs/paste/WacComponents/processPastedContentWacComponents.js.map +1 -1
  49. package/lib-mjs/paste/WordDesktop/getStyleMetadata.js +1 -1
  50. package/lib-mjs/paste/WordDesktop/getStyleMetadata.js.map +1 -1
  51. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.js +6 -19
  52. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  53. package/lib-mjs/paste/WordDesktop/processWordLists.js +38 -13
  54. package/lib-mjs/paste/WordDesktop/processWordLists.js.map +1 -1
  55. package/package.json +5 -5
@@ -1,7 +1,6 @@
1
- import { __read, __spreadArray } from "tslib";
2
1
  import addParser from '../utils/addParser';
3
2
  import { setProcessor } from '../utils/setProcessor';
4
- import { CLASSES_TO_KEEP, COMMENT_HIGHLIGHT_CLASS, COMMENT_HIGHLIGHT_CLICKED_CLASS, LIST_CONTAINER_ELEMENT_CLASS_NAME, TABLE_CONTAINER, TEMP_ELEMENTS_CLASSES, WAC_IDENTIFY_SELECTOR, } from './constants';
3
+ import { COMMENT_HIGHLIGHT_CLASS, COMMENT_HIGHLIGHT_CLICKED_CLASS, LIST_CONTAINER_ELEMENT_CLASS_NAME, TEMP_ELEMENTS_CLASSES, WAC_IDENTIFY_SELECTOR, } from './constants';
5
4
  var LIST_ELEMENT_TAGS = ['UL', 'OL', 'LI'];
6
5
  var LIST_ELEMENT_SELECTOR = LIST_ELEMENT_TAGS.join(',');
7
6
  var COMMENT_BG_COLOR_REST = 'rgba(209, 209, 209, 0.5)';
@@ -134,17 +133,16 @@ var wacCommentParser = function (format, element) {
134
133
  * @param ev ContentModelBeforePasteEvent
135
134
  */
136
135
  export function processPastedContentWacComponents(ev) {
137
- var _a;
138
136
  addParser(ev.domToModelOption, 'segment', wacSubSuperParser);
139
137
  addParser(ev.domToModelOption, 'listItemThread', wacListItemParser);
140
138
  addParser(ev.domToModelOption, 'listLevel', wacListLevelParser);
141
- addParser(ev.domToModelOption, 'container', wacBlockParser);
139
+ addParser(ev.domToModelOption, 'container', wacContainerParser);
140
+ addParser(ev.domToModelOption, 'table', wacContainerParser);
142
141
  addParser(ev.domToModelOption, 'segment', wacCommentParser);
143
142
  setProcessor(ev.domToModelOption, 'element', wacElementProcessor);
144
143
  setProcessor(ev.domToModelOption, 'li', wacLiElementProcessor);
145
144
  setProcessor(ev.domToModelOption, 'ol', wacListProcessor);
146
145
  setProcessor(ev.domToModelOption, 'ul', wacListProcessor);
147
- (_a = ev.sanitizingOption.additionalAllowedCssClasses).push.apply(_a, __spreadArray([], __read(CLASSES_TO_KEEP), false));
148
146
  }
149
147
  /**
150
148
  * List items from word have this format when using List items:
@@ -181,8 +179,8 @@ var wacListProcessor = function (group, element, context) {
181
179
  (_e = (_d = context.defaultElementProcessors).ul) === null || _e === void 0 ? void 0 : _e.call(_d, group, element, context);
182
180
  }
183
181
  };
184
- var wacBlockParser = function (format, element) {
185
- if (element.classList.contains(TABLE_CONTAINER) && element.style.marginLeft.startsWith('-')) {
182
+ var wacContainerParser = function (format, element) {
183
+ if (element.style.marginLeft.startsWith('-')) {
186
184
  delete format.marginLeft;
187
185
  }
188
186
  };
@@ -1 +1 @@
1
- {"version":3,"file":"processPastedContentWacComponents.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-plugins/lib/paste/WacComponents/processPastedContentWacComponents.ts"],"names":[],"mappings":"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","sourcesContent":["import addParser from '../utils/addParser';\nimport { setProcessor } from '../utils/setProcessor';\nimport {\n CLASSES_TO_KEEP,\n COMMENT_HIGHLIGHT_CLASS,\n COMMENT_HIGHLIGHT_CLICKED_CLASS,\n LIST_CONTAINER_ELEMENT_CLASS_NAME,\n TABLE_CONTAINER,\n TEMP_ELEMENTS_CLASSES,\n WAC_IDENTIFY_SELECTOR,\n} from './constants';\nimport type {\n ContentModelBeforePasteEvent,\n ContentModelBlockFormat,\n ContentModelBlockGroup,\n ContentModelListItemLevelFormat,\n ContentModelSegmentFormat,\n DomToModelContext,\n ElementProcessor,\n FormatParser,\n} from 'roosterjs-content-model-types';\n\nconst LIST_ELEMENT_TAGS = ['UL', 'OL', 'LI'];\nconst LIST_ELEMENT_SELECTOR = LIST_ELEMENT_TAGS.join(',');\n\nconst COMMENT_BG_COLOR_REST = 'rgba(209, 209, 209, 0.5)';\nconst COMMENTS_TEXT_HIGHLIGHT_CLICKED = 'rgba(197, 139, 204, 0.5)';\n\n/**\n * Wac components do not use sub and super tags, instead only add vertical align to a span.\n * This parser normalize the content for content model\n */\nconst wacSubSuperParser: FormatParser<ContentModelSegmentFormat> = (\n format: ContentModelSegmentFormat,\n element: HTMLElement\n): void => {\n const verticalAlign = element.style.verticalAlign;\n if (verticalAlign === 'super') {\n format.superOrSubScriptSequence = 'super';\n }\n if (verticalAlign === 'sub') {\n format.superOrSubScriptSequence = 'sub';\n }\n};\n\n/**\n * This processor does:\n * 1) Remove the display and margin of the element.\n * 2) When an element should be ignored but should handle the child elements call the default child processor.\n * 3) Removes the End of Paragraph element to avoid empty lines, we should only remove this if the previous element of the EOP is an EmptyTextRun\n * 4) Finally call the default processor.\n * @returns\n */\nconst wacElementProcessor: ElementProcessor<HTMLElement> = (\n group: ContentModelBlockGroup,\n element: HTMLElement,\n context: DomToModelContext\n): void => {\n const elementTag = element.tagName;\n\n if (element.matches(WAC_IDENTIFY_SELECTOR)) {\n element.style.removeProperty('display');\n element.style.removeProperty('margin');\n }\n\n if (element.classList.contains(LIST_CONTAINER_ELEMENT_CLASS_NAME)) {\n context.elementProcessors.child(group, element, context);\n return;\n }\n\n if (TEMP_ELEMENTS_CLASSES.some(className => element.classList.contains(className))) {\n return;\n } else if (shouldClearListContext(elementTag, element, context)) {\n const { listFormat } = context;\n listFormat.levels = [];\n listFormat.listParent = undefined;\n }\n\n context.defaultElementProcessors.element(group, element, context);\n};\n\n/**\n * This processor calls the default list processor and then sets the correct list level and list bullet.\n */\nconst wacLiElementProcessor: ElementProcessor<HTMLLIElement> = (\n group: ContentModelBlockGroup,\n element: HTMLLIElement,\n context: DomToModelContext\n): void => {\n context.defaultElementProcessors.li?.(group, element, context);\n const { listFormat } = context;\n const listParent = listFormat.listParent;\n if (listParent) {\n const lastblock = listParent.blocks[listParent.blocks.length - 1];\n if (\n lastblock.blockType == 'BlockGroup' &&\n lastblock.blockGroupType == 'ListItem' &&\n context.listFormat.listParent !== lastblock\n ) {\n const currentLevel = lastblock.levels[lastblock.levels.length - 1];\n\n // Get item level from 'data-aria-level' attribute\n const level = parseInt(element.getAttribute('data-aria-level') ?? '');\n if (level > 0) {\n if (level > lastblock.levels.length) {\n while (level != lastblock.levels.length) {\n lastblock.levels.push(currentLevel);\n }\n } else {\n lastblock.levels.splice(level, lastblock.levels.length - 1);\n lastblock.levels[level - 1] = currentLevel;\n }\n }\n }\n }\n};\n\n/**\n * This parsers does:\n * 1) Sets the display for dummy item to undefined when the current style is block.\n * 2) Removes the Margin Left\n */\nconst wacListItemParser: FormatParser<ContentModelListItemLevelFormat> = (\n format: ContentModelListItemLevelFormat,\n element: HTMLElement\n): void => {\n if (element.style.display === 'block') {\n format.displayForDummyItem = undefined;\n }\n\n format.marginLeft = undefined;\n};\n\n/**\n * Wac usually adds padding to lists which is unwanted so remove it.\n */\nconst wacListLevelParser: FormatParser<ContentModelListItemLevelFormat> = (\n format: ContentModelListItemLevelFormat\n): void => {\n format.marginLeft = undefined;\n format.paddingLeft = undefined;\n};\n\n/**\n * This function returns whether we need to clear the list format.\n * Word Online wraps lists inside divs to have this structure:\n *\n * <div class='ListContainerWrapper'>\n * <ol>...</ol>\n * </div>\n * <div>\n * <p>...</p>\n * <div>\n * <div class='ListContainerWrapper'>\n * <ol>...</ol>\n * </div>\n *\n * So if a elements is not contained inside of a list we should clear the list context to prevent normal text to be\n * transformed into list\n * For the above scenario, if we do not clear the format, the content inside of the second div would be transformed to a list too.\n */\nfunction shouldClearListContext(\n elementTag: string,\n element: HTMLElement,\n context: DomToModelContext\n) {\n return (\n context.listFormat.levels.length > 0 &&\n LIST_ELEMENT_TAGS.every(tag => tag != elementTag) &&\n !element.closest(LIST_ELEMENT_SELECTOR)\n );\n}\n\nconst wacCommentParser: FormatParser<ContentModelSegmentFormat> = (\n format: ContentModelSegmentFormat,\n element: HTMLElement\n): void => {\n if (\n (element.className.includes(COMMENT_HIGHLIGHT_CLASS) &&\n element.style.backgroundColor == COMMENT_BG_COLOR_REST) ||\n (element.className.includes(COMMENT_HIGHLIGHT_CLICKED_CLASS) &&\n element.style.backgroundColor == COMMENTS_TEXT_HIGHLIGHT_CLICKED)\n ) {\n delete format.backgroundColor;\n }\n};\n/**\n * @internal\n * Convert pasted content from Office Online\n * Once it is known that the document is from WAC\n * We need to remove the display property and margin from all the list item\n * @param ev ContentModelBeforePasteEvent\n */\nexport function processPastedContentWacComponents(ev: ContentModelBeforePasteEvent) {\n addParser(ev.domToModelOption, 'segment', wacSubSuperParser);\n addParser(ev.domToModelOption, 'listItemThread', wacListItemParser);\n addParser(ev.domToModelOption, 'listLevel', wacListLevelParser);\n addParser(ev.domToModelOption, 'container', wacBlockParser);\n addParser(ev.domToModelOption, 'segment', wacCommentParser);\n\n setProcessor(ev.domToModelOption, 'element', wacElementProcessor);\n setProcessor(ev.domToModelOption, 'li', wacLiElementProcessor);\n setProcessor(ev.domToModelOption, 'ol', wacListProcessor);\n setProcessor(ev.domToModelOption, 'ul', wacListProcessor);\n ev.sanitizingOption.additionalAllowedCssClasses.push(...CLASSES_TO_KEEP);\n}\n\n/**\n * List items from word have this format when using List items:\n * @example\n <div>\n <ol></ol>\n </div>\n <div>\n <ol></ol>\n </div>\n <div>\n <ol></ol>\n </div>\n * Due to this the div between each of the lists we need to restore the list context to use the previous list,\n * otherwise it could create a new list instead under the same list element\n */\nconst wacListProcessor: ElementProcessor<HTMLOListElement | HTMLUListElement> = (\n group: ContentModelBlockGroup,\n element: HTMLOListElement | HTMLUListElement,\n context: DomToModelContext\n): void => {\n const lastBlock = group.blocks[group.blocks.length - 1];\n const isWrappedInContainer = element.closest(`.${LIST_CONTAINER_ELEMENT_CLASS_NAME}`);\n if (\n isWrappedInContainer?.previousElementSibling?.classList.contains(\n LIST_CONTAINER_ELEMENT_CLASS_NAME\n )\n ) {\n if (lastBlock?.blockType === 'BlockGroup' && lastBlock.blockGroupType == 'ListItem') {\n context.listFormat = {\n threadItemCounts: [],\n levels: lastBlock.levels,\n listParent: group,\n };\n }\n }\n if (element.tagName.toUpperCase() === 'OL') {\n context.defaultElementProcessors.ol?.(group, element as HTMLOListElement, context);\n } else {\n context.defaultElementProcessors.ul?.(group, element as HTMLUListElement, context);\n }\n};\n\nconst wacBlockParser: FormatParser<ContentModelBlockFormat> = (\n format: ContentModelBlockFormat,\n element: HTMLElement\n) => {\n if (element.classList.contains(TABLE_CONTAINER) && element.style.marginLeft.startsWith('-')) {\n delete format.marginLeft;\n }\n};\n"]}
1
+ {"version":3,"file":"processPastedContentWacComponents.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-plugins/lib/paste/WacComponents/processPastedContentWacComponents.ts"],"names":[],"mappings":"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","sourcesContent":["import addParser from '../utils/addParser';\nimport { setProcessor } from '../utils/setProcessor';\nimport {\n COMMENT_HIGHLIGHT_CLASS,\n COMMENT_HIGHLIGHT_CLICKED_CLASS,\n LIST_CONTAINER_ELEMENT_CLASS_NAME,\n TEMP_ELEMENTS_CLASSES,\n WAC_IDENTIFY_SELECTOR,\n} from './constants';\nimport type {\n ContentModelBeforePasteEvent,\n ContentModelBlockFormat,\n ContentModelBlockGroup,\n ContentModelListItemLevelFormat,\n ContentModelSegmentFormat,\n DomToModelContext,\n ElementProcessor,\n FormatParser,\n} from 'roosterjs-content-model-types';\n\nconst LIST_ELEMENT_TAGS = ['UL', 'OL', 'LI'];\nconst LIST_ELEMENT_SELECTOR = LIST_ELEMENT_TAGS.join(',');\n\nconst COMMENT_BG_COLOR_REST = 'rgba(209, 209, 209, 0.5)';\nconst COMMENTS_TEXT_HIGHLIGHT_CLICKED = 'rgba(197, 139, 204, 0.5)';\n\n/**\n * Wac components do not use sub and super tags, instead only add vertical align to a span.\n * This parser normalize the content for content model\n */\nconst wacSubSuperParser: FormatParser<ContentModelSegmentFormat> = (\n format: ContentModelSegmentFormat,\n element: HTMLElement\n): void => {\n const verticalAlign = element.style.verticalAlign;\n if (verticalAlign === 'super') {\n format.superOrSubScriptSequence = 'super';\n }\n if (verticalAlign === 'sub') {\n format.superOrSubScriptSequence = 'sub';\n }\n};\n\n/**\n * This processor does:\n * 1) Remove the display and margin of the element.\n * 2) When an element should be ignored but should handle the child elements call the default child processor.\n * 3) Removes the End of Paragraph element to avoid empty lines, we should only remove this if the previous element of the EOP is an EmptyTextRun\n * 4) Finally call the default processor.\n * @returns\n */\nconst wacElementProcessor: ElementProcessor<HTMLElement> = (\n group: ContentModelBlockGroup,\n element: HTMLElement,\n context: DomToModelContext\n): void => {\n const elementTag = element.tagName;\n\n if (element.matches(WAC_IDENTIFY_SELECTOR)) {\n element.style.removeProperty('display');\n element.style.removeProperty('margin');\n }\n\n if (element.classList.contains(LIST_CONTAINER_ELEMENT_CLASS_NAME)) {\n context.elementProcessors.child(group, element, context);\n return;\n }\n\n if (TEMP_ELEMENTS_CLASSES.some(className => element.classList.contains(className))) {\n return;\n } else if (shouldClearListContext(elementTag, element, context)) {\n const { listFormat } = context;\n listFormat.levels = [];\n listFormat.listParent = undefined;\n }\n\n context.defaultElementProcessors.element(group, element, context);\n};\n\n/**\n * This processor calls the default list processor and then sets the correct list level and list bullet.\n */\nconst wacLiElementProcessor: ElementProcessor<HTMLLIElement> = (\n group: ContentModelBlockGroup,\n element: HTMLLIElement,\n context: DomToModelContext\n): void => {\n context.defaultElementProcessors.li?.(group, element, context);\n const { listFormat } = context;\n const listParent = listFormat.listParent;\n if (listParent) {\n const lastblock = listParent.blocks[listParent.blocks.length - 1];\n if (\n lastblock.blockType == 'BlockGroup' &&\n lastblock.blockGroupType == 'ListItem' &&\n context.listFormat.listParent !== lastblock\n ) {\n const currentLevel = lastblock.levels[lastblock.levels.length - 1];\n\n // Get item level from 'data-aria-level' attribute\n const level = parseInt(element.getAttribute('data-aria-level') ?? '');\n if (level > 0) {\n if (level > lastblock.levels.length) {\n while (level != lastblock.levels.length) {\n lastblock.levels.push(currentLevel);\n }\n } else {\n lastblock.levels.splice(level, lastblock.levels.length - 1);\n lastblock.levels[level - 1] = currentLevel;\n }\n }\n }\n }\n};\n\n/**\n * This parsers does:\n * 1) Sets the display for dummy item to undefined when the current style is block.\n * 2) Removes the Margin Left\n */\nconst wacListItemParser: FormatParser<ContentModelListItemLevelFormat> = (\n format: ContentModelListItemLevelFormat,\n element: HTMLElement\n): void => {\n if (element.style.display === 'block') {\n format.displayForDummyItem = undefined;\n }\n\n format.marginLeft = undefined;\n};\n\n/**\n * Wac usually adds padding to lists which is unwanted so remove it.\n */\nconst wacListLevelParser: FormatParser<ContentModelListItemLevelFormat> = (\n format: ContentModelListItemLevelFormat\n): void => {\n format.marginLeft = undefined;\n format.paddingLeft = undefined;\n};\n\n/**\n * This function returns whether we need to clear the list format.\n * Word Online wraps lists inside divs to have this structure:\n *\n * <div class='ListContainerWrapper'>\n * <ol>...</ol>\n * </div>\n * <div>\n * <p>...</p>\n * <div>\n * <div class='ListContainerWrapper'>\n * <ol>...</ol>\n * </div>\n *\n * So if a elements is not contained inside of a list we should clear the list context to prevent normal text to be\n * transformed into list\n * For the above scenario, if we do not clear the format, the content inside of the second div would be transformed to a list too.\n */\nfunction shouldClearListContext(\n elementTag: string,\n element: HTMLElement,\n context: DomToModelContext\n) {\n return (\n context.listFormat.levels.length > 0 &&\n LIST_ELEMENT_TAGS.every(tag => tag != elementTag) &&\n !element.closest(LIST_ELEMENT_SELECTOR)\n );\n}\n\nconst wacCommentParser: FormatParser<ContentModelSegmentFormat> = (\n format: ContentModelSegmentFormat,\n element: HTMLElement\n): void => {\n if (\n (element.className.includes(COMMENT_HIGHLIGHT_CLASS) &&\n element.style.backgroundColor == COMMENT_BG_COLOR_REST) ||\n (element.className.includes(COMMENT_HIGHLIGHT_CLICKED_CLASS) &&\n element.style.backgroundColor == COMMENTS_TEXT_HIGHLIGHT_CLICKED)\n ) {\n delete format.backgroundColor;\n }\n};\n/**\n * @internal\n * Convert pasted content from Office Online\n * Once it is known that the document is from WAC\n * We need to remove the display property and margin from all the list item\n * @param ev ContentModelBeforePasteEvent\n */\nexport function processPastedContentWacComponents(ev: ContentModelBeforePasteEvent) {\n addParser(ev.domToModelOption, 'segment', wacSubSuperParser);\n addParser(ev.domToModelOption, 'listItemThread', wacListItemParser);\n addParser(ev.domToModelOption, 'listLevel', wacListLevelParser);\n addParser(ev.domToModelOption, 'container', wacContainerParser);\n addParser(ev.domToModelOption, 'table', wacContainerParser);\n addParser(ev.domToModelOption, 'segment', wacCommentParser);\n\n setProcessor(ev.domToModelOption, 'element', wacElementProcessor);\n setProcessor(ev.domToModelOption, 'li', wacLiElementProcessor);\n setProcessor(ev.domToModelOption, 'ol', wacListProcessor);\n setProcessor(ev.domToModelOption, 'ul', wacListProcessor);\n}\n\n/**\n * List items from word have this format when using List items:\n * @example\n <div>\n <ol></ol>\n </div>\n <div>\n <ol></ol>\n </div>\n <div>\n <ol></ol>\n </div>\n * Due to this the div between each of the lists we need to restore the list context to use the previous list,\n * otherwise it could create a new list instead under the same list element\n */\nconst wacListProcessor: ElementProcessor<HTMLOListElement | HTMLUListElement> = (\n group: ContentModelBlockGroup,\n element: HTMLOListElement | HTMLUListElement,\n context: DomToModelContext\n): void => {\n const lastBlock = group.blocks[group.blocks.length - 1];\n const isWrappedInContainer = element.closest(`.${LIST_CONTAINER_ELEMENT_CLASS_NAME}`);\n if (\n isWrappedInContainer?.previousElementSibling?.classList.contains(\n LIST_CONTAINER_ELEMENT_CLASS_NAME\n )\n ) {\n if (lastBlock?.blockType === 'BlockGroup' && lastBlock.blockGroupType == 'ListItem') {\n context.listFormat = {\n threadItemCounts: [],\n levels: lastBlock.levels,\n listParent: group,\n };\n }\n }\n if (element.tagName.toUpperCase() === 'OL') {\n context.defaultElementProcessors.ol?.(group, element as HTMLOListElement, context);\n } else {\n context.defaultElementProcessors.ul?.(group, element as HTMLUListElement, context);\n }\n};\n\nconst wacContainerParser: FormatParser<ContentModelBlockFormat> = (\n format: ContentModelBlockFormat,\n element: HTMLElement\n) => {\n if (element.style.marginLeft.startsWith('-')) {\n delete format.marginLeft;\n }\n};\n"]}
@@ -60,7 +60,7 @@ export default function getStyleMetadata(ev, trustedHTMLHandler) {
60
60
  });
61
61
  var data = {
62
62
  'mso-level-number-format': record['mso-level-number-format'],
63
- 'mso-level-start-at': record['mso-level-start-at'],
63
+ 'mso-level-start-at': record['mso-level-start-at'] || '1',
64
64
  'mso-level-text': record['mso-level-text'],
65
65
  };
66
66
  if (getObjectKeys(data).some(function (key) { return !!data[key]; })) {
@@ -1 +1 @@
1
- {"version":3,"file":"getStyleMetadata.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-plugins/lib/paste/WordDesktop/getStyleMetadata.ts"],"names":[],"mappings":"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","sourcesContent":["import { getObjectKeys } from 'roosterjs-content-model-dom';\nimport type { WordMetadata } from './WordMetadata';\nimport type { ContentModelBeforePasteEvent } from 'roosterjs-content-model-types';\n\nconst FORMATING_REGEX = /[\\n\\t'{}\"]+/g;\n\n/**\n * @internal\n * Word Desktop content has a style tag that contains data for the lists.\n * So this function query that style tag and extract the data from the innerHTML, since it is not available from the HTMLStyleElement.sheet.\n *\n * The format is like:\n * example of style element content\n * @list l0:level1 {\n * styleTag: styleValue;\n * ...\n * }\n *\n * To extract the data:\n * 1. Substring the value of the style selector, using @ index and { index\n * 2. Substring the value of the style rules by Substring the content between { and }\n * 3. Split the value of the rules using ; as separator { styleTag: styleValue; styleTag1: StyleValue1 } = ['styleTag: styleValue', 'styleTag1: StyleValue1']\n * 4. Split the value of the rule using : as separator: styleTag: styleValue = [styleTag, styleValue]\n * 5. Save data in record and only use the required information.\n *\n */\nexport default function getStyleMetadata(\n ev: ContentModelBeforePasteEvent,\n trustedHTMLHandler: (val: string) => string\n) {\n const metadataMap: Map<string, WordMetadata> = new Map();\n const doc = new DOMParser().parseFromString(trustedHTMLHandler(ev.htmlBefore), 'text/html');\n const styles = doc.querySelectorAll('style');\n\n styles.forEach(style => {\n const text = style?.innerHTML.trim() || '';\n\n let index = 0;\n while (index >= 0) {\n const indexAt = text.indexOf('@', index + 1);\n const indexCurlyEnd = text.indexOf('}', indexAt);\n const indexCurlyStart = text.indexOf('{', indexAt);\n index = indexAt;\n\n // 1.\n const metadataName = text\n .substring(indexAt + 1, indexCurlyStart)\n .replace(FORMATING_REGEX, '')\n .replace('list', '')\n .trimRight()\n .trimLeft();\n\n // 2.\n const dataName = text\n .substring(indexCurlyStart, indexCurlyEnd + 1)\n .trimLeft()\n .trimRight();\n const record: Record<string, string> = {};\n\n // 3.\n const entries = dataName.split(';');\n entries.forEach(entry => {\n // 4.\n const [key, value] = entry.split(':');\n if (key && value) {\n const formatedKey = key.replace(FORMATING_REGEX, '').trimRight().trimLeft();\n const formatedValue = value.replace(FORMATING_REGEX, '').trimRight().trimLeft();\n // 5.\n record[formatedKey] = formatedValue;\n }\n });\n\n const data: WordMetadata = {\n 'mso-level-number-format': record['mso-level-number-format'],\n 'mso-level-start-at': record['mso-level-start-at'],\n 'mso-level-text': record['mso-level-text'],\n };\n if (getObjectKeys(data).some(key => !!data[key])) {\n metadataMap.set(metadataName, data);\n }\n }\n });\n return metadataMap;\n}\n"]}
1
+ {"version":3,"file":"getStyleMetadata.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-plugins/lib/paste/WordDesktop/getStyleMetadata.ts"],"names":[],"mappings":"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","sourcesContent":["import { getObjectKeys } from 'roosterjs-content-model-dom';\nimport type { WordMetadata } from './WordMetadata';\nimport type { ContentModelBeforePasteEvent } from 'roosterjs-content-model-types';\n\nconst FORMATING_REGEX = /[\\n\\t'{}\"]+/g;\n\n/**\n * @internal\n * Word Desktop content has a style tag that contains data for the lists.\n * So this function query that style tag and extract the data from the innerHTML, since it is not available from the HTMLStyleElement.sheet.\n *\n * The format is like:\n * example of style element content\n * @list l0:level1 {\n * styleTag: styleValue;\n * ...\n * }\n *\n * To extract the data:\n * 1. Substring the value of the style selector, using @ index and { index\n * 2. Substring the value of the style rules by Substring the content between { and }\n * 3. Split the value of the rules using ; as separator { styleTag: styleValue; styleTag1: StyleValue1 } = ['styleTag: styleValue', 'styleTag1: StyleValue1']\n * 4. Split the value of the rule using : as separator: styleTag: styleValue = [styleTag, styleValue]\n * 5. Save data in record and only use the required information.\n *\n */\nexport default function getStyleMetadata(\n ev: ContentModelBeforePasteEvent,\n trustedHTMLHandler: (val: string) => string\n) {\n const metadataMap: Map<string, WordMetadata> = new Map();\n const doc = new DOMParser().parseFromString(trustedHTMLHandler(ev.htmlBefore), 'text/html');\n const styles = doc.querySelectorAll('style');\n\n styles.forEach(style => {\n const text = style?.innerHTML.trim() || '';\n\n let index = 0;\n while (index >= 0) {\n const indexAt = text.indexOf('@', index + 1);\n const indexCurlyEnd = text.indexOf('}', indexAt);\n const indexCurlyStart = text.indexOf('{', indexAt);\n index = indexAt;\n\n // 1.\n const metadataName = text\n .substring(indexAt + 1, indexCurlyStart)\n .replace(FORMATING_REGEX, '')\n .replace('list', '')\n .trimRight()\n .trimLeft();\n\n // 2.\n const dataName = text\n .substring(indexCurlyStart, indexCurlyEnd + 1)\n .trimLeft()\n .trimRight();\n const record: Record<string, string> = {};\n\n // 3.\n const entries = dataName.split(';');\n entries.forEach(entry => {\n // 4.\n const [key, value] = entry.split(':');\n if (key && value) {\n const formatedKey = key.replace(FORMATING_REGEX, '').trimRight().trimLeft();\n const formatedValue = value.replace(FORMATING_REGEX, '').trimRight().trimLeft();\n // 5.\n record[formatedKey] = formatedValue;\n }\n });\n\n const data: WordMetadata = {\n 'mso-level-number-format': record['mso-level-number-format'],\n 'mso-level-start-at': record['mso-level-start-at'] || '1',\n 'mso-level-text': record['mso-level-text'],\n };\n if (getObjectKeys(data).some(key => !!data[key])) {\n metadataMap.set(metadataName, data);\n }\n }\n });\n return metadataMap;\n}\n"]}
@@ -1,8 +1,6 @@
1
1
  import addParser from '../utils/addParser';
2
2
  import getStyleMetadata from './getStyleMetadata';
3
- import { chainSanitizerCallback } from 'roosterjs-editor-dom';
4
3
  import { getStyles } from '../utils/getStyles';
5
- import { moveChildNodes } from 'roosterjs-content-model-dom';
6
4
  import { processWordComments } from './processWordComments';
7
5
  import { processWordList } from './processWordLists';
8
6
  import { setProcessor } from '../utils/setProcessor';
@@ -18,17 +16,8 @@ export function processPastedContentFromWordDesktop(ev, trustedHTMLHandler) {
18
16
  setProcessor(ev.domToModelOption, 'element', wordDesktopElementProcessor(metadataMap));
19
17
  addParser(ev.domToModelOption, 'block', removeNonValidLineHeight);
20
18
  addParser(ev.domToModelOption, 'listLevel', listLevelParser);
21
- addParser(ev.domToModelOption, 'listItemElement', listItemElementParser);
22
- // Remove "border:none" for image to fix image resize behavior
23
- // We found a problem that when paste an image with "border:none" then the resize border will be
24
- // displayed incorrectly when resize it. So we need to drop this style
25
- chainSanitizerCallback(ev.sanitizingOption.cssStyleCallbacks, 'border', function (value, element) { return element.tagName != 'IMG' || value != 'none'; });
26
- // Preserve <o:p> when its innerHTML is "&nbsp;" to avoid dropping an empty line
27
- chainSanitizerCallback(ev.sanitizingOption.elementCallbacks, 'O:P', function (element) {
28
- moveChildNodes(element);
29
- element.appendChild(element.ownerDocument.createTextNode('\u00A0')); // &nbsp;
30
- return true;
31
- });
19
+ addParser(ev.domToModelOption, 'container', wordTableParser);
20
+ addParser(ev.domToModelOption, 'table', wordTableParser);
32
21
  }
33
22
  var wordDesktopElementProcessor = function (metadataKey) {
34
23
  return function (group, element, context) {
@@ -55,12 +44,10 @@ function listLevelParser(format, element, context, defaultStyle) {
55
44
  }
56
45
  format.marginBottom = undefined;
57
46
  }
58
- var listItemElementParser = function (format, element) {
59
- if (element.style.marginLeft) {
60
- format.marginLeft = undefined;
61
- }
62
- if (element.style.marginRight) {
63
- format.marginRight = undefined;
47
+ var wordTableParser = function (format) {
48
+ var _a;
49
+ if ((_a = format.marginLeft) === null || _a === void 0 ? void 0 : _a.startsWith('-')) {
50
+ delete format.marginLeft;
64
51
  }
65
52
  };
66
53
  //# sourceMappingURL=processPastedContentFromWordDesktop.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"processPastedContentFromWordDesktop.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-plugins/lib/paste/WordDesktop/processPastedContentFromWordDesktop.ts"],"names":[],"mappings":"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","sourcesContent":["import addParser from '../utils/addParser';\nimport getStyleMetadata from './getStyleMetadata';\nimport { chainSanitizerCallback } from 'roosterjs-editor-dom';\nimport { getStyles } from '../utils/getStyles';\nimport { moveChildNodes } from 'roosterjs-content-model-dom';\nimport { processWordComments } from './processWordComments';\nimport { processWordList } from './processWordLists';\nimport { setProcessor } from '../utils/setProcessor';\nimport type { WordMetadata } from './WordMetadata';\nimport type {\n ContentModelBeforePasteEvent,\n ContentModelBlockFormat,\n ContentModelListItemFormat,\n ContentModelListItemLevelFormat,\n DomToModelContext,\n ElementProcessor,\n FormatParser,\n} from 'roosterjs-content-model-types';\n\nconst PERCENTAGE_REGEX = /%/;\nconst DEFAULT_BROWSER_LINE_HEIGHT_PERCENTAGE = 120;\n\n/**\n * @internal\n * Handles Pasted content when source is Word Desktop\n * @param ev ContentModelBeforePasteEvent\n */\nexport function processPastedContentFromWordDesktop(\n ev: ContentModelBeforePasteEvent,\n trustedHTMLHandler: (text: string) => string\n) {\n const metadataMap: Map<string, WordMetadata> = getStyleMetadata(ev, trustedHTMLHandler);\n\n setProcessor(ev.domToModelOption, 'element', wordDesktopElementProcessor(metadataMap));\n addParser(ev.domToModelOption, 'block', removeNonValidLineHeight);\n addParser(ev.domToModelOption, 'listLevel', listLevelParser);\n addParser(ev.domToModelOption, 'listItemElement', listItemElementParser);\n\n // Remove \"border:none\" for image to fix image resize behavior\n // We found a problem that when paste an image with \"border:none\" then the resize border will be\n // displayed incorrectly when resize it. So we need to drop this style\n chainSanitizerCallback(\n ev.sanitizingOption.cssStyleCallbacks,\n 'border',\n (value, element) => element.tagName != 'IMG' || value != 'none'\n );\n\n // Preserve <o:p> when its innerHTML is \"&nbsp;\" to avoid dropping an empty line\n chainSanitizerCallback(ev.sanitizingOption.elementCallbacks, 'O:P', element => {\n moveChildNodes(element);\n element.appendChild(element.ownerDocument.createTextNode('\\u00A0')); // &nbsp;\n return true;\n });\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\nfunction removeNonValidLineHeight(\n format: ContentModelBlockFormat,\n element: HTMLElement,\n context: DomToModelContext,\n defaultStyle: Readonly<Partial<CSSStyleDeclaration>>\n): void {\n //If the line height is less than the browser default line height, line between the text is going to be too narrow\n let parsedLineHeight: number;\n if (\n PERCENTAGE_REGEX.test(element.style.lineHeight) &&\n !isNaN((parsedLineHeight = parseInt(element.style.lineHeight))) &&\n parsedLineHeight < DEFAULT_BROWSER_LINE_HEIGHT_PERCENTAGE\n ) {\n format.lineHeight = defaultStyle.lineHeight;\n }\n}\n\nfunction listLevelParser(\n format: ContentModelListItemLevelFormat,\n element: HTMLElement,\n context: DomToModelContext,\n defaultStyle: Readonly<Partial<CSSStyleDeclaration>>\n): void {\n if (element.style.marginLeft != '') {\n format.marginLeft = defaultStyle.marginLeft;\n }\n\n format.marginBottom = undefined;\n}\n\nconst listItemElementParser: FormatParser<ContentModelListItemFormat> = (\n format: ContentModelListItemFormat,\n element: HTMLElement\n): void => {\n if (element.style.marginLeft) {\n format.marginLeft = undefined;\n }\n if (element.style.marginRight) {\n format.marginRight = undefined;\n }\n};\n"]}
1
+ {"version":3,"file":"processPastedContentFromWordDesktop.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-plugins/lib/paste/WordDesktop/processPastedContentFromWordDesktop.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAC3C,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAYrD,IAAM,gBAAgB,GAAG,GAAG,CAAC;AAC7B,IAAM,sCAAsC,GAAG,GAAG,CAAC;AAEnD;;;;GAIG;AACH,MAAM,UAAU,mCAAmC,CAC/C,EAAgC,EAChC,kBAA4C;IAE5C,IAAM,WAAW,GAA8B,gBAAgB,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC;IAExF,YAAY,CAAC,EAAE,CAAC,gBAAgB,EAAE,SAAS,EAAE,2BAA2B,CAAC,WAAW,CAAC,CAAC,CAAC;IACvF,SAAS,CAAC,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,wBAAwB,CAAC,CAAC;IAClE,SAAS,CAAC,EAAE,CAAC,gBAAgB,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;IAC7D,SAAS,CAAC,EAAE,CAAC,gBAAgB,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;IAC7D,SAAS,CAAC,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;AAC7D,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;AAEF,SAAS,wBAAwB,CAC7B,MAA+B,EAC/B,OAAoB,EACpB,OAA0B,EAC1B,YAAoD;IAEpD,kHAAkH;IAClH,IAAI,gBAAwB,CAAC;IAC7B,IACI,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC;QAC/C,CAAC,KAAK,CAAC,CAAC,gBAAgB,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;QAC/D,gBAAgB,GAAG,sCAAsC,EAC3D;QACE,MAAM,CAAC,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC;KAC/C;AACL,CAAC;AAED,SAAS,eAAe,CACpB,MAAuC,EACvC,OAAoB,EACpB,OAA0B,EAC1B,YAAoD;IAEpD,IAAI,OAAO,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,EAAE;QAChC,MAAM,CAAC,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC;KAC/C;IAED,MAAM,CAAC,YAAY,GAAG,SAAS,CAAC;AACpC,CAAC;AAED,IAAM,eAAe,GAA0C,UAAC,MAAM;;IAClE,IAAI,MAAA,MAAM,CAAC,UAAU,0CAAE,UAAU,CAAC,GAAG,CAAC,EAAE;QACpC,OAAO,MAAM,CAAC,UAAU,CAAC;KAC5B;AACL,CAAC,CAAC","sourcesContent":["import addParser from '../utils/addParser';\nimport getStyleMetadata from './getStyleMetadata';\nimport { getStyles } from '../utils/getStyles';\nimport { processWordComments } from './processWordComments';\nimport { processWordList } from './processWordLists';\nimport { setProcessor } from '../utils/setProcessor';\nimport type { WordMetadata } from './WordMetadata';\nimport type {\n ContentModelBeforePasteEvent,\n ContentModelBlockFormat,\n ContentModelListItemLevelFormat,\n ContentModelTableFormat,\n DomToModelContext,\n ElementProcessor,\n FormatParser,\n} from 'roosterjs-content-model-types';\n\nconst PERCENTAGE_REGEX = /%/;\nconst DEFAULT_BROWSER_LINE_HEIGHT_PERCENTAGE = 120;\n\n/**\n * @internal\n * Handles Pasted content when source is Word Desktop\n * @param ev ContentModelBeforePasteEvent\n */\nexport function processPastedContentFromWordDesktop(\n ev: ContentModelBeforePasteEvent,\n trustedHTMLHandler: (text: string) => string\n) {\n const metadataMap: Map<string, WordMetadata> = getStyleMetadata(ev, trustedHTMLHandler);\n\n setProcessor(ev.domToModelOption, 'element', wordDesktopElementProcessor(metadataMap));\n addParser(ev.domToModelOption, 'block', removeNonValidLineHeight);\n addParser(ev.domToModelOption, 'listLevel', listLevelParser);\n addParser(ev.domToModelOption, 'container', wordTableParser);\n addParser(ev.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\nfunction removeNonValidLineHeight(\n format: ContentModelBlockFormat,\n element: HTMLElement,\n context: DomToModelContext,\n defaultStyle: Readonly<Partial<CSSStyleDeclaration>>\n): void {\n //If the line height is less than the browser default line height, line between the text is going to be too narrow\n let parsedLineHeight: number;\n if (\n PERCENTAGE_REGEX.test(element.style.lineHeight) &&\n !isNaN((parsedLineHeight = parseInt(element.style.lineHeight))) &&\n parsedLineHeight < DEFAULT_BROWSER_LINE_HEIGHT_PERCENTAGE\n ) {\n format.lineHeight = defaultStyle.lineHeight;\n }\n}\n\nfunction listLevelParser(\n format: ContentModelListItemLevelFormat,\n element: HTMLElement,\n context: DomToModelContext,\n defaultStyle: Readonly<Partial<CSSStyleDeclaration>>\n): void {\n if (element.style.marginLeft != '') {\n format.marginLeft = defaultStyle.marginLeft;\n }\n\n format.marginBottom = undefined;\n}\n\nconst wordTableParser: FormatParser<ContentModelTableFormat> = (format): void => {\n if (format.marginLeft?.startsWith('-')) {\n delete format.marginLeft;\n }\n};\n"]}
@@ -1,6 +1,6 @@
1
1
  import { __read, __spreadArray } from "tslib";
2
2
  import { getListStyleTypeFromString, updateListMetadata } from 'roosterjs-content-model-core';
3
- import { addBlock, createListItem, createListLevel, parseFormat, } from 'roosterjs-content-model-dom';
3
+ import { addBlock, createListItem, createListLevel, isEmpty, parseFormat, } from 'roosterjs-content-model-dom';
4
4
  /** Word list metadata style name */
5
5
  var MSO_LIST = 'mso-list';
6
6
  var MSO_LIST_IGNORE = 'ignore';
@@ -45,7 +45,7 @@ export function processWordList(styles, group, element, context, metadata) {
45
45
  : 'UL';
46
46
  // Create the new level of the list item and parse the format
47
47
  var newLevel = createListLevel(listType);
48
- parseFormat(element, context.formatParsers.listLevel, newLevel.format, context);
48
+ parseFormat(element, __spreadArray(__spreadArray([], __read(context.formatParsers.listLevel), false), [wordListPaddingParser], false), newLevel.format, context);
49
49
  // If the list format is in a different level, update the array so we get the new item
50
50
  // To be in the same level as the provided level metadata.
51
51
  if (wordLevel > listFormat.levels.length) {
@@ -57,6 +57,8 @@ export function processWordList(styles, group, element, context, metadata) {
57
57
  listFormat.levels.splice(wordLevel, listFormat.levels.length - 1);
58
58
  listFormat.levels[wordLevel - 1] = newLevel;
59
59
  }
60
+ listFormat.levels[listFormat.levels.length - 1]
61
+ .format.wordList = wordList;
60
62
  listFormat.listParent = group;
61
63
  processAsListItem(listFormat, context, element, group, listMetadata);
62
64
  if (listFormat.levels.length > 0 &&
@@ -83,7 +85,7 @@ function processAsListItem(listFormat, context, element, group, listMetadata) {
83
85
  parseFormat(element, context.formatParsers.segmentOnBlock, context.segmentFormat, context);
84
86
  parseFormat(element, context.formatParsers.listItemElement, listItem.format, context);
85
87
  if (listType == 'OL') {
86
- parseFormat(element, [startNumberOverrideParser(listMetadata)], listItem.levels[listItem.levels.length - 1].format, context);
88
+ setStartNumber(listItem, context, listMetadata);
87
89
  }
88
90
  context.elementProcessors.child(listItem, element, context);
89
91
  addBlock(group, listItem);
@@ -134,16 +136,39 @@ function getBulletFromMetadata(listMetadata, listType) {
134
136
  }
135
137
  return getListStyleTypeFromString(listType, templateFinal);
136
138
  }
137
- function startNumberOverrideParser(listMetadata) {
138
- return function (format, _, context) {
139
- var _a = context.listFormat, wordKnownLevels = _a.wordKnownLevels, wordLevel = _a.wordLevel, wordList = _a.wordList, levels = _a.levels;
140
- if (typeof wordLevel === 'number' && wordList) {
141
- var start = parseInt((listMetadata === null || listMetadata === void 0 ? void 0 : listMetadata['mso-level-start-at']) || '1');
142
- var knownLevel = (wordKnownLevels === null || wordKnownLevels === void 0 ? void 0 : wordKnownLevels.get(wordList)) || [];
143
- if (start != undefined && !isNaN(start) && knownLevel.length != levels.length) {
144
- format.startNumberOverride = start;
145
- }
139
+ function wordListPaddingParser(format, element) {
140
+ if (element.style.marginLeft && element.style.marginLeft != '0in') {
141
+ format.paddingLeft = '0px';
142
+ }
143
+ if (element.style.marginRight && element.style.marginRight != '0in') {
144
+ format.paddingRight = '0px';
145
+ }
146
+ }
147
+ function setStartNumber(listItem, context, listMetadata) {
148
+ var _a, _b;
149
+ var _c = context.listFormat, listParent = _c.listParent, wordList = _c.wordList, wordKnownLevels = _c.wordKnownLevels, wordLevel = _c.wordLevel, levels = _c.levels;
150
+ var block = getLastNotEmptyBlock(listParent);
151
+ if (((block === null || block === void 0 ? void 0 : block.blockType) != 'BlockGroup' ||
152
+ block.blockGroupType != 'ListItem' ||
153
+ (wordLevel &&
154
+ ((_b = (_a = block.levels[wordLevel]) === null || _a === void 0 ? void 0 : _a.format) === null || _b === void 0 ? void 0 : _b.wordList) != wordList)) &&
155
+ wordList) {
156
+ var start = (listMetadata === null || listMetadata === void 0 ? void 0 : listMetadata['mso-level-start-at'])
157
+ ? parseInt(listMetadata['mso-level-start-at'])
158
+ : NaN;
159
+ var knownLevel = (wordKnownLevels === null || wordKnownLevels === void 0 ? void 0 : wordKnownLevels.get(wordList)) || [];
160
+ if (start != undefined && !isNaN(start) && knownLevel.length != levels.length) {
161
+ listItem.levels[listItem.levels.length - 1].format.startNumberOverride = start;
146
162
  }
147
- };
163
+ }
164
+ }
165
+ function getLastNotEmptyBlock(listParent) {
166
+ for (var index = ((listParent === null || listParent === void 0 ? void 0 : listParent.blocks.length) || 0) - 1; index > 0; index--) {
167
+ var result = listParent === null || listParent === void 0 ? void 0 : listParent.blocks[index];
168
+ if (result && !isEmpty(result)) {
169
+ return result;
170
+ }
171
+ }
172
+ return undefined;
148
173
  }
149
174
  //# sourceMappingURL=processWordLists.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"processWordLists.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-plugins/lib/paste/WordDesktop/processWordLists.ts"],"names":[],"mappings":"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","sourcesContent":["import { getListStyleTypeFromString, updateListMetadata } from 'roosterjs-content-model-core';\nimport type { WordMetadata } from './WordMetadata';\nimport {\n addBlock,\n createListItem,\n createListLevel,\n parseFormat,\n} from 'roosterjs-content-model-dom';\nimport type {\n ContentModelBlockGroup,\n ContentModelListItemLevelFormat,\n ContentModelListLevel,\n DomToModelContext,\n DomToModelListFormat,\n FormatParser,\n} from 'roosterjs-content-model-types';\n\n/** Word list metadata style name */\nconst MSO_LIST = 'mso-list';\nconst MSO_LIST_IGNORE = 'ignore';\nconst WORD_FIRST_LIST = 'l0';\n\nconst TEMPLATE_VALUE_REGEX = /%[0-9a-zA-Z]+/g;\n\ninterface WordDesktopListFormat extends DomToModelListFormat {\n wordLevel?: number | '';\n wordList?: string;\n wordKnownLevels?: Map<string, ContentModelListLevel[]>;\n}\n\nconst BULLET_METADATA = 'bullet';\n/**\n * @internal\n * @param styles\n * @param group\n * @param element\n * @param context\n * @returns\n */\nexport function processWordList(\n styles: Record<string, string>,\n group: ContentModelBlockGroup,\n element: HTMLElement,\n context: DomToModelContext,\n metadata: Map<string, WordMetadata>\n) {\n const listFormat = context.listFormat as WordDesktopListFormat;\n if (!listFormat.wordKnownLevels) {\n listFormat.wordKnownLevels = new Map<string, ContentModelListLevel[]>();\n }\n const wordListStyle = styles[MSO_LIST] || '';\n\n // If the element contains Ignore style, do not process it,\n // Usually this element contains the fake bullet used in Word Desktop.\n if (wordListStyle.toLowerCase() === MSO_LIST_IGNORE) {\n return true;\n }\n\n const [lNumber, level] = wordListStyle.split(' ');\n // Try get the list metadata from word, which follows this format: l1 level1 lfo2\n // If we are able to get the level property means we can process this element to be a list\n listFormat.wordLevel = level && parseInt(level.substr('level'.length));\n\n listFormat.wordList = lNumber || WORD_FIRST_LIST;\n if (listFormat.levels.length == 0) {\n listFormat.levels =\n (listFormat.wordList && listFormat.wordKnownLevels.get(listFormat.wordList)) || [];\n }\n\n if (wordListStyle && group && typeof listFormat.wordLevel === 'number') {\n const { wordLevel, wordList } = listFormat;\n // Retrieve the Fake bullet on the element and also the list type\n const listMetadata = metadata.get(`${lNumber}:${level}`);\n const listType =\n listMetadata?.['mso-level-number-format']?.toLowerCase() != BULLET_METADATA\n ? 'OL'\n : 'UL';\n\n // Create the new level of the list item and parse the format\n const newLevel: ContentModelListLevel = createListLevel(listType);\n parseFormat(element, context.formatParsers.listLevel, newLevel.format, context);\n\n // If the list format is in a different level, update the array so we get the new item\n // To be in the same level as the provided level metadata.\n if (wordLevel > listFormat.levels.length) {\n while (wordLevel != listFormat.levels.length) {\n listFormat.levels.push(newLevel);\n }\n } else {\n listFormat.levels.splice(wordLevel, listFormat.levels.length - 1);\n listFormat.levels[wordLevel - 1] = newLevel;\n }\n\n listFormat.listParent = group;\n\n processAsListItem(listFormat, context, element, group, listMetadata);\n\n if (\n listFormat.levels.length > 0 &&\n listFormat.wordKnownLevels.get(wordList) != listFormat.levels\n ) {\n listFormat.wordKnownLevels.set(wordList, [...listFormat.levels]);\n }\n return true;\n }\n\n return false;\n}\n\nfunction processAsListItem(\n listFormat: WordDesktopListFormat,\n context: DomToModelContext,\n element: HTMLElement,\n group: ContentModelBlockGroup,\n listMetadata: WordMetadata | undefined\n) {\n const listLevel = listFormat.levels[listFormat.levels.length - 1];\n const { listType } = listLevel;\n const bullet = getBulletFromMetadata(listMetadata, listType);\n if (bullet) {\n updateListMetadata(listFormat.levels[listFormat.levels.length - 1], metadata =>\n Object.assign({}, metadata, {\n unorderedStyleType: listType == 'UL' ? bullet : undefined,\n orderedStyleType: listType == 'OL' ? bullet : undefined,\n })\n );\n }\n\n const listItem = createListItem(listFormat.levels, context.segmentFormat);\n\n parseFormat(element, context.formatParsers.segmentOnBlock, context.segmentFormat, context);\n parseFormat(element, context.formatParsers.listItemElement, listItem.format, context);\n\n if (listType == 'OL') {\n parseFormat(\n element,\n [startNumberOverrideParser(listMetadata)],\n listItem.levels[listItem.levels.length - 1].format,\n context\n );\n }\n\n context.elementProcessors.child(listItem, element, context);\n addBlock(group, listItem);\n}\n\nfunction getBulletFromMetadata(listMetadata: WordMetadata | undefined, listType: 'OL' | 'UL') {\n const templateType = listMetadata?.['mso-level-number-format'] || 'decimal';\n let templateFinal: string;\n\n if (listMetadata?.['mso-level-text']) {\n let templateValue: string = '';\n switch (templateType) {\n case 'alpha-upper':\n templateValue = 'UpperAlpha';\n break;\n case 'alpha-lower':\n templateValue = 'LowerAlpha';\n break;\n case 'roman-lower':\n templateValue = 'LowerRoman';\n break;\n case 'roman-upper':\n templateValue = 'UpperRoman';\n break;\n default:\n templateValue = 'Number';\n break;\n }\n const template = (listMetadata['mso-level-text'] || '')\n .replace('\\\\', '')\n .replace('\"', '')\n .replace(TEMPLATE_VALUE_REGEX, '${' + templateValue + '}');\n\n templateFinal = '\"' + template + ' \"';\n } else {\n switch (templateType) {\n case 'alpha-lower':\n templateFinal = 'lower-alpha';\n break;\n case 'roman-lower':\n templateFinal = 'lower-roman';\n break;\n case 'roman-upper':\n templateFinal = 'upper-roman';\n break;\n default:\n templateFinal = 'decimal';\n break;\n }\n }\n\n return getListStyleTypeFromString(listType, templateFinal);\n}\n\nfunction startNumberOverrideParser(\n listMetadata: WordMetadata | undefined\n): FormatParser<ContentModelListItemLevelFormat> | null {\n return (format, _, context) => {\n const {\n wordKnownLevels,\n wordLevel,\n wordList,\n levels,\n } = context.listFormat as WordDesktopListFormat;\n if (typeof wordLevel === 'number' && wordList) {\n const start = parseInt(listMetadata?.['mso-level-start-at'] || '1');\n const knownLevel = wordKnownLevels?.get(wordList) || [];\n\n if (start != undefined && !isNaN(start) && knownLevel.length != levels.length) {\n format.startNumberOverride = start;\n }\n }\n };\n}\n"]}
1
+ {"version":3,"file":"processWordLists.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-plugins/lib/paste/WordDesktop/processWordLists.ts"],"names":[],"mappings":"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","sourcesContent":["import { getListStyleTypeFromString, updateListMetadata } from 'roosterjs-content-model-core';\nimport type { WordMetadata } from './WordMetadata';\nimport {\n addBlock,\n createListItem,\n createListLevel,\n isEmpty,\n parseFormat,\n} from 'roosterjs-content-model-dom';\nimport type {\n ContentModelBlockGroup,\n ContentModelListItem,\n ContentModelListItemFormat,\n ContentModelListItemLevelFormat,\n ContentModelListLevel,\n DomToModelContext,\n DomToModelListFormat,\n} from 'roosterjs-content-model-types';\n\n/** Word list metadata style name */\nconst MSO_LIST = 'mso-list';\nconst MSO_LIST_IGNORE = 'ignore';\nconst WORD_FIRST_LIST = 'l0';\nconst TEMPLATE_VALUE_REGEX = /%[0-9a-zA-Z]+/g;\n\ninterface WordDesktopListFormat extends DomToModelListFormat {\n wordLevel?: number | '';\n wordList?: string;\n wordKnownLevels?: Map<string, ContentModelListLevel[]>;\n}\n\ninterface WordListFormat extends ContentModelListItemFormat {\n wordList?: string;\n}\n\nconst BULLET_METADATA = 'bullet';\n/**\n * @internal\n * @param styles\n * @param group\n * @param element\n * @param context\n * @returns\n */\nexport function processWordList(\n styles: Record<string, string>,\n group: ContentModelBlockGroup,\n element: HTMLElement,\n context: DomToModelContext,\n metadata: Map<string, WordMetadata>\n) {\n const listFormat = context.listFormat as WordDesktopListFormat;\n if (!listFormat.wordKnownLevels) {\n listFormat.wordKnownLevels = new Map<string, ContentModelListLevel[]>();\n }\n const wordListStyle = styles[MSO_LIST] || '';\n\n // If the element contains Ignore style, do not process it,\n // Usually this element contains the fake bullet used in Word Desktop.\n if (wordListStyle.toLowerCase() === MSO_LIST_IGNORE) {\n return true;\n }\n\n const [lNumber, level] = wordListStyle.split(' ');\n // Try get the list metadata from word, which follows this format: l1 level1 lfo2\n // If we are able to get the level property means we can process this element to be a list\n listFormat.wordLevel = level && parseInt(level.substr('level'.length));\n\n listFormat.wordList = lNumber || WORD_FIRST_LIST;\n if (listFormat.levels.length == 0) {\n listFormat.levels =\n (listFormat.wordList && listFormat.wordKnownLevels.get(listFormat.wordList)) || [];\n }\n\n if (wordListStyle && group && typeof listFormat.wordLevel === 'number') {\n const { wordLevel, wordList } = listFormat;\n // Retrieve the Fake bullet on the element and also the list type\n const listMetadata = metadata.get(`${lNumber}:${level}`);\n const listType =\n listMetadata?.['mso-level-number-format']?.toLowerCase() != BULLET_METADATA\n ? 'OL'\n : 'UL';\n\n // Create the new level of the list item and parse the format\n const newLevel: ContentModelListLevel = createListLevel(listType);\n parseFormat(\n element,\n [...context.formatParsers.listLevel, wordListPaddingParser],\n newLevel.format,\n context\n );\n\n // If the list format is in a different level, update the array so we get the new item\n // To be in the same level as the provided level metadata.\n if (wordLevel > listFormat.levels.length) {\n while (wordLevel != listFormat.levels.length) {\n listFormat.levels.push(newLevel);\n }\n } else {\n listFormat.levels.splice(wordLevel, listFormat.levels.length - 1);\n listFormat.levels[wordLevel - 1] = newLevel;\n }\n (listFormat.levels[listFormat.levels.length - 1]\n .format as WordListFormat).wordList = wordList;\n\n listFormat.listParent = group;\n\n processAsListItem(listFormat, context, element, group, listMetadata);\n\n if (\n listFormat.levels.length > 0 &&\n listFormat.wordKnownLevels.get(wordList) != listFormat.levels\n ) {\n listFormat.wordKnownLevels.set(wordList, [...listFormat.levels]);\n }\n return true;\n }\n\n return false;\n}\n\nfunction processAsListItem(\n listFormat: WordDesktopListFormat,\n context: DomToModelContext,\n element: HTMLElement,\n group: ContentModelBlockGroup,\n listMetadata: WordMetadata | undefined\n) {\n const listLevel = listFormat.levels[listFormat.levels.length - 1];\n const { listType } = listLevel;\n const bullet = getBulletFromMetadata(listMetadata, listType);\n if (bullet) {\n updateListMetadata(listFormat.levels[listFormat.levels.length - 1], metadata =>\n Object.assign({}, metadata, {\n unorderedStyleType: listType == 'UL' ? bullet : undefined,\n orderedStyleType: listType == 'OL' ? bullet : undefined,\n })\n );\n }\n\n const listItem = createListItem(listFormat.levels, context.segmentFormat);\n\n parseFormat(element, context.formatParsers.segmentOnBlock, context.segmentFormat, context);\n parseFormat(element, context.formatParsers.listItemElement, listItem.format, context);\n\n if (listType == 'OL') {\n setStartNumber(listItem, context, listMetadata);\n }\n\n context.elementProcessors.child(listItem, element, context);\n addBlock(group, listItem);\n}\n\nfunction getBulletFromMetadata(listMetadata: WordMetadata | undefined, listType: 'OL' | 'UL') {\n const templateType = listMetadata?.['mso-level-number-format'] || 'decimal';\n let templateFinal: string;\n\n if (listMetadata?.['mso-level-text']) {\n let templateValue: string = '';\n switch (templateType) {\n case 'alpha-upper':\n templateValue = 'UpperAlpha';\n break;\n case 'alpha-lower':\n templateValue = 'LowerAlpha';\n break;\n case 'roman-lower':\n templateValue = 'LowerRoman';\n break;\n case 'roman-upper':\n templateValue = 'UpperRoman';\n break;\n default:\n templateValue = 'Number';\n break;\n }\n const template = (listMetadata['mso-level-text'] || '')\n .replace('\\\\', '')\n .replace('\"', '')\n .replace(TEMPLATE_VALUE_REGEX, '${' + templateValue + '}');\n\n templateFinal = '\"' + template + ' \"';\n } else {\n switch (templateType) {\n case 'alpha-lower':\n templateFinal = 'lower-alpha';\n break;\n case 'roman-lower':\n templateFinal = 'lower-roman';\n break;\n case 'roman-upper':\n templateFinal = 'upper-roman';\n break;\n default:\n templateFinal = 'decimal';\n break;\n }\n }\n\n return getListStyleTypeFromString(listType, templateFinal);\n}\n\nfunction wordListPaddingParser(\n format: ContentModelListItemLevelFormat,\n element: HTMLElement\n): void {\n if (element.style.marginLeft && element.style.marginLeft != '0in') {\n format.paddingLeft = '0px';\n }\n if (element.style.marginRight && element.style.marginRight != '0in') {\n format.paddingRight = '0px';\n }\n}\n\nfunction setStartNumber(\n listItem: ContentModelListItem,\n context: DomToModelContext,\n listMetadata: WordMetadata | undefined\n) {\n const {\n listParent,\n wordList,\n wordKnownLevels,\n wordLevel,\n levels,\n } = context.listFormat as WordDesktopListFormat;\n\n const block = getLastNotEmptyBlock(listParent);\n if (\n (block?.blockType != 'BlockGroup' ||\n block.blockGroupType != 'ListItem' ||\n (wordLevel &&\n (block.levels[wordLevel]?.format as WordListFormat)?.wordList != wordList)) &&\n wordList\n ) {\n const start = listMetadata?.['mso-level-start-at']\n ? parseInt(listMetadata['mso-level-start-at'])\n : NaN;\n const knownLevel = wordKnownLevels?.get(wordList) || [];\n\n if (start != undefined && !isNaN(start) && knownLevel.length != levels.length) {\n listItem.levels[listItem.levels.length - 1].format.startNumberOverride = start;\n }\n }\n}\n\nfunction getLastNotEmptyBlock(listParent: ContentModelBlockGroup | undefined) {\n for (let index = (listParent?.blocks.length || 0) - 1; index > 0; index--) {\n const result = listParent?.blocks[index];\n if (result && !isEmpty(result)) {\n return result;\n }\n }\n\n return undefined;\n}\n"]}
package/package.json CHANGED
@@ -5,12 +5,12 @@
5
5
  "tslib": "^2.3.1",
6
6
  "roosterjs-editor-types": "^8.59.0",
7
7
  "roosterjs-editor-dom": "^8.59.0",
8
- "roosterjs-content-model-core": "^0.22.0",
9
- "roosterjs-content-model-editor": "^0.22.0",
10
- "roosterjs-content-model-dom": "^0.22.0",
11
- "roosterjs-content-model-types": "^0.22.0"
8
+ "roosterjs-content-model-core": "^0.23.0",
9
+ "roosterjs-content-model-editor": "^0.23.0",
10
+ "roosterjs-content-model-dom": "^0.23.0",
11
+ "roosterjs-content-model-types": "^0.23.0"
12
12
  },
13
- "version": "0.22.0",
13
+ "version": "0.23.0",
14
14
  "main": "./lib/index.js",
15
15
  "typings": "./lib/index.d.ts",
16
16
  "module": "./lib-mjs/index.js",