roosterjs-content-model-plugins 9.45.2 → 9.47.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/EditPlugin.js +1 -4
  2. package/lib/edit/EditPlugin.js.map +1 -1
  3. package/lib/edit/keyboardDelete.js +30 -3
  4. package/lib/edit/keyboardDelete.js.map +1 -1
  5. package/lib/paste/WacComponents/processPastedContentWacComponents.js +5 -1
  6. package/lib/paste/WacComponents/processPastedContentWacComponents.js.map +1 -1
  7. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.js +2 -0
  8. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  9. package/lib/paste/parsers/adjustWordListMarginParser.d.ts +9 -0
  10. package/lib/paste/parsers/adjustWordListMarginParser.js +26 -0
  11. package/lib/paste/parsers/adjustWordListMarginParser.js.map +1 -0
  12. package/lib/tableEdit/editors/features/TableMover.js +2 -3
  13. package/lib/tableEdit/editors/features/TableMover.js.map +1 -1
  14. package/lib/touch/TouchPlugin.js +3 -3
  15. package/lib/touch/TouchPlugin.js.map +1 -1
  16. package/lib-amd/edit/EditPlugin.js +1 -4
  17. package/lib-amd/edit/EditPlugin.js.map +1 -1
  18. package/lib-amd/edit/keyboardDelete.js +30 -4
  19. package/lib-amd/edit/keyboardDelete.js.map +1 -1
  20. package/lib-amd/paste/WacComponents/processPastedContentWacComponents.js +5 -1
  21. package/lib-amd/paste/WacComponents/processPastedContentWacComponents.js.map +1 -1
  22. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.js +2 -1
  23. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  24. package/lib-amd/paste/parsers/adjustWordListMarginParser.d.ts +9 -0
  25. package/lib-amd/paste/parsers/adjustWordListMarginParser.js +27 -0
  26. package/lib-amd/paste/parsers/adjustWordListMarginParser.js.map +1 -0
  27. package/lib-amd/tableEdit/editors/features/TableMover.js +3 -3
  28. package/lib-amd/tableEdit/editors/features/TableMover.js.map +1 -1
  29. package/lib-amd/touch/TouchPlugin.js +3 -3
  30. package/lib-amd/touch/TouchPlugin.js.map +1 -1
  31. package/lib-mjs/edit/EditPlugin.js +1 -4
  32. package/lib-mjs/edit/EditPlugin.js.map +1 -1
  33. package/lib-mjs/edit/keyboardDelete.js +31 -4
  34. package/lib-mjs/edit/keyboardDelete.js.map +1 -1
  35. package/lib-mjs/paste/WacComponents/processPastedContentWacComponents.js +5 -1
  36. package/lib-mjs/paste/WacComponents/processPastedContentWacComponents.js.map +1 -1
  37. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.js +2 -0
  38. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  39. package/lib-mjs/paste/parsers/adjustWordListMarginParser.d.ts +9 -0
  40. package/lib-mjs/paste/parsers/adjustWordListMarginParser.js +22 -0
  41. package/lib-mjs/paste/parsers/adjustWordListMarginParser.js.map +1 -0
  42. package/lib-mjs/tableEdit/editors/features/TableMover.js +3 -4
  43. package/lib-mjs/tableEdit/editors/features/TableMover.js.map +1 -1
  44. package/lib-mjs/touch/TouchPlugin.js +3 -3
  45. package/lib-mjs/touch/TouchPlugin.js.map +1 -1
  46. package/package.json +5 -5
  47. package/lib/utils/getNodePositionFromEvent.d.ts +0 -5
  48. package/lib/utils/getNodePositionFromEvent.js +0 -34
  49. package/lib/utils/getNodePositionFromEvent.js.map +0 -1
  50. package/lib-amd/utils/getNodePositionFromEvent.d.ts +0 -5
  51. package/lib-amd/utils/getNodePositionFromEvent.js +0 -36
  52. package/lib-amd/utils/getNodePositionFromEvent.js.map +0 -1
  53. package/lib-mjs/utils/getNodePositionFromEvent.d.ts +0 -5
  54. package/lib-mjs/utils/getNodePositionFromEvent.js +0 -30
  55. package/lib-mjs/utils/getNodePositionFromEvent.js.map +0 -1
@@ -176,10 +176,7 @@ var EditPlugin = /** @class */ (function () {
176
176
  case 'Delete':
177
177
  // Use our API to handle BACKSPACE/DELETE key.
178
178
  // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache
179
- // And leave it to browser when shift key is pressed so that browser will trigger cut event
180
- if (!event.rawEvent.shiftKey) {
181
- (0, keyboardDelete_1.keyboardDelete)(editor, rawEvent, this.options);
182
- }
179
+ (0, keyboardDelete_1.keyboardDelete)(editor, rawEvent, this.options);
183
180
  break;
184
181
  case 'Tab':
185
182
  if (!hasCtrlOrMetaKey) {
@@ -1 +1 @@
1
- {"version":3,"file":"EditPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/edit/EditPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { keyboardDelete } from './keyboardDelete';\nimport { keyboardEnter } from './keyboardEnter';\nimport { keyboardInput } from './keyboardInput';\nimport { keyboardTab } from './keyboardTab';\nimport { parseTableCells } from 'roosterjs-content-model-dom';\nimport type { EditOptions, HandleTabOptions } from './EditOptions';\nimport type {\n DOMSelection,\n EditorPlugin,\n IEditor,\n KeyDownEvent,\n PluginEvent,\n} from 'roosterjs-content-model-types';\n\nconst BACKSPACE_KEY = 8;\nconst DELETE_KEY = 46;\n/**\n * According to https://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html\n * 229 can be sent in variants generated when Long press (iOS) or using IM.\n *\n * Other cases: https://stackoverflow.com/questions/25043934/is-it-ok-to-ignore-keydown-events-with-keycode-229\n */\nconst DEAD_KEY = 229;\n\nconst DefaultHandleTabOptions: Required<HandleTabOptions> = {\n indentMultipleBlocks: true,\n indentTable: true,\n appendTableRow: true,\n indentList: true,\n indentParagraph: true,\n};\n\nconst DisabledHandleTabOptions: Required<HandleTabOptions> = {\n indentMultipleBlocks: false,\n indentTable: false,\n appendTableRow: false,\n indentList: false,\n indentParagraph: false,\n};\n\nconst DefaultOptions: Partial<EditOptions> & { handleTabKey: Required<HandleTabOptions> } = {\n handleTabKey: DefaultHandleTabOptions,\n handleExpandedSelectionOnDelete: true,\n};\n\n/**\n * Edit plugins helps editor to do editing operation on top of content model.\n * This includes:\n * 1. Delete Key\n * 2. Backspace Key\n * 3. Tab Key\n */\nexport class EditPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n private disposer: (() => void) | null = null;\n private shouldHandleNextInputEvent = false;\n private selectionAfterDelete: DOMSelection | null = null;\n private handleNormalEnter: (editor: IEditor) => boolean = () => false;\n private options: EditOptions & { handleTabKey: Required<HandleTabOptions> };\n\n /**\n * @param options An optional parameter that takes in an object of type EditOptions, which includes the following properties:\n * handleTabKey: A boolean or HandleTabOptions object that controls Tab key handling. When a boolean, true enables all features and false disables all. When an object, individual features can be controlled. Defaults to all enabled.\n */\n constructor(options: EditOptions = DefaultOptions) {\n const tabOptions =\n options.handleTabKey === false\n ? DisabledHandleTabOptions\n : options.handleTabKey === true || !options.handleTabKey\n ? DefaultHandleTabOptions\n : { ...DefaultHandleTabOptions, ...options.handleTabKey };\n this.options = { ...DefaultOptions, ...options, handleTabKey: tabOptions };\n }\n\n private createNormalEnterChecker(result: boolean) {\n return result ? () => true : () => false;\n }\n\n private getHandleNormalEnter(editor: IEditor) {\n switch (typeof this.options.shouldHandleEnterKey) {\n case 'function':\n return this.options.shouldHandleEnterKey;\n case 'boolean':\n return this.createNormalEnterChecker(this.options.shouldHandleEnterKey);\n default:\n return this.createNormalEnterChecker(\n editor.isExperimentalFeatureEnabled('HandleEnterKey')\n );\n }\n }\n\n /**\n * Get name of this plugin\n */\n getName() {\n return 'Edit';\n }\n\n /**\n * The first method that editor will call to a plugin when editor is initializing.\n * It will pass in the editor instance, plugin should take this chance to save the\n * editor reference so that it can call to any editor method or format API later.\n * @param editor The editor object\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.handleNormalEnter = this.getHandleNormalEnter(editor);\n\n if (editor.getEnvironment().isAndroid) {\n this.disposer = this.editor.attachDomEvent({\n beforeinput: {\n beforeDispatch: e => this.handleBeforeInputEvent(editor, e),\n },\n });\n }\n }\n\n /**\n * The last method that editor will call to a plugin before it is disposed.\n * Plugin can take this chance to clear the reference to editor. After this method is\n * called, plugin should not call to any editor method since it will result in error.\n */\n dispose() {\n this.editor = null;\n this.disposer?.();\n this.disposer = null;\n }\n\n /**\n * Core method for a plugin. Once an event happens in editor, editor will call this\n * method of each plugin to handle the event as long as the event is not handled\n * exclusively by another plugin.\n * @param event The event to handle:\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case 'keyDown':\n this.handleKeyDownEvent(this.editor, event);\n break;\n case 'keyUp':\n if (this.selectionAfterDelete) {\n this.editor.setDOMSelection(this.selectionAfterDelete);\n this.selectionAfterDelete = null;\n }\n break;\n }\n }\n }\n\n /**\n * Check if the plugin should handle the given event exclusively.\n * Handle an event exclusively means other plugin will not receive this event in\n * onPluginEvent method.\n * If two plugins will return true in willHandleEventExclusively() for the same event,\n * the final result depends on the order of the plugins are added into editor\n * @param event The event to check:\n */\n willHandleEventExclusively(event: PluginEvent) {\n if (\n this.editor &&\n this.options.handleTabKey.appendTableRow &&\n event.eventType == 'keyDown' &&\n event.rawEvent.key == 'Tab' &&\n !event.rawEvent.shiftKey\n ) {\n const selection = this.editor.getDOMSelection();\n const startContainer =\n selection?.type == 'range' ? selection.range.startContainer : null;\n const table = startContainer\n ? this.editor.getDOMHelper().findClosestElementAncestor(startContainer, 'table')\n : null;\n const parsedTable = table && parseTableCells(table);\n\n if (parsedTable) {\n const lastRow = parsedTable[parsedTable.length - 1];\n const lastCell = lastRow && lastRow[lastRow.length - 1];\n\n if (typeof lastCell == 'object' && lastCell.contains(startContainer)) {\n // When TAB in the last cell of a table, we will generate new table row, so prevent other plugins handling this event\n // e.g. SelectionPlugin will move the focus out of table, which is conflict with this behavior\n return true;\n }\n }\n }\n\n return false;\n }\n\n private handleKeyDownEvent(editor: IEditor, event: KeyDownEvent) {\n const rawEvent = event.rawEvent;\n const hasCtrlOrMetaKey = rawEvent.ctrlKey || rawEvent.metaKey;\n\n if (!rawEvent.defaultPrevented && !event.handledByEditFeature) {\n switch (rawEvent.key) {\n case 'Backspace':\n // Use our API to handle BACKSPACE/DELETE key.\n // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache\n if (!this.shouldBrowserHandleBackspace(editor)) {\n keyboardDelete(editor, rawEvent, this.options);\n }\n break;\n\n case 'Delete':\n // Use our API to handle BACKSPACE/DELETE key.\n // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache\n // And leave it to browser when shift key is pressed so that browser will trigger cut event\n if (!event.rawEvent.shiftKey) {\n keyboardDelete(editor, rawEvent, this.options);\n }\n break;\n\n case 'Tab':\n if (!hasCtrlOrMetaKey) {\n keyboardTab(editor, rawEvent, this.options.handleTabKey);\n }\n break;\n case 'Unidentified':\n if (editor.getEnvironment().isAndroid) {\n this.shouldHandleNextInputEvent = true;\n }\n break;\n\n case 'Enter':\n if (\n !hasCtrlOrMetaKey &&\n !event.rawEvent.isComposing &&\n event.rawEvent.keyCode !== DEAD_KEY\n ) {\n keyboardEnter(\n editor,\n rawEvent,\n this.handleNormalEnter(editor),\n this.options.formatsToPreserveOnMerge\n );\n }\n break;\n\n default:\n keyboardInput(editor, rawEvent);\n break;\n }\n }\n }\n\n private handleBeforeInputEvent(editor: IEditor, rawEvent: Event) {\n // Some Android IMEs doesn't fire correct keydown event for BACKSPACE/DELETE key\n // Here we translate input event to BACKSPACE/DELETE keydown event to be compatible with existing logic\n if (\n !this.shouldHandleNextInputEvent ||\n !(rawEvent instanceof InputEvent) ||\n rawEvent.defaultPrevented\n ) {\n return;\n }\n this.shouldHandleNextInputEvent = false;\n\n let handled = false;\n switch (rawEvent.inputType) {\n case 'deleteContentBackward':\n if (!this.shouldBrowserHandleBackspace(editor)) {\n // This logic is Android specific. It's because some Android keyboard doesn't support key and keycode, the value of them is always Unidentified, so we have to manually create a new one.\n handled = keyboardDelete(\n editor,\n new KeyboardEvent('keydown', {\n key: 'Backspace',\n keyCode: BACKSPACE_KEY,\n which: BACKSPACE_KEY,\n }),\n this.options\n );\n }\n break;\n case 'deleteContentForward':\n handled = keyboardDelete(\n editor,\n new KeyboardEvent('keydown', {\n key: 'Delete',\n keyCode: DELETE_KEY,\n which: DELETE_KEY,\n }),\n this.options\n );\n break;\n }\n\n if (handled) {\n rawEvent.preventDefault();\n\n // Restore the selection on keyup event to avoid the cursor jump issue\n // See: https://issues.chromium.org/issues/330596261\n this.selectionAfterDelete = editor.getDOMSelection();\n }\n }\n\n private shouldBrowserHandleBackspace(editor: IEditor): boolean {\n const opt = this.options.shouldHandleBackspaceKey;\n switch (typeof opt) {\n case 'function':\n return opt(editor);\n case 'boolean':\n return opt;\n default:\n return false;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"EditPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/edit/EditPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { keyboardDelete } from './keyboardDelete';\nimport { keyboardEnter } from './keyboardEnter';\nimport { keyboardInput } from './keyboardInput';\nimport { keyboardTab } from './keyboardTab';\nimport { parseTableCells } from 'roosterjs-content-model-dom';\nimport type { EditOptions, HandleTabOptions } from './EditOptions';\nimport type {\n DOMSelection,\n EditorPlugin,\n IEditor,\n KeyDownEvent,\n PluginEvent,\n} from 'roosterjs-content-model-types';\n\nconst BACKSPACE_KEY = 8;\nconst DELETE_KEY = 46;\n/**\n * According to https://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html\n * 229 can be sent in variants generated when Long press (iOS) or using IM.\n *\n * Other cases: https://stackoverflow.com/questions/25043934/is-it-ok-to-ignore-keydown-events-with-keycode-229\n */\nconst DEAD_KEY = 229;\n\nconst DefaultHandleTabOptions: Required<HandleTabOptions> = {\n indentMultipleBlocks: true,\n indentTable: true,\n appendTableRow: true,\n indentList: true,\n indentParagraph: true,\n};\n\nconst DisabledHandleTabOptions: Required<HandleTabOptions> = {\n indentMultipleBlocks: false,\n indentTable: false,\n appendTableRow: false,\n indentList: false,\n indentParagraph: false,\n};\n\nconst DefaultOptions: Partial<EditOptions> & { handleTabKey: Required<HandleTabOptions> } = {\n handleTabKey: DefaultHandleTabOptions,\n handleExpandedSelectionOnDelete: true,\n};\n\n/**\n * Edit plugins helps editor to do editing operation on top of content model.\n * This includes:\n * 1. Delete Key\n * 2. Backspace Key\n * 3. Tab Key\n */\nexport class EditPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n private disposer: (() => void) | null = null;\n private shouldHandleNextInputEvent = false;\n private selectionAfterDelete: DOMSelection | null = null;\n private handleNormalEnter: (editor: IEditor) => boolean = () => false;\n private options: EditOptions & { handleTabKey: Required<HandleTabOptions> };\n\n /**\n * @param options An optional parameter that takes in an object of type EditOptions, which includes the following properties:\n * handleTabKey: A boolean or HandleTabOptions object that controls Tab key handling. When a boolean, true enables all features and false disables all. When an object, individual features can be controlled. Defaults to all enabled.\n */\n constructor(options: EditOptions = DefaultOptions) {\n const tabOptions =\n options.handleTabKey === false\n ? DisabledHandleTabOptions\n : options.handleTabKey === true || !options.handleTabKey\n ? DefaultHandleTabOptions\n : { ...DefaultHandleTabOptions, ...options.handleTabKey };\n this.options = { ...DefaultOptions, ...options, handleTabKey: tabOptions };\n }\n\n private createNormalEnterChecker(result: boolean) {\n return result ? () => true : () => false;\n }\n\n private getHandleNormalEnter(editor: IEditor) {\n switch (typeof this.options.shouldHandleEnterKey) {\n case 'function':\n return this.options.shouldHandleEnterKey;\n case 'boolean':\n return this.createNormalEnterChecker(this.options.shouldHandleEnterKey);\n default:\n return this.createNormalEnterChecker(\n editor.isExperimentalFeatureEnabled('HandleEnterKey')\n );\n }\n }\n\n /**\n * Get name of this plugin\n */\n getName() {\n return 'Edit';\n }\n\n /**\n * The first method that editor will call to a plugin when editor is initializing.\n * It will pass in the editor instance, plugin should take this chance to save the\n * editor reference so that it can call to any editor method or format API later.\n * @param editor The editor object\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.handleNormalEnter = this.getHandleNormalEnter(editor);\n\n if (editor.getEnvironment().isAndroid) {\n this.disposer = this.editor.attachDomEvent({\n beforeinput: {\n beforeDispatch: e => this.handleBeforeInputEvent(editor, e),\n },\n });\n }\n }\n\n /**\n * The last method that editor will call to a plugin before it is disposed.\n * Plugin can take this chance to clear the reference to editor. After this method is\n * called, plugin should not call to any editor method since it will result in error.\n */\n dispose() {\n this.editor = null;\n this.disposer?.();\n this.disposer = null;\n }\n\n /**\n * Core method for a plugin. Once an event happens in editor, editor will call this\n * method of each plugin to handle the event as long as the event is not handled\n * exclusively by another plugin.\n * @param event The event to handle:\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case 'keyDown':\n this.handleKeyDownEvent(this.editor, event);\n break;\n case 'keyUp':\n if (this.selectionAfterDelete) {\n this.editor.setDOMSelection(this.selectionAfterDelete);\n this.selectionAfterDelete = null;\n }\n break;\n }\n }\n }\n\n /**\n * Check if the plugin should handle the given event exclusively.\n * Handle an event exclusively means other plugin will not receive this event in\n * onPluginEvent method.\n * If two plugins will return true in willHandleEventExclusively() for the same event,\n * the final result depends on the order of the plugins are added into editor\n * @param event The event to check:\n */\n willHandleEventExclusively(event: PluginEvent) {\n if (\n this.editor &&\n this.options.handleTabKey.appendTableRow &&\n event.eventType == 'keyDown' &&\n event.rawEvent.key == 'Tab' &&\n !event.rawEvent.shiftKey\n ) {\n const selection = this.editor.getDOMSelection();\n const startContainer =\n selection?.type == 'range' ? selection.range.startContainer : null;\n const table = startContainer\n ? this.editor.getDOMHelper().findClosestElementAncestor(startContainer, 'table')\n : null;\n const parsedTable = table && parseTableCells(table);\n\n if (parsedTable) {\n const lastRow = parsedTable[parsedTable.length - 1];\n const lastCell = lastRow && lastRow[lastRow.length - 1];\n\n if (typeof lastCell == 'object' && lastCell.contains(startContainer)) {\n // When TAB in the last cell of a table, we will generate new table row, so prevent other plugins handling this event\n // e.g. SelectionPlugin will move the focus out of table, which is conflict with this behavior\n return true;\n }\n }\n }\n\n return false;\n }\n\n private handleKeyDownEvent(editor: IEditor, event: KeyDownEvent) {\n const rawEvent = event.rawEvent;\n const hasCtrlOrMetaKey = rawEvent.ctrlKey || rawEvent.metaKey;\n\n if (!rawEvent.defaultPrevented && !event.handledByEditFeature) {\n switch (rawEvent.key) {\n case 'Backspace':\n // Use our API to handle BACKSPACE/DELETE key.\n // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache\n if (!this.shouldBrowserHandleBackspace(editor)) {\n keyboardDelete(editor, rawEvent, this.options);\n }\n break;\n\n case 'Delete':\n // Use our API to handle BACKSPACE/DELETE key.\n // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache\n keyboardDelete(editor, rawEvent, this.options);\n break;\n\n case 'Tab':\n if (!hasCtrlOrMetaKey) {\n keyboardTab(editor, rawEvent, this.options.handleTabKey);\n }\n break;\n case 'Unidentified':\n if (editor.getEnvironment().isAndroid) {\n this.shouldHandleNextInputEvent = true;\n }\n break;\n\n case 'Enter':\n if (\n !hasCtrlOrMetaKey &&\n !event.rawEvent.isComposing &&\n event.rawEvent.keyCode !== DEAD_KEY\n ) {\n keyboardEnter(\n editor,\n rawEvent,\n this.handleNormalEnter(editor),\n this.options.formatsToPreserveOnMerge\n );\n }\n break;\n\n default:\n keyboardInput(editor, rawEvent);\n break;\n }\n }\n }\n\n private handleBeforeInputEvent(editor: IEditor, rawEvent: Event) {\n // Some Android IMEs doesn't fire correct keydown event for BACKSPACE/DELETE key\n // Here we translate input event to BACKSPACE/DELETE keydown event to be compatible with existing logic\n if (\n !this.shouldHandleNextInputEvent ||\n !(rawEvent instanceof InputEvent) ||\n rawEvent.defaultPrevented\n ) {\n return;\n }\n this.shouldHandleNextInputEvent = false;\n\n let handled = false;\n switch (rawEvent.inputType) {\n case 'deleteContentBackward':\n if (!this.shouldBrowserHandleBackspace(editor)) {\n // This logic is Android specific. It's because some Android keyboard doesn't support key and keycode, the value of them is always Unidentified, so we have to manually create a new one.\n handled = keyboardDelete(\n editor,\n new KeyboardEvent('keydown', {\n key: 'Backspace',\n keyCode: BACKSPACE_KEY,\n which: BACKSPACE_KEY,\n }),\n this.options\n );\n }\n break;\n case 'deleteContentForward':\n handled = keyboardDelete(\n editor,\n new KeyboardEvent('keydown', {\n key: 'Delete',\n keyCode: DELETE_KEY,\n which: DELETE_KEY,\n }),\n this.options\n );\n break;\n }\n\n if (handled) {\n rawEvent.preventDefault();\n\n // Restore the selection on keyup event to avoid the cursor jump issue\n // See: https://issues.chromium.org/issues/330596261\n this.selectionAfterDelete = editor.getDOMSelection();\n }\n }\n\n private shouldBrowserHandleBackspace(editor: IEditor): boolean {\n const opt = this.options.shouldHandleBackspaceKey;\n switch (typeof opt) {\n case 'function':\n return opt(editor);\n case 'boolean':\n return opt;\n default:\n return false;\n }\n }\n}\n"]}
@@ -5,6 +5,7 @@ var deleteAllSegmentBefore_1 = require("./deleteSteps/deleteAllSegmentBefore");
5
5
  var deleteEmptyQuote_1 = require("./deleteSteps/deleteEmptyQuote");
6
6
  var deleteList_1 = require("./deleteSteps/deleteList");
7
7
  var deleteParagraphStyle_1 = require("./deleteSteps/deleteParagraphStyle");
8
+ var roosterjs_content_model_api_1 = require("roosterjs-content-model-api");
8
9
  var deleteCollapsedSelection_1 = require("./deleteSteps/deleteCollapsedSelection");
9
10
  var roosterjs_content_model_dom_1 = require("roosterjs-content-model-dom");
10
11
  var handleKeyboardEventCommon_1 = require("./handleKeyboardEventCommon");
@@ -21,7 +22,12 @@ function keyboardDelete(editor, rawEvent, options) {
21
22
  var handled = false;
22
23
  var selection = editor.getDOMSelection();
23
24
  var handleExpandedSelectionOnDelete = options.handleExpandedSelectionOnDelete;
24
- if (shouldDeleteWithContentModel(selection, rawEvent, !!handleExpandedSelectionOnDelete)) {
25
+ var tableDeleteType = shouldDeleteTableWithContentModel(selection, rawEvent);
26
+ if (tableDeleteType) {
27
+ (0, roosterjs_content_model_api_1.editTable)(editor, tableDeleteType);
28
+ handled = true;
29
+ }
30
+ else if (shouldDeleteWithContentModel(selection, rawEvent, !!handleExpandedSelectionOnDelete)) {
25
31
  editor.formatContentModel(function (model, context) {
26
32
  var result = (0, roosterjs_content_model_dom_1.deleteSelection)(model, getDeleteSteps(rawEvent, !!editor.getEnvironment().isMac, options), context).deleteResult;
27
33
  handled = (0, handleKeyboardEventCommon_1.handleKeyboardEventResult)(editor, model, rawEvent, result, context);
@@ -58,8 +64,8 @@ function getDeleteSteps(rawEvent, isMac, options) {
58
64
  }
59
65
  function shouldDeleteWithContentModel(selection, rawEvent, handleExpandedSelection) {
60
66
  var _a, _b;
61
- if (!selection) {
62
- return false; // Nothing to delete
67
+ if (!selection || (rawEvent.key == 'Delete' && rawEvent.shiftKey)) {
68
+ return false; // Nothing to delete or leave it to browser when delete and shift key is pressed so that browser will trigger cut event
63
69
  }
64
70
  else if (selection.type != 'range') {
65
71
  return true;
@@ -112,4 +118,25 @@ function canDeleteAfter(rawEvent, text, offset) {
112
118
  var _a, _b;
113
119
  return rawEvent.key == 'Delete' && offset < ((_b = (_a = text.nodeValue) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) - 1;
114
120
  }
121
+ function shouldDeleteTableWithContentModel(selection, rawEvent) {
122
+ if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'table' &&
123
+ (rawEvent.key == 'Backspace' || (rawEvent.key == 'Delete' && rawEvent.shiftKey))) {
124
+ var lastRow = selection.lastRow, lastColumn = selection.lastColumn, table = selection.table, firstColumn = selection.firstColumn, firstRow = selection.firstRow;
125
+ var parsedTable = (0, roosterjs_content_model_dom_1.parseTableCells)(table);
126
+ var rowNumber = parsedTable.length;
127
+ var isWholeColumnSelected = firstRow == 0 && lastRow == rowNumber - 1;
128
+ var columnNumber = parsedTable[lastRow].length;
129
+ var isWholeRowSelected = firstColumn == 0 && lastColumn == columnNumber - 1;
130
+ if (isWholeRowSelected && isWholeColumnSelected) {
131
+ return 'deleteTable';
132
+ }
133
+ if (isWholeRowSelected) {
134
+ return 'deleteRow';
135
+ }
136
+ if (isWholeColumnSelected) {
137
+ return 'deleteColumn';
138
+ }
139
+ }
140
+ return undefined;
141
+ }
115
142
  //# sourceMappingURL=keyboardDelete.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"keyboardDelete.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/edit/keyboardDelete.ts"],"names":[],"mappings":"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","sourcesContent":["import { deleteAllSegmentBefore } from './deleteSteps/deleteAllSegmentBefore';\nimport { deleteEmptyQuote } from './deleteSteps/deleteEmptyQuote';\nimport { deleteList } from './deleteSteps/deleteList';\nimport { deleteParagraphStyle } from './deleteSteps/deleteParagraphStyle';\nimport { getDeleteCollapsedSelection } from './deleteSteps/deleteCollapsedSelection';\nimport {\n ChangeSource,\n deleteSelection,\n isElementOfType,\n isLinkUndeletable,\n isModifierKey,\n isNodeOfType,\n} from 'roosterjs-content-model-dom';\nimport {\n handleKeyboardEventResult,\n shouldDeleteAllSegmentsBefore,\n shouldDeleteWord,\n} from './handleKeyboardEventCommon';\nimport {\n backwardDeleteWordSelection,\n forwardDeleteWordSelection,\n} from './deleteSteps/deleteWordSelection';\nimport type { DOMSelection, DeleteSelectionStep, IEditor } from 'roosterjs-content-model-types';\nimport type { EditOptions } from './EditOptions';\n\n/**\n * @internal\n * Do keyboard event handling for DELETE/BACKSPACE key\n * @param editor The editor object\n * @param rawEvent DOM keyboard event\n * @param handleExpandedSelection Whether to handle expanded selection within a text node by CM\n * @returns True if the event is handled by content model, otherwise false\n */\nexport function keyboardDelete(editor: IEditor, rawEvent: KeyboardEvent, options: EditOptions) {\n let handled = false;\n const selection = editor.getDOMSelection();\n const { handleExpandedSelectionOnDelete } = options;\n\n if (shouldDeleteWithContentModel(selection, rawEvent, !!handleExpandedSelectionOnDelete)) {\n editor.formatContentModel(\n (model, context) => {\n const result = deleteSelection(\n model,\n getDeleteSteps(rawEvent, !!editor.getEnvironment().isMac, options),\n context\n ).deleteResult;\n\n handled = handleKeyboardEventResult(editor, model, rawEvent, result, context);\n return handled;\n },\n {\n rawEvent,\n changeSource: ChangeSource.Keyboard,\n getChangeData: () => rawEvent.which,\n scrollCaretIntoView: true,\n apiName: rawEvent.key == 'Delete' ? 'handleDeleteKey' : 'handleBackspaceKey',\n }\n );\n }\n\n return handled;\n}\n\nfunction getDeleteSteps(\n rawEvent: KeyboardEvent,\n isMac: boolean,\n options: EditOptions\n): (DeleteSelectionStep | null)[] {\n const isForward = rawEvent.key == 'Delete';\n const deleteAllSegmentBeforeStep =\n shouldDeleteAllSegmentsBefore(rawEvent) && !isForward ? deleteAllSegmentBefore : null;\n const deleteWordSelection = shouldDeleteWord(rawEvent, isMac)\n ? isForward\n ? forwardDeleteWordSelection\n : backwardDeleteWordSelection\n : null;\n\n const deleteCollapsedSelection = getDeleteCollapsedSelection(\n isForward ? 'forward' : 'backward',\n options\n );\n\n const deleteQuote = !isForward ? deleteEmptyQuote : null;\n return [\n deleteAllSegmentBeforeStep,\n deleteWordSelection,\n isForward ? null : deleteList,\n deleteCollapsedSelection,\n deleteQuote,\n deleteParagraphStyle,\n ];\n}\n\nfunction shouldDeleteWithContentModel(\n selection: DOMSelection | null,\n rawEvent: KeyboardEvent,\n handleExpandedSelection: boolean\n) {\n if (!selection) {\n return false; // Nothing to delete\n } else if (selection.type != 'range') {\n return true;\n } else if (!selection.range.collapsed) {\n if (handleExpandedSelection) {\n return true; // Selection is not collapsed, need to delete all selections\n }\n\n const range = selection.range;\n const { startContainer, endContainer } = selection.range;\n const isInSameTextNode =\n startContainer === endContainer && isNodeOfType(startContainer, 'TEXT_NODE');\n return !(\n isInSameTextNode &&\n !isModifierKey(rawEvent) &&\n range.endOffset - range.startOffset < (startContainer.nodeValue?.length ?? 0)\n );\n } else {\n const range = selection.range;\n const startContainer = range.startContainer;\n const startOffset = range.startOffset;\n\n // When selection is collapsed and is in middle of text node, no need to use Content Model to delete\n return !(\n isNodeOfType(startContainer, 'TEXT_NODE') &&\n !isModifierKey(rawEvent) &&\n (canDeleteBefore(rawEvent, startContainer, startOffset) ||\n canDeleteAfter(rawEvent, startContainer, startOffset))\n );\n }\n}\n\nfunction canDeleteBefore(rawEvent: KeyboardEvent, text: Text, offset: number) {\n if (rawEvent.key != 'Backspace' || offset <= 1) {\n return false;\n }\n\n const length = text.nodeValue?.length ?? 0;\n\n if (offset == length) {\n // At the end of text, need to check if next segment is deletable\n const nextSibling = text.nextSibling;\n const isNextSiblingUndeletable =\n isNodeOfType(nextSibling, 'ELEMENT_NODE') &&\n isElementOfType(nextSibling, 'a') &&\n isLinkUndeletable(nextSibling) &&\n !nextSibling.firstChild;\n\n // If next sibling is undeletable, we cannot let browser handle it since it will remove the anchor\n // So we return false here to let Content Model handle it\n return !isNextSiblingUndeletable;\n } else {\n // In middle of text, we can safely let browser handle deletion\n return true;\n }\n}\n\nfunction canDeleteAfter(rawEvent: KeyboardEvent, text: Text, offset: number) {\n return rawEvent.key == 'Delete' && offset < (text.nodeValue?.length ?? 0) - 1;\n}\n"]}
1
+ {"version":3,"file":"keyboardDelete.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/edit/keyboardDelete.ts"],"names":[],"mappings":"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","sourcesContent":["import { deleteAllSegmentBefore } from './deleteSteps/deleteAllSegmentBefore';\nimport { deleteEmptyQuote } from './deleteSteps/deleteEmptyQuote';\nimport { deleteList } from './deleteSteps/deleteList';\nimport { deleteParagraphStyle } from './deleteSteps/deleteParagraphStyle';\nimport { editTable } from 'roosterjs-content-model-api';\nimport { getDeleteCollapsedSelection } from './deleteSteps/deleteCollapsedSelection';\nimport {\n ChangeSource,\n deleteSelection,\n isElementOfType,\n isLinkUndeletable,\n isModifierKey,\n isNodeOfType,\n parseTableCells,\n} from 'roosterjs-content-model-dom';\nimport {\n handleKeyboardEventResult,\n shouldDeleteAllSegmentsBefore,\n shouldDeleteWord,\n} from './handleKeyboardEventCommon';\nimport {\n backwardDeleteWordSelection,\n forwardDeleteWordSelection,\n} from './deleteSteps/deleteWordSelection';\nimport type {\n DOMSelection,\n DeleteSelectionStep,\n IEditor,\n TableDeleteOperation,\n} from 'roosterjs-content-model-types';\nimport type { EditOptions } from './EditOptions';\n\n/**\n * @internal\n * Do keyboard event handling for DELETE/BACKSPACE key\n * @param editor The editor object\n * @param rawEvent DOM keyboard event\n * @param handleExpandedSelection Whether to handle expanded selection within a text node by CM\n * @returns True if the event is handled by content model, otherwise false\n */\nexport function keyboardDelete(editor: IEditor, rawEvent: KeyboardEvent, options: EditOptions) {\n let handled = false;\n const selection = editor.getDOMSelection();\n const { handleExpandedSelectionOnDelete } = options;\n const tableDeleteType = shouldDeleteTableWithContentModel(selection, rawEvent);\n\n if (tableDeleteType) {\n editTable(editor, tableDeleteType);\n handled = true;\n } else if (\n shouldDeleteWithContentModel(selection, rawEvent, !!handleExpandedSelectionOnDelete)\n ) {\n editor.formatContentModel(\n (model, context) => {\n const result = deleteSelection(\n model,\n getDeleteSteps(rawEvent, !!editor.getEnvironment().isMac, options),\n context\n ).deleteResult;\n\n handled = handleKeyboardEventResult(editor, model, rawEvent, result, context);\n return handled;\n },\n {\n rawEvent,\n changeSource: ChangeSource.Keyboard,\n getChangeData: () => rawEvent.which,\n scrollCaretIntoView: true,\n apiName: rawEvent.key == 'Delete' ? 'handleDeleteKey' : 'handleBackspaceKey',\n }\n );\n }\n\n return handled;\n}\n\nfunction getDeleteSteps(\n rawEvent: KeyboardEvent,\n isMac: boolean,\n options: EditOptions\n): (DeleteSelectionStep | null)[] {\n const isForward = rawEvent.key == 'Delete';\n const deleteAllSegmentBeforeStep =\n shouldDeleteAllSegmentsBefore(rawEvent) && !isForward ? deleteAllSegmentBefore : null;\n const deleteWordSelection = shouldDeleteWord(rawEvent, isMac)\n ? isForward\n ? forwardDeleteWordSelection\n : backwardDeleteWordSelection\n : null;\n\n const deleteCollapsedSelection = getDeleteCollapsedSelection(\n isForward ? 'forward' : 'backward',\n options\n );\n\n const deleteQuote = !isForward ? deleteEmptyQuote : null;\n return [\n deleteAllSegmentBeforeStep,\n deleteWordSelection,\n isForward ? null : deleteList,\n deleteCollapsedSelection,\n deleteQuote,\n deleteParagraphStyle,\n ];\n}\n\nfunction shouldDeleteWithContentModel(\n selection: DOMSelection | null,\n rawEvent: KeyboardEvent,\n handleExpandedSelection: boolean\n) {\n if (!selection || (rawEvent.key == 'Delete' && rawEvent.shiftKey)) {\n return false; // Nothing to delete or leave it to browser when delete and shift key is pressed so that browser will trigger cut event\n } else if (selection.type != 'range') {\n return true;\n } else if (!selection.range.collapsed) {\n if (handleExpandedSelection) {\n return true; // Selection is not collapsed, need to delete all selections\n }\n\n const range = selection.range;\n const { startContainer, endContainer } = selection.range;\n const isInSameTextNode =\n startContainer === endContainer && isNodeOfType(startContainer, 'TEXT_NODE');\n return !(\n isInSameTextNode &&\n !isModifierKey(rawEvent) &&\n range.endOffset - range.startOffset < (startContainer.nodeValue?.length ?? 0)\n );\n } else {\n const range = selection.range;\n const startContainer = range.startContainer;\n const startOffset = range.startOffset;\n\n // When selection is collapsed and is in middle of text node, no need to use Content Model to delete\n return !(\n isNodeOfType(startContainer, 'TEXT_NODE') &&\n !isModifierKey(rawEvent) &&\n (canDeleteBefore(rawEvent, startContainer, startOffset) ||\n canDeleteAfter(rawEvent, startContainer, startOffset))\n );\n }\n}\n\nfunction canDeleteBefore(rawEvent: KeyboardEvent, text: Text, offset: number) {\n if (rawEvent.key != 'Backspace' || offset <= 1) {\n return false;\n }\n\n const length = text.nodeValue?.length ?? 0;\n\n if (offset == length) {\n // At the end of text, need to check if next segment is deletable\n const nextSibling = text.nextSibling;\n const isNextSiblingUndeletable =\n isNodeOfType(nextSibling, 'ELEMENT_NODE') &&\n isElementOfType(nextSibling, 'a') &&\n isLinkUndeletable(nextSibling) &&\n !nextSibling.firstChild;\n\n // If next sibling is undeletable, we cannot let browser handle it since it will remove the anchor\n // So we return false here to let Content Model handle it\n return !isNextSiblingUndeletable;\n } else {\n // In middle of text, we can safely let browser handle deletion\n return true;\n }\n}\n\nfunction canDeleteAfter(rawEvent: KeyboardEvent, text: Text, offset: number) {\n return rawEvent.key == 'Delete' && offset < (text.nodeValue?.length ?? 0) - 1;\n}\n\nfunction shouldDeleteTableWithContentModel(\n selection: DOMSelection | null,\n rawEvent: KeyboardEvent\n): TableDeleteOperation | undefined {\n if (\n selection?.type == 'table' &&\n (rawEvent.key == 'Backspace' || (rawEvent.key == 'Delete' && rawEvent.shiftKey))\n ) {\n const { lastRow, lastColumn, table, firstColumn, firstRow } = selection;\n const parsedTable = parseTableCells(table);\n const rowNumber = parsedTable.length;\n const isWholeColumnSelected = firstRow == 0 && lastRow == rowNumber - 1;\n const columnNumber = parsedTable[lastRow].length;\n const isWholeRowSelected = firstColumn == 0 && lastColumn == columnNumber - 1;\n if (isWholeRowSelected && isWholeColumnSelected) {\n return 'deleteTable';\n }\n\n if (isWholeRowSelected) {\n return 'deleteRow';\n }\n\n if (isWholeColumnSelected) {\n return 'deleteColumn';\n }\n }\n return undefined;\n}\n"]}
@@ -8,6 +8,8 @@ var setProcessor_1 = require("../utils/setProcessor");
8
8
  var constants_1 = require("./constants");
9
9
  var LIST_ELEMENT_TAGS = ['UL', 'OL', 'LI'];
10
10
  var LIST_ELEMENT_SELECTOR = LIST_ELEMENT_TAGS.join(',');
11
+ var END_OF_PARAGRAPH = 'EOP';
12
+ var SELECTED_CLASS = 'Selected';
11
13
  /**
12
14
  * Wac components do not use sub and super tags, instead only add vertical align to a span.
13
15
  * This parser normalize the content for content model
@@ -39,7 +41,9 @@ var wacElementProcessor = function (group, element, context) {
39
41
  context.elementProcessors.child(group, element, context);
40
42
  return;
41
43
  }
42
- if (constants_1.TEMP_ELEMENTS_CLASSES.some(function (className) { return element.classList.contains(className); })) {
44
+ if (constants_1.TEMP_ELEMENTS_CLASSES.some(function (className) { return element.classList.contains(className); }) ||
45
+ // This is needed to remove some temporary End of paragraph elements that WAC sometimes preserves
46
+ (element.classList.contains(SELECTED_CLASS) && element.classList.contains(END_OF_PARAGRAPH))) {
43
47
  return;
44
48
  }
45
49
  else if (shouldClearListContext(elementTag, element, context)) {
@@ -1 +1 @@
1
- {"version":3,"file":"processPastedContentWacComponents.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/WacComponents/processPastedContentWacComponents.ts"],"names":[],"mappings":";;;;AAAA,gDAA+C;AAC/C,2EAA2E;AAC3E,sDAAqD;AACrD,yCAMqB;AAcrB,IAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC7C,IAAM,qBAAqB,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAa1D;;;GAGG;AACH,IAAM,iBAAiB,GAA4C,UAC/D,MAAiC,EACjC,OAAoB;IAEpB,IAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC;IAClD,IAAI,aAAa,KAAK,OAAO,EAAE;QAC3B,MAAM,CAAC,wBAAwB,GAAG,OAAO,CAAC;KAC7C;IACD,IAAI,aAAa,KAAK,KAAK,EAAE;QACzB,MAAM,CAAC,wBAAwB,GAAG,KAAK,CAAC;KAC3C;AACL,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,IAAM,mBAAmB,GAAkC,UACvD,KAA6B,EAC7B,OAAoB,EACpB,OAA0B;IAE1B,IAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAEnC,IAAI,OAAO,CAAC,OAAO,CAAC,kCAAsB,CAAC,EAAE;QACzC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACxC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;KAC1C;IAED,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,6CAAiC,CAAC,EAAE;QAC/D,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACzD,OAAO;KACV;IAED,IAAI,iCAAqB,CAAC,IAAI,CAAC,UAAA,SAAS,IAAI,OAAA,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,EAArC,CAAqC,CAAC,EAAE;QAChF,OAAO;KACV;SAAM,IAAI,sBAAsB,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QACrD,IAAA,UAAU,GAAK,OAAO,WAAZ,CAAa;QAC/B,UAAU,CAAC,MAAM,GAAG,EAAE,CAAC;QACvB,UAAU,CAAC,UAAU,GAAG,SAAS,CAAC;KACrC;IAED,OAAO,CAAC,wBAAwB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC,CAAC;AAEF;;GAEG;AACH,IAAM,qBAAqB,GAAoC,UAC3D,KAA6B,EAC7B,OAAsB,EACtB,OAA0B;;IAE1B,IAAM,KAAK,GAAG,QAAQ,CAAC,MAAA,OAAO,CAAC,YAAY,CAAC,iBAAiB,CAAC,mCAAI,EAAE,CAAC,CAAC;IACtE,IAAM,UAAU,GAAG,OAAO,CAAC,UAAwB,CAAC;IACpD,IAAM,QAAQ,GACV,CAAA,MAAA,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,0CAAE,QAAQ;SAChE,MAAA,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,0CAAE,OAAO,CAAC,WAAW,EAAkB,CAAA,CAAC;IACrE,IAAM,QAAQ,GAA0B,IAAA,6CAAe,EAAC,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IACvF,IAAA,yCAAW,EAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,eAAe,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtF,IAAA,yCAAW,EAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChF,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,UAAU,CAAC,iBAAiB,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;IAEtF,IAAI,KAAK,GAAG,CAAC,EAAE;QACX,IAAI,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE;YAC1C,OAAO,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE;gBAC9C,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;aAC5C;SACJ;aAAM;YACH,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC9E,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;SACnD;KACJ;IAED,MAAA,MAAA,OAAO,CAAC,wBAAwB,EAAC,EAAE,mDAAG,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAE/D,IAAM,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC;IACzC,IAAI,UAAU,EAAE;QACZ,IAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAClE,IAAI,SAAS,CAAC,SAAS,IAAI,YAAY,IAAI,SAAS,CAAC,cAAc,IAAI,UAAU,EAAE;YAC/E,IAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACnE,mBAAmB,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SACvD;KACJ;IAED,IAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,UAAA,CAAC;QACvB,IAAM,QAAQ,GAA0B;YACpC,OAAO,4BAAO,CAAC,CAAC,OAAO,CAAE;YACzB,MAAM,4BAAO,CAAC,CAAC,MAAM,CAAE;YACvB,QAAQ,EAAE,CAAC,CAAC,QAAQ;SACvB,CAAC;QACF,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IACH,UAAU,CAAC,iBAAiB,GAAG,SAAS,CAAC;IACzC,UAAU,CAAC,MAAM,GAAG,EAAE,CAAC;AAC3B,CAAC,CAAC;AAEF;;;;GAIG;AACH,IAAM,iBAAiB,GAAkD,UACrE,MAAuC,EACvC,OAAoB;IAEpB,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,KAAK,OAAO,EAAE;QACnC,MAAM,CAAC,mBAAmB,GAAG,SAAS,CAAC;KAC1C;IAED,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,WAAW,GAAG,SAAS,CAAC;AACnC,CAAC,CAAC;AAEF;;GAEG;AACH,IAAM,kBAAkB,GAAkD,UACtE,MAAuC;IAEvC,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,WAAW,GAAG,SAAS,CAAC;AACnC,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,sBAAsB,CAC3B,UAAkB,EAClB,OAAoB,EACpB,OAA0B;IAE1B,OAAO,CACH,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QACpC,iBAAiB,CAAC,KAAK,CAAC,UAAA,GAAG,IAAI,OAAA,GAAG,IAAI,UAAU,EAAjB,CAAiB,CAAC;QACjD,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAC1C,CAAC;AACN,CAAC;AAED,IAAM,gBAAgB,GAA4C,UAC9D,MAAiC,EACjC,OAAoB;IAEpB,IACI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,mCAAuB,CAAC;QACnD,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,2CAA+B,CAAC,EAC7D;QACE,OAAO,MAAM,CAAC,eAAe,CAAC;KACjC;AACL,CAAC,CAAC;AACF;;;;;;GAMG;AACH,SAAgB,iCAAiC,CAAC,EAAoB;IAClE,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAC;IAC7D,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;IACpE,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;IACrE,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAChE,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAChE,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC;IAC5D,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAE5D,IAAA,2BAAY,EAAC,EAAE,CAAC,gBAAgB,EAAE,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAClE,IAAA,2BAAY,EAAC,EAAE,CAAC,gBAAgB,EAAE,IAAI,EAAE,qBAAqB,CAAC,CAAC;AACnE,CAAC;AAXD,8EAWC;AAED,IAAM,kBAAkB,GAA0C,UAC9D,MAA+B,EAC/B,OAAoB;IAEpB,IAAI,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QAC1C,OAAO,MAAM,CAAC,UAAU,CAAC;KAC5B;AACL,CAAC,CAAC;AAEF,SAAS,mBAAmB,CACxB,YAA+C,EAC/C,OAAsB,EACtB,GAAsB;IAEtB,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,QAAQ,IAAI,IAAI,EAAE;QAChD,OAAO;KACV;IAED,IAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,IAAM,UAAU,GAAG,GAAG,CAAC,UAAwB,CAAC;IAC1C,IAAA,KAAA,oBAAqB,uBAAuB,CAAC,IAAI,EAAE,OAAO,CAAC,IAAA,EAA1D,KAAK,QAAA,EAAE,SAAS,QAA0C,CAAC;IAElE,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE;QAC5B,UAAU,CAAC,cAAc,GAAG,EAAE,CAAC;KAClC;IAED,IAAM,MAAM,GAAuB,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACxE,IAAI,MAAM,IAAI,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE;QAC/B,YAAY,CAAC,MAAM,CAAC,mBAAmB,GAAG,KAAK,CAAC;KACnD;IACD,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;AACjD,CAAC;AACD,SAAS,uBAAuB,CAC5B,IAAoC,EACpC,IAAoC;IAEpC,IAAM,SAAS,GACX,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,CAAC,IAAI,CAAC,KAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAqB,CAAC,CAAC;IAC1F,IAAM,KAAK,GACP,QAAQ,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,YAAY,CAAC,OAAO,CAAC,KAAI,GAAG,CAAC,GAAG,CAAC,SAAS,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChG,IAAM,SAAS,GAAG,QAAQ,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,YAAY,CAAC,iBAAiB,CAAC,KAAI,EAAE,CAAC,CAAC;IAExE,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAC9B,CAAC","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { createListLevel, parseFormat } from 'roosterjs-content-model-dom';\nimport { setProcessor } from '../utils/setProcessor';\nimport {\n COMMENT_HIGHLIGHT_CLASS,\n COMMENT_HIGHLIGHT_CLICKED_CLASS,\n LIST_CONTAINER_ELEMENT_CLASS_NAME,\n REMOVE_MARGIN_ELEMENTS,\n TEMP_ELEMENTS_CLASSES,\n} from './constants';\nimport type {\n BeforePasteEvent,\n ContentModelBlockFormat,\n ContentModelBlockGroup,\n ContentModelListItemLevelFormat,\n ContentModelListLevel,\n ContentModelSegmentFormat,\n DomToModelContext,\n DomToModelListFormat,\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\ninterface WacContext extends DomToModelListFormat {\n /**\n * Current list levels\n */\n currentListLevels?: ContentModelListLevel[];\n /**\n * Array to keep the start of the lists and determine if the start override should be set.\n */\n listItemThread?: number[];\n}\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(REMOVE_MARGIN_ELEMENTS)) {\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 const level = parseInt(element.getAttribute('data-aria-level') ?? '');\n const listFormat = context.listFormat as WacContext;\n const listType =\n listFormat.levels[context.listFormat.levels.length - 1]?.listType ||\n (element.closest('ol,ul')?.tagName.toUpperCase() as 'UL' | 'OL');\n const newLevel: ContentModelListLevel = createListLevel(listType, context.blockFormat);\n parseFormat(element, context.formatParsers.listLevelThread, newLevel.format, context);\n parseFormat(element, context.formatParsers.listLevel, newLevel.format, context);\n context.listFormat.levels = listFormat.currentListLevels || context.listFormat.levels;\n\n if (level > 0) {\n if (level > context.listFormat.levels.length) {\n while (level != context.listFormat.levels.length) {\n context.listFormat.levels.push(newLevel);\n }\n } else {\n context.listFormat.levels.splice(level, context.listFormat.levels.length - 1);\n context.listFormat.levels[level - 1] = newLevel;\n }\n }\n\n context.defaultElementProcessors.li?.(group, element, context);\n\n const listParent = listFormat.listParent;\n if (listParent) {\n const lastblock = listParent.blocks[listParent.blocks.length - 1];\n if (lastblock.blockType == 'BlockGroup' && lastblock.blockGroupType == 'ListItem') {\n const currentLevel = lastblock.levels[lastblock.levels.length - 1];\n updateStartOverride(currentLevel, element, context);\n }\n }\n\n const newLevels: ContentModelListLevel[] = [];\n listFormat.levels.forEach(v => {\n const newValue: ContentModelListLevel = {\n dataset: { ...v.dataset },\n format: { ...v.format },\n listType: v.listType,\n };\n newLevels.push(newValue);\n });\n listFormat.currentListLevels = newLevels;\n listFormat.levels = [];\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 format.marginRight = 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.className.includes(COMMENT_HIGHLIGHT_CLICKED_CLASS)\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 BeforePasteEvent\n */\nexport function processPastedContentWacComponents(ev: BeforePasteEvent) {\n addParser(ev.domToModelOption, 'segment', wacSubSuperParser);\n addParser(ev.domToModelOption, 'listItemThread', wacListItemParser);\n addParser(ev.domToModelOption, 'listItemElement', 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}\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\nfunction updateStartOverride(\n currentLevel: ContentModelListLevel | undefined,\n element: HTMLLIElement,\n ctx: DomToModelContext\n) {\n if (!currentLevel || currentLevel.listType == 'UL') {\n return;\n }\n\n const list = element.closest('ol');\n const listFormat = ctx.listFormat as WacContext;\n const [start, listLevel] = extractWordListMetadata(list, element);\n\n if (!listFormat.listItemThread) {\n listFormat.listItemThread = [];\n }\n\n const thread: number | undefined = listFormat.listItemThread[listLevel];\n if (thread && start - thread != 1) {\n currentLevel.format.startNumberOverride = start;\n }\n listFormat.listItemThread[listLevel] = start;\n}\nfunction extractWordListMetadata(\n list: HTMLElement | null | undefined,\n item: HTMLElement | null | undefined\n) {\n const itemIndex =\n item && Array.from(list?.querySelectorAll('li') || []).indexOf(item as HTMLLIElement);\n const start =\n parseInt(list?.getAttribute('start') || '1') + (itemIndex && itemIndex > 0 ? itemIndex : 0);\n const listLevel = parseInt(item?.getAttribute('data-aria-level') || '');\n\n return [start, listLevel];\n}\n"]}
1
+ {"version":3,"file":"processPastedContentWacComponents.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/WacComponents/processPastedContentWacComponents.ts"],"names":[],"mappings":";;;;AAAA,gDAA+C;AAC/C,2EAA2E;AAC3E,sDAAqD;AACrD,yCAMqB;AAcrB,IAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC7C,IAAM,qBAAqB,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1D,IAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B,IAAM,cAAc,GAAG,UAAU,CAAC;AAalC;;;GAGG;AACH,IAAM,iBAAiB,GAA4C,UAC/D,MAAiC,EACjC,OAAoB;IAEpB,IAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC;IAClD,IAAI,aAAa,KAAK,OAAO,EAAE;QAC3B,MAAM,CAAC,wBAAwB,GAAG,OAAO,CAAC;KAC7C;IACD,IAAI,aAAa,KAAK,KAAK,EAAE;QACzB,MAAM,CAAC,wBAAwB,GAAG,KAAK,CAAC;KAC3C;AACL,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,IAAM,mBAAmB,GAAkC,UACvD,KAA6B,EAC7B,OAAoB,EACpB,OAA0B;IAE1B,IAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAEnC,IAAI,OAAO,CAAC,OAAO,CAAC,kCAAsB,CAAC,EAAE;QACzC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACxC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;KAC1C;IAED,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,6CAAiC,CAAC,EAAE;QAC/D,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACzD,OAAO;KACV;IAED,IACI,iCAAqB,CAAC,IAAI,CAAC,UAAA,SAAS,IAAI,OAAA,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,EAArC,CAAqC,CAAC;QAC9E,iGAAiG;QACjG,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,EAC9F;QACE,OAAO;KACV;SAAM,IAAI,sBAAsB,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QACrD,IAAA,UAAU,GAAK,OAAO,WAAZ,CAAa;QAC/B,UAAU,CAAC,MAAM,GAAG,EAAE,CAAC;QACvB,UAAU,CAAC,UAAU,GAAG,SAAS,CAAC;KACrC;IAED,OAAO,CAAC,wBAAwB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC,CAAC;AAEF;;GAEG;AACH,IAAM,qBAAqB,GAAoC,UAC3D,KAA6B,EAC7B,OAAsB,EACtB,OAA0B;;IAE1B,IAAM,KAAK,GAAG,QAAQ,CAAC,MAAA,OAAO,CAAC,YAAY,CAAC,iBAAiB,CAAC,mCAAI,EAAE,CAAC,CAAC;IACtE,IAAM,UAAU,GAAG,OAAO,CAAC,UAAwB,CAAC;IACpD,IAAM,QAAQ,GACV,CAAA,MAAA,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,0CAAE,QAAQ;SAChE,MAAA,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,0CAAE,OAAO,CAAC,WAAW,EAAkB,CAAA,CAAC;IACrE,IAAM,QAAQ,GAA0B,IAAA,6CAAe,EAAC,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IACvF,IAAA,yCAAW,EAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,eAAe,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtF,IAAA,yCAAW,EAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChF,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,UAAU,CAAC,iBAAiB,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;IAEtF,IAAI,KAAK,GAAG,CAAC,EAAE;QACX,IAAI,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE;YAC1C,OAAO,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE;gBAC9C,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;aAC5C;SACJ;aAAM;YACH,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC9E,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;SACnD;KACJ;IAED,MAAA,MAAA,OAAO,CAAC,wBAAwB,EAAC,EAAE,mDAAG,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAE/D,IAAM,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC;IACzC,IAAI,UAAU,EAAE;QACZ,IAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAClE,IAAI,SAAS,CAAC,SAAS,IAAI,YAAY,IAAI,SAAS,CAAC,cAAc,IAAI,UAAU,EAAE;YAC/E,IAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACnE,mBAAmB,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SACvD;KACJ;IAED,IAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,UAAA,CAAC;QACvB,IAAM,QAAQ,GAA0B;YACpC,OAAO,4BAAO,CAAC,CAAC,OAAO,CAAE;YACzB,MAAM,4BAAO,CAAC,CAAC,MAAM,CAAE;YACvB,QAAQ,EAAE,CAAC,CAAC,QAAQ;SACvB,CAAC;QACF,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IACH,UAAU,CAAC,iBAAiB,GAAG,SAAS,CAAC;IACzC,UAAU,CAAC,MAAM,GAAG,EAAE,CAAC;AAC3B,CAAC,CAAC;AAEF;;;;GAIG;AACH,IAAM,iBAAiB,GAAkD,UACrE,MAAuC,EACvC,OAAoB;IAEpB,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,KAAK,OAAO,EAAE;QACnC,MAAM,CAAC,mBAAmB,GAAG,SAAS,CAAC;KAC1C;IAED,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,WAAW,GAAG,SAAS,CAAC;AACnC,CAAC,CAAC;AAEF;;GAEG;AACH,IAAM,kBAAkB,GAAkD,UACtE,MAAuC;IAEvC,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,WAAW,GAAG,SAAS,CAAC;AACnC,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,sBAAsB,CAC3B,UAAkB,EAClB,OAAoB,EACpB,OAA0B;IAE1B,OAAO,CACH,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QACpC,iBAAiB,CAAC,KAAK,CAAC,UAAA,GAAG,IAAI,OAAA,GAAG,IAAI,UAAU,EAAjB,CAAiB,CAAC;QACjD,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAC1C,CAAC;AACN,CAAC;AAED,IAAM,gBAAgB,GAA4C,UAC9D,MAAiC,EACjC,OAAoB;IAEpB,IACI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,mCAAuB,CAAC;QACnD,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,2CAA+B,CAAC,EAC7D;QACE,OAAO,MAAM,CAAC,eAAe,CAAC;KACjC;AACL,CAAC,CAAC;AACF;;;;;;GAMG;AACH,SAAgB,iCAAiC,CAAC,EAAoB;IAClE,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAC;IAC7D,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;IACpE,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;IACrE,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAChE,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAChE,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC;IAC5D,IAAA,qBAAS,EAAC,EAAE,CAAC,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAE5D,IAAA,2BAAY,EAAC,EAAE,CAAC,gBAAgB,EAAE,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAClE,IAAA,2BAAY,EAAC,EAAE,CAAC,gBAAgB,EAAE,IAAI,EAAE,qBAAqB,CAAC,CAAC;AACnE,CAAC;AAXD,8EAWC;AAED,IAAM,kBAAkB,GAA0C,UAC9D,MAA+B,EAC/B,OAAoB;IAEpB,IAAI,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QAC1C,OAAO,MAAM,CAAC,UAAU,CAAC;KAC5B;AACL,CAAC,CAAC;AAEF,SAAS,mBAAmB,CACxB,YAA+C,EAC/C,OAAsB,EACtB,GAAsB;IAEtB,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,QAAQ,IAAI,IAAI,EAAE;QAChD,OAAO;KACV;IAED,IAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,IAAM,UAAU,GAAG,GAAG,CAAC,UAAwB,CAAC;IAC1C,IAAA,KAAA,oBAAqB,uBAAuB,CAAC,IAAI,EAAE,OAAO,CAAC,IAAA,EAA1D,KAAK,QAAA,EAAE,SAAS,QAA0C,CAAC;IAElE,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE;QAC5B,UAAU,CAAC,cAAc,GAAG,EAAE,CAAC;KAClC;IAED,IAAM,MAAM,GAAuB,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACxE,IAAI,MAAM,IAAI,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE;QAC/B,YAAY,CAAC,MAAM,CAAC,mBAAmB,GAAG,KAAK,CAAC;KACnD;IACD,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;AACjD,CAAC;AACD,SAAS,uBAAuB,CAC5B,IAAoC,EACpC,IAAoC;IAEpC,IAAM,SAAS,GACX,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,CAAC,IAAI,CAAC,KAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAqB,CAAC,CAAC;IAC1F,IAAM,KAAK,GACP,QAAQ,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,YAAY,CAAC,OAAO,CAAC,KAAI,GAAG,CAAC,GAAG,CAAC,SAAS,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChG,IAAM,SAAS,GAAG,QAAQ,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,YAAY,CAAC,iBAAiB,CAAC,KAAI,EAAE,CAAC,CAAC;IAExE,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAC9B,CAAC","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { createListLevel, parseFormat } from 'roosterjs-content-model-dom';\nimport { setProcessor } from '../utils/setProcessor';\nimport {\n COMMENT_HIGHLIGHT_CLASS,\n COMMENT_HIGHLIGHT_CLICKED_CLASS,\n LIST_CONTAINER_ELEMENT_CLASS_NAME,\n REMOVE_MARGIN_ELEMENTS,\n TEMP_ELEMENTS_CLASSES,\n} from './constants';\nimport type {\n BeforePasteEvent,\n ContentModelBlockFormat,\n ContentModelBlockGroup,\n ContentModelListItemLevelFormat,\n ContentModelListLevel,\n ContentModelSegmentFormat,\n DomToModelContext,\n DomToModelListFormat,\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(',');\nconst END_OF_PARAGRAPH = 'EOP';\nconst SELECTED_CLASS = 'Selected';\n\ninterface WacContext extends DomToModelListFormat {\n /**\n * Current list levels\n */\n currentListLevels?: ContentModelListLevel[];\n /**\n * Array to keep the start of the lists and determine if the start override should be set.\n */\n listItemThread?: number[];\n}\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(REMOVE_MARGIN_ELEMENTS)) {\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 (\n TEMP_ELEMENTS_CLASSES.some(className => element.classList.contains(className)) ||\n // This is needed to remove some temporary End of paragraph elements that WAC sometimes preserves\n (element.classList.contains(SELECTED_CLASS) && element.classList.contains(END_OF_PARAGRAPH))\n ) {\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 const level = parseInt(element.getAttribute('data-aria-level') ?? '');\n const listFormat = context.listFormat as WacContext;\n const listType =\n listFormat.levels[context.listFormat.levels.length - 1]?.listType ||\n (element.closest('ol,ul')?.tagName.toUpperCase() as 'UL' | 'OL');\n const newLevel: ContentModelListLevel = createListLevel(listType, context.blockFormat);\n parseFormat(element, context.formatParsers.listLevelThread, newLevel.format, context);\n parseFormat(element, context.formatParsers.listLevel, newLevel.format, context);\n context.listFormat.levels = listFormat.currentListLevels || context.listFormat.levels;\n\n if (level > 0) {\n if (level > context.listFormat.levels.length) {\n while (level != context.listFormat.levels.length) {\n context.listFormat.levels.push(newLevel);\n }\n } else {\n context.listFormat.levels.splice(level, context.listFormat.levels.length - 1);\n context.listFormat.levels[level - 1] = newLevel;\n }\n }\n\n context.defaultElementProcessors.li?.(group, element, context);\n\n const listParent = listFormat.listParent;\n if (listParent) {\n const lastblock = listParent.blocks[listParent.blocks.length - 1];\n if (lastblock.blockType == 'BlockGroup' && lastblock.blockGroupType == 'ListItem') {\n const currentLevel = lastblock.levels[lastblock.levels.length - 1];\n updateStartOverride(currentLevel, element, context);\n }\n }\n\n const newLevels: ContentModelListLevel[] = [];\n listFormat.levels.forEach(v => {\n const newValue: ContentModelListLevel = {\n dataset: { ...v.dataset },\n format: { ...v.format },\n listType: v.listType,\n };\n newLevels.push(newValue);\n });\n listFormat.currentListLevels = newLevels;\n listFormat.levels = [];\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 format.marginRight = 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.className.includes(COMMENT_HIGHLIGHT_CLICKED_CLASS)\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 BeforePasteEvent\n */\nexport function processPastedContentWacComponents(ev: BeforePasteEvent) {\n addParser(ev.domToModelOption, 'segment', wacSubSuperParser);\n addParser(ev.domToModelOption, 'listItemThread', wacListItemParser);\n addParser(ev.domToModelOption, 'listItemElement', 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}\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\nfunction updateStartOverride(\n currentLevel: ContentModelListLevel | undefined,\n element: HTMLLIElement,\n ctx: DomToModelContext\n) {\n if (!currentLevel || currentLevel.listType == 'UL') {\n return;\n }\n\n const list = element.closest('ol');\n const listFormat = ctx.listFormat as WacContext;\n const [start, listLevel] = extractWordListMetadata(list, element);\n\n if (!listFormat.listItemThread) {\n listFormat.listItemThread = [];\n }\n\n const thread: number | undefined = listFormat.listItemThread[listLevel];\n if (thread && start - thread != 1) {\n currentLevel.format.startNumberOverride = start;\n }\n listFormat.listItemThread[listLevel] = start;\n}\nfunction extractWordListMetadata(\n list: HTMLElement | null | undefined,\n item: HTMLElement | null | undefined\n) {\n const itemIndex =\n item && Array.from(list?.querySelectorAll('li') || []).indexOf(item as HTMLLIElement);\n const start =\n parseInt(list?.getAttribute('start') || '1') + (itemIndex && itemIndex > 0 ? itemIndex : 0);\n const listLevel = parseInt(item?.getAttribute('data-aria-level') || '');\n\n return [start, listLevel];\n}\n"]}
@@ -8,6 +8,7 @@ var getStyles_1 = require("../utils/getStyles");
8
8
  var listLevelParser_1 = require("../parsers/listLevelParser");
9
9
  var processWordComments_1 = require("./processWordComments");
10
10
  var processWordLists_1 = require("./processWordLists");
11
+ var adjustWordListMarginParser_1 = require("../parsers/adjustWordListMarginParser");
11
12
  var removeNegativeTextIndentParser_1 = require("../parsers/removeNegativeTextIndentParser");
12
13
  var setProcessor_1 = require("../utils/setProcessor");
13
14
  var wordContainerParser_1 = require("../parsers/wordContainerParser");
@@ -24,6 +25,7 @@ function processPastedContentFromWordDesktop(domToModelOption, htmlString) {
24
25
  (0, addParser_1.addParser)(domToModelOption, 'block', adjustPercentileLineHeightParser_1.adjustPercentileLineHeight);
25
26
  (0, addParser_1.addParser)(domToModelOption, 'block', removeNegativeTextIndentParser_1.removeNegativeTextIndentParser);
26
27
  (0, addParser_1.addParser)(domToModelOption, 'listItemElement', removeNegativeTextIndentParser_1.removeNegativeTextIndentParser);
28
+ (0, addParser_1.addParser)(domToModelOption, 'listItemElement', adjustWordListMarginParser_1.adjustWordListMarginParser);
27
29
  (0, addParser_1.addParser)(domToModelOption, 'listLevel', listLevelParser_1.listLevelParser);
28
30
  (0, addParser_1.addParser)(domToModelOption, 'container', wordContainerParser_1.wordContainerParser);
29
31
  (0, addParser_1.addParser)(domToModelOption, 'table', wordTableParser_1.wordTableParser);
@@ -1 +1 @@
1
- {"version":3,"file":"processPastedContentFromWordDesktop.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/WordDesktop/processPastedContentFromWordDesktop.ts"],"names":[],"mappings":";;;AAAA,gDAA+C;AAC/C,gGAAyF;AACzF,uDAAsD;AACtD,gDAA+C;AAC/C,8DAA6D;AAC7D,6DAA4D;AAC5D,uDAAqD;AACrD,4FAA2F;AAC3F,sDAAqD;AACrD,sEAAqE;AACrE,8DAA6D;AAI7D;;;;;GAKG;AACH,SAAgB,mCAAmC,CAC/C,gBAAkC,EAClC,UAAkB;IAElB,IAAM,WAAW,GAA8B,IAAA,mCAAgB,EAAC,UAAU,CAAC,CAAC;IAE5E,IAAA,2BAAY,EAAC,gBAAgB,EAAE,SAAS,EAAE,2BAA2B,CAAC,WAAW,CAAC,CAAC,CAAC;IACpF,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,6DAA0B,CAAC,CAAC;IACjE,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,+DAA8B,CAAC,CAAC;IACrE,IAAA,qBAAS,EAAC,gBAAgB,EAAE,iBAAiB,EAAE,+DAA8B,CAAC,CAAC;IAC/E,IAAA,qBAAS,EAAC,gBAAgB,EAAE,WAAW,EAAE,iCAAe,CAAC,CAAC;IAC1D,IAAA,qBAAS,EAAC,gBAAgB,EAAE,WAAW,EAAE,yCAAmB,CAAC,CAAC;IAC9D,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,iCAAe,CAAC,CAAC;AAC1D,CAAC;AAbD,kFAaC;AAED,IAAM,2BAA2B,GAAG,UAChC,WAAsC;IAEtC,OAAO,UAAC,KAAK,EAAE,OAAO,EAAE,OAAO;QAC3B,IAAM,MAAM,GAAG,IAAA,qBAAS,EAAC,OAAO,CAAC,CAAC;QAClC,4FAA4F;QAC5F,IACI,CAAC,CACG,IAAA,kCAAe,EAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC;YAC7D,IAAA,yCAAmB,EAAC,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 { 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, '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,gDAA+C;AAC/C,gGAAyF;AACzF,uDAAsD;AACtD,gDAA+C;AAC/C,8DAA6D;AAC7D,6DAA4D;AAC5D,uDAAqD;AACrD,oFAAmF;AACnF,4FAA2F;AAC3F,sDAAqD;AACrD,sEAAqE;AACrE,8DAA6D;AAI7D;;;;;GAKG;AACH,SAAgB,mCAAmC,CAC/C,gBAAkC,EAClC,UAAkB;IAElB,IAAM,WAAW,GAA8B,IAAA,mCAAgB,EAAC,UAAU,CAAC,CAAC;IAE5E,IAAA,2BAAY,EAAC,gBAAgB,EAAE,SAAS,EAAE,2BAA2B,CAAC,WAAW,CAAC,CAAC,CAAC;IACpF,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,6DAA0B,CAAC,CAAC;IACjE,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,+DAA8B,CAAC,CAAC;IACrE,IAAA,qBAAS,EAAC,gBAAgB,EAAE,iBAAiB,EAAE,+DAA8B,CAAC,CAAC;IAC/E,IAAA,qBAAS,EAAC,gBAAgB,EAAE,iBAAiB,EAAE,uDAA0B,CAAC,CAAC;IAC3E,IAAA,qBAAS,EAAC,gBAAgB,EAAE,WAAW,EAAE,iCAAe,CAAC,CAAC;IAC1D,IAAA,qBAAS,EAAC,gBAAgB,EAAE,WAAW,EAAE,yCAAmB,CAAC,CAAC;IAC9D,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,iCAAe,CAAC,CAAC;AAC1D,CAAC;AAdD,kFAcC;AAED,IAAM,2BAA2B,GAAG,UAChC,WAAsC;IAEtC,OAAO,UAAC,KAAK,EAAE,OAAO,EAAE,OAAO;QAC3B,IAAM,MAAM,GAAG,IAAA,qBAAS,EAAC,OAAO,CAAC,CAAC;QAClC,4FAA4F;QAC5F,IACI,CAAC,CACG,IAAA,kCAAe,EAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC;YAC7D,IAAA,yCAAmB,EAAC,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"]}
@@ -0,0 +1,9 @@
1
+ import type { FormatParser, MarginFormat } from 'roosterjs-content-model-types';
2
+ /**
3
+ * @internal
4
+ * Parser that subtracts the default list format (paddingInlineStart: 40px) from
5
+ * the marginLeft of list item elements that have the MsoListParagraph class,
6
+ * since Word adds the full indentation as margin on the paragraph, which
7
+ * duplicates the padding the list element already provides.
8
+ */
9
+ export declare const adjustWordListMarginParser: FormatParser<MarginFormat>;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.adjustWordListMarginParser = void 0;
4
+ var roosterjs_content_model_dom_1 = require("roosterjs-content-model-dom");
5
+ var MSO_LIST_PARAGRAPH_CLASS = 'MsoListParagraph';
6
+ // Default list padding from the HTML user-agent stylesheet (paddingInlineStart for <ul>/<ol>)
7
+ var DEFAULT_LIST_PADDING_INLINE_START = '40px';
8
+ /**
9
+ * @internal
10
+ * Parser that subtracts the default list format (paddingInlineStart: 40px) from
11
+ * the marginLeft of list item elements that have the MsoListParagraph class,
12
+ * since Word adds the full indentation as margin on the paragraph, which
13
+ * duplicates the padding the list element already provides.
14
+ */
15
+ var adjustWordListMarginParser = function (format, element) {
16
+ if (element.classList.contains(MSO_LIST_PARAGRAPH_CLASS) && format.marginLeft) {
17
+ var currentPx = (0, roosterjs_content_model_dom_1.parseValueWithUnit)(format.marginLeft, element);
18
+ var defaultPx = (0, roosterjs_content_model_dom_1.parseValueWithUnit)(DEFAULT_LIST_PADDING_INLINE_START);
19
+ var result = currentPx - defaultPx;
20
+ if (result > 0) {
21
+ format.marginLeft = result + "px";
22
+ }
23
+ }
24
+ };
25
+ exports.adjustWordListMarginParser = adjustWordListMarginParser;
26
+ //# sourceMappingURL=adjustWordListMarginParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adjustWordListMarginParser.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/parsers/adjustWordListMarginParser.ts"],"names":[],"mappings":";;;AAAA,2EAAiE;AAGjE,IAAM,wBAAwB,GAAG,kBAAkB,CAAC;AAEpD,8FAA8F;AAC9F,IAAM,iCAAiC,GAAG,MAAM,CAAC;AAEjD;;;;;;GAMG;AACI,IAAM,0BAA0B,GAA+B,UAClE,MAAoB,EACpB,OAAoB;IAEpB,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,wBAAwB,CAAC,IAAI,MAAM,CAAC,UAAU,EAAE;QAC3E,IAAM,SAAS,GAAG,IAAA,gDAAkB,EAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjE,IAAM,SAAS,GAAG,IAAA,gDAAkB,EAAC,iCAAiC,CAAC,CAAC;QACxE,IAAM,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;QAErC,IAAI,MAAM,GAAG,CAAC,EAAE;YACZ,MAAM,CAAC,UAAU,GAAM,MAAM,OAAI,CAAC;SACrC;KACJ;AACL,CAAC,CAAC;AAbW,QAAA,0BAA0B,8BAarC","sourcesContent":["import { parseValueWithUnit } from 'roosterjs-content-model-dom';\nimport type { FormatParser, MarginFormat } from 'roosterjs-content-model-types';\n\nconst MSO_LIST_PARAGRAPH_CLASS = 'MsoListParagraph';\n\n// Default list padding from the HTML user-agent stylesheet (paddingInlineStart for <ul>/<ol>)\nconst DEFAULT_LIST_PADDING_INLINE_START = '40px';\n\n/**\n * @internal\n * Parser that subtracts the default list format (paddingInlineStart: 40px) from\n * the marginLeft of list item elements that have the MsoListParagraph class,\n * since Word adds the full indentation as margin on the paragraph, which\n * duplicates the padding the list element already provides.\n */\nexport const adjustWordListMarginParser: FormatParser<MarginFormat> = (\n format: MarginFormat,\n element: HTMLElement\n): void => {\n if (element.classList.contains(MSO_LIST_PARAGRAPH_CLASS) && format.marginLeft) {\n const currentPx = parseValueWithUnit(format.marginLeft, element);\n const defaultPx = parseValueWithUnit(DEFAULT_LIST_PADDING_INLINE_START);\n const result = currentPx - defaultPx;\n\n if (result > 0) {\n format.marginLeft = `${result}px`;\n }\n }\n};\n"]}
@@ -6,7 +6,6 @@ var createElement_1 = require("../../../pluginUtils/CreateElement/createElement"
6
6
  var DragAndDropHelper_1 = require("../../../pluginUtils/DragAndDrop/DragAndDropHelper");
7
7
  var roosterjs_content_model_api_1 = require("roosterjs-content-model-api");
8
8
  var getTableFromContentModel_1 = require("../utils/getTableFromContentModel");
9
- var getNodePositionFromEvent_1 = require("../../../utils/getNodePositionFromEvent");
10
9
  var roosterjs_content_model_dom_1 = require("roosterjs-content-model-dom");
11
10
  var TABLE_MOVER_LENGTH = 12;
12
11
  /**
@@ -134,7 +133,7 @@ function onDragging(context, event, initValue) {
134
133
  // Move table outline rectangle
135
134
  tableRect.style.top = event.clientY + TABLE_MOVER_LENGTH + "px";
136
135
  tableRect.style.left = event.clientX + TABLE_MOVER_LENGTH + "px";
137
- var pos = (0, getNodePositionFromEvent_1.getNodePositionFromEvent)(editor, event.clientX, event.clientY);
136
+ var pos = (0, roosterjs_content_model_dom_1.getNodePositionFromEvent)(editor.getDocument(), editor.getDOMHelper(), event.clientX, event.clientY);
138
137
  if (pos) {
139
138
  var range = editor.getDocument().createRange();
140
139
  range.setStart(pos.node, pos.offset);
@@ -174,7 +173,7 @@ function onDragEnd(context, event, initValue) {
174
173
  }
175
174
  var insertionSuccess_1 = false;
176
175
  // Get position to insert table
177
- var insertPosition = (0, getNodePositionFromEvent_1.getNodePositionFromEvent)(editor, event.clientX, event.clientY);
176
+ var insertPosition = (0, roosterjs_content_model_dom_1.getNodePositionFromEvent)(editor.getDocument(), editor.getDOMHelper(), event.clientX, event.clientY);
178
177
  if (insertPosition) {
179
178
  // Move table to new position
180
179
  (0, roosterjs_content_model_api_1.formatInsertPointWithContentModel)(editor, insertPosition, function (model, context, ip) {
@@ -1 +1 @@
1
- {"version":3,"file":"TableMover.js","sourceRoot":"","sources":["../../../../../../packages/roosterjs-content-model-plugins/lib/tableEdit/editors/features/TableMover.ts"],"names":[],"mappings":"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","sourcesContent":["import { createElement } from '../../../pluginUtils/CreateElement/createElement';\nimport { DragAndDropHelper } from '../../../pluginUtils/DragAndDrop/DragAndDropHelper';\nimport { formatInsertPointWithContentModel } from 'roosterjs-content-model-api';\nimport { getCMTableFromTable } from '../utils/getTableFromContentModel';\nimport { getNodePositionFromEvent } from '../../../utils/getNodePositionFromEvent';\nimport type { TableEditFeature } from './TableEditFeature';\nimport type { OnTableEditorCreatedCallback } from '../../OnTableEditorCreatedCallback';\nimport type { DragAndDropHandler } from '../../../pluginUtils/DragAndDrop/DragAndDropHandler';\nimport {\n cloneModel,\n createContentModelDocument,\n createSelectionMarker,\n getFirstSelectedTable,\n isNodeOfType,\n mergeModel,\n mutateBlock,\n normalizeRect,\n setParagraphNotImplicit,\n setSelection,\n} from 'roosterjs-content-model-dom';\nimport type {\n DOMSelection,\n IEditor,\n ReadonlyContentModelTable,\n Rect,\n ShallowMutableContentModelDocument,\n} from 'roosterjs-content-model-types';\n\nconst TABLE_MOVER_LENGTH = 12;\n/**\n * @internal\n */\nexport const TABLE_MOVER_ID = '_Table_Mover';\nconst TABLE_MOVER_STYLE_KEY = '_TableMoverCursorStyle';\n\n/**\n * @internal\n * Allows user to move table to another position\n * Contains the function to select whole table\n */\nexport function createTableMover(\n table: HTMLTableElement,\n editor: IEditor,\n isRTL: boolean,\n onFinishDragging: (table: HTMLTableElement) => void,\n onStart: () => void,\n onEnd: (disposeHandler: boolean) => void,\n contentDiv?: EventTarget | null,\n anchorContainer?: HTMLElement,\n onTableEditorCreated?: OnTableEditorCreatedCallback,\n disableMovement?: boolean\n): TableEditFeature | null {\n const rect = normalizeRect(table.getBoundingClientRect());\n\n if (!isTableTopVisible(editor, rect, contentDiv as Node)) {\n return null;\n }\n\n const zoomScale = editor.getDOMHelper().calculateZoomScale();\n const document = table.ownerDocument;\n const createElementData = {\n tag: 'div',\n style: 'position: fixed; cursor: move; user-select: none; border: 1px solid #808080',\n };\n\n const div = createElement(createElementData, document) as HTMLDivElement;\n\n div.id = TABLE_MOVER_ID;\n div.style.width = `${TABLE_MOVER_LENGTH}px`;\n div.style.height = `${TABLE_MOVER_LENGTH}px`;\n\n (anchorContainer || document.body).appendChild(div);\n\n const context: TableMoverContext = {\n table,\n zoomScale,\n rect,\n isRTL,\n editor,\n div,\n onFinishDragging,\n onStart,\n onEnd,\n disableMovement,\n };\n\n setDivPosition(context, div);\n\n const featureHandler = new TableMoverFeature(\n div,\n context,\n () => {},\n disableMovement\n ? { onDragEnd }\n : {\n onDragStart,\n onDragging,\n onDragEnd,\n },\n context.zoomScale,\n onTableEditorCreated,\n editor.getEnvironment().isMobileOrTablet\n );\n\n return { node: table, div, featureHandler };\n}\n\n/**\n * @internal\n * Exported for testing\n */\nexport interface TableMoverContext {\n table: HTMLTableElement;\n zoomScale: number;\n rect: Rect | null;\n isRTL: boolean;\n editor: IEditor;\n div: HTMLElement;\n onFinishDragging: (table: HTMLTableElement) => void;\n onStart: () => void;\n onEnd: (disposeHandler: boolean) => void;\n disableMovement?: boolean;\n}\n\n/**\n * @internal\n * Exported for testing\n */\nexport interface TableMoverInitValue {\n cmTable: ReadonlyContentModelTable | undefined;\n initialSelection: DOMSelection | null;\n tableRect: HTMLDivElement;\n}\n\nclass TableMoverFeature extends DragAndDropHelper<TableMoverContext, TableMoverInitValue> {\n private disposer: undefined | (() => void);\n\n constructor(\n div: HTMLElement,\n context: TableMoverContext,\n onSubmit: (\n context: TableMoverContext,\n trigger: HTMLElement,\n container?: HTMLElement\n ) => void,\n handler: DragAndDropHandler<TableMoverContext, TableMoverInitValue>,\n zoomScale: number,\n onTableEditorCreated?: OnTableEditorCreatedCallback,\n forceMobile?: boolean | undefined\n ) {\n super(div, context, onSubmit, handler, zoomScale, forceMobile);\n this.disposer = onTableEditorCreated?.('TableMover', div);\n }\n\n dispose(): void {\n this.disposer?.();\n this.disposer = undefined;\n super.dispose();\n }\n}\n\nfunction setDivPosition(context: TableMoverContext, trigger: HTMLElement) {\n const { rect } = context;\n if (rect) {\n trigger.style.top = `${rect.top - TABLE_MOVER_LENGTH}px`;\n trigger.style.left = `${rect.left - TABLE_MOVER_LENGTH - 2}px`;\n }\n}\n\nfunction isTableTopVisible(editor: IEditor, rect: Rect | null, contentDiv?: Node | null): boolean {\n const visibleViewport = editor.getVisibleViewport();\n if (isNodeOfType(contentDiv, 'ELEMENT_NODE') && visibleViewport && rect) {\n const containerRect = normalizeRect(contentDiv.getBoundingClientRect());\n\n return !!containerRect && containerRect.top <= rect.top && visibleViewport.top <= rect.top;\n }\n\n return true;\n}\n\nfunction setTableMoverCursor(editor: IEditor, state: boolean, type?: 'move' | 'copy') {\n editor?.setEditorStyle(TABLE_MOVER_STYLE_KEY, state ? 'cursor: ' + type ?? 'move' : null);\n}\n\n/**\n * @internal\n * Exported for testing\n */\nexport function onDragStart(context: TableMoverContext): TableMoverInitValue {\n context.onStart();\n\n const { editor, table, div } = context;\n\n setTableMoverCursor(editor, true, 'move');\n\n // Create table outline rectangle\n const trect = table.getBoundingClientRect();\n const createElementData = {\n tag: 'div',\n style: 'position: fixed; user-select: none; border: 1px solid #808080',\n };\n const tableRect = createElement(createElementData, editor.getDocument()) as HTMLDivElement;\n tableRect.style.width = `${trect.width}px`;\n tableRect.style.height = `${trect.height}px`;\n tableRect.style.top = `${trect.top}px`;\n tableRect.style.left = `${trect.left}px`;\n div.parentNode?.appendChild(tableRect);\n\n // Get drag start selection\n const initialSelection = editor.getDOMSelection();\n\n // Get Table block in content model\n const cmTable = getCMTableFromTable(editor, table);\n\n return {\n cmTable,\n initialSelection,\n tableRect,\n };\n}\n\n/**\n * @internal\n * Exported for testing\n */\nexport function onDragging(\n context: TableMoverContext,\n event: MouseEvent,\n initValue: TableMoverInitValue\n) {\n const { tableRect } = initValue;\n const { editor } = context;\n\n // Move table outline rectangle\n tableRect.style.top = `${event.clientY + TABLE_MOVER_LENGTH}px`;\n tableRect.style.left = `${event.clientX + TABLE_MOVER_LENGTH}px`;\n\n const pos = getNodePositionFromEvent(editor, event.clientX, event.clientY);\n if (pos) {\n const range = editor.getDocument().createRange();\n range.setStart(pos.node, pos.offset);\n range.collapse(true);\n\n editor.setDOMSelection({ type: 'range', range, isReverted: false });\n return true;\n }\n return false;\n}\n\n/**\n * @internal\n * Exported for testing\n */\nexport function onDragEnd(\n context: TableMoverContext,\n event: MouseEvent,\n initValue: TableMoverInitValue | undefined\n) {\n const { editor, table, onFinishDragging: selectWholeTable, disableMovement } = context;\n const element = event.target;\n\n // Remove table outline rectangle\n initValue?.tableRect.remove();\n\n // Reset cursor\n setTableMoverCursor(editor, false);\n\n if (element == context.div) {\n // Table mover was only clicked, select whole table and do not dismiss the handler element.\n selectWholeTable(table);\n context.onEnd(false /* disposeHandler */);\n return true;\n } else {\n // Check if table was dragged on itself, element is not in editor, or movement is disabled\n if (\n table.contains(element as Node) ||\n !editor.getDOMHelper().isNodeInEditor(element as Node) ||\n disableMovement\n ) {\n editor.setDOMSelection(initValue?.initialSelection ?? null);\n context.onEnd(true /* disposeHandler */);\n return false;\n }\n\n let insertionSuccess: boolean = false;\n\n // Get position to insert table\n const insertPosition = getNodePositionFromEvent(editor, event.clientX, event.clientY);\n if (insertPosition) {\n // Move table to new position\n formatInsertPointWithContentModel(\n editor,\n insertPosition,\n (model, context, ip) => {\n // Remove old table\n const [oldTable, path] = getFirstSelectedTable(model);\n if (oldTable) {\n const index = path[0].blocks.indexOf(oldTable);\n mutateBlock(path[0]).blocks.splice(index, 1);\n }\n\n if (ip && initValue?.cmTable) {\n // Insert new table\n const doc: ShallowMutableContentModelDocument = createContentModelDocument();\n doc.blocks.push(oldTable ?? mutateBlock(initValue.cmTable));\n insertionSuccess = !!mergeModel(model, cloneModel(doc), context, {\n mergeFormat: 'none',\n insertPosition: ip,\n });\n\n if (insertionSuccess) {\n // After mergeModel, the new table should be selected\n const finalTable = getFirstSelectedTable(model)[0] ?? initValue.cmTable;\n if (finalTable) {\n // Add selection marker to the first cell of the table\n const firstCell = finalTable.rows[0].cells[0];\n const markerParagraph = firstCell?.blocks[0];\n\n if (markerParagraph?.blockType == 'Paragraph') {\n const marker = createSelectionMarker(model.format);\n\n mutateBlock(markerParagraph).segments.unshift(marker);\n setParagraphNotImplicit(markerParagraph);\n setSelection(model, marker);\n }\n }\n }\n return insertionSuccess;\n }\n },\n {\n // Select first cell of the old table\n selectionOverride: {\n type: 'table',\n firstColumn: 0,\n firstRow: 0,\n lastColumn: 0,\n lastRow: 0,\n table: table,\n },\n apiName: 'TableMover',\n }\n );\n } else {\n // No movement, restore initial selection\n editor.setDOMSelection(initValue?.initialSelection ?? null);\n }\n context.onEnd(true /* disposeHandler */);\n return insertionSuccess;\n }\n}\n"]}
1
+ {"version":3,"file":"TableMover.js","sourceRoot":"","sources":["../../../../../../packages/roosterjs-content-model-plugins/lib/tableEdit/editors/features/TableMover.ts"],"names":[],"mappings":"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","sourcesContent":["import { createElement } from '../../../pluginUtils/CreateElement/createElement';\nimport { DragAndDropHelper } from '../../../pluginUtils/DragAndDrop/DragAndDropHelper';\nimport { formatInsertPointWithContentModel } from 'roosterjs-content-model-api';\nimport { getCMTableFromTable } from '../utils/getTableFromContentModel';\nimport {\n cloneModel,\n createContentModelDocument,\n createSelectionMarker,\n getFirstSelectedTable,\n getNodePositionFromEvent,\n isNodeOfType,\n mergeModel,\n mutateBlock,\n normalizeRect,\n setParagraphNotImplicit,\n setSelection,\n} from 'roosterjs-content-model-dom';\nimport type { TableEditFeature } from './TableEditFeature';\nimport type { OnTableEditorCreatedCallback } from '../../OnTableEditorCreatedCallback';\nimport type { DragAndDropHandler } from '../../../pluginUtils/DragAndDrop/DragAndDropHandler';\nimport type {\n DOMSelection,\n IEditor,\n ReadonlyContentModelTable,\n Rect,\n ShallowMutableContentModelDocument,\n} from 'roosterjs-content-model-types';\n\nconst TABLE_MOVER_LENGTH = 12;\n/**\n * @internal\n */\nexport const TABLE_MOVER_ID = '_Table_Mover';\nconst TABLE_MOVER_STYLE_KEY = '_TableMoverCursorStyle';\n\n/**\n * @internal\n * Allows user to move table to another position\n * Contains the function to select whole table\n */\nexport function createTableMover(\n table: HTMLTableElement,\n editor: IEditor,\n isRTL: boolean,\n onFinishDragging: (table: HTMLTableElement) => void,\n onStart: () => void,\n onEnd: (disposeHandler: boolean) => void,\n contentDiv?: EventTarget | null,\n anchorContainer?: HTMLElement,\n onTableEditorCreated?: OnTableEditorCreatedCallback,\n disableMovement?: boolean\n): TableEditFeature | null {\n const rect = normalizeRect(table.getBoundingClientRect());\n\n if (!isTableTopVisible(editor, rect, contentDiv as Node)) {\n return null;\n }\n\n const zoomScale = editor.getDOMHelper().calculateZoomScale();\n const document = table.ownerDocument;\n const createElementData = {\n tag: 'div',\n style: 'position: fixed; cursor: move; user-select: none; border: 1px solid #808080',\n };\n\n const div = createElement(createElementData, document) as HTMLDivElement;\n\n div.id = TABLE_MOVER_ID;\n div.style.width = `${TABLE_MOVER_LENGTH}px`;\n div.style.height = `${TABLE_MOVER_LENGTH}px`;\n\n (anchorContainer || document.body).appendChild(div);\n\n const context: TableMoverContext = {\n table,\n zoomScale,\n rect,\n isRTL,\n editor,\n div,\n onFinishDragging,\n onStart,\n onEnd,\n disableMovement,\n };\n\n setDivPosition(context, div);\n\n const featureHandler = new TableMoverFeature(\n div,\n context,\n () => {},\n disableMovement\n ? { onDragEnd }\n : {\n onDragStart,\n onDragging,\n onDragEnd,\n },\n context.zoomScale,\n onTableEditorCreated,\n editor.getEnvironment().isMobileOrTablet\n );\n\n return { node: table, div, featureHandler };\n}\n\n/**\n * @internal\n * Exported for testing\n */\nexport interface TableMoverContext {\n table: HTMLTableElement;\n zoomScale: number;\n rect: Rect | null;\n isRTL: boolean;\n editor: IEditor;\n div: HTMLElement;\n onFinishDragging: (table: HTMLTableElement) => void;\n onStart: () => void;\n onEnd: (disposeHandler: boolean) => void;\n disableMovement?: boolean;\n}\n\n/**\n * @internal\n * Exported for testing\n */\nexport interface TableMoverInitValue {\n cmTable: ReadonlyContentModelTable | undefined;\n initialSelection: DOMSelection | null;\n tableRect: HTMLDivElement;\n}\n\nclass TableMoverFeature extends DragAndDropHelper<TableMoverContext, TableMoverInitValue> {\n private disposer: undefined | (() => void);\n\n constructor(\n div: HTMLElement,\n context: TableMoverContext,\n onSubmit: (\n context: TableMoverContext,\n trigger: HTMLElement,\n container?: HTMLElement\n ) => void,\n handler: DragAndDropHandler<TableMoverContext, TableMoverInitValue>,\n zoomScale: number,\n onTableEditorCreated?: OnTableEditorCreatedCallback,\n forceMobile?: boolean | undefined\n ) {\n super(div, context, onSubmit, handler, zoomScale, forceMobile);\n this.disposer = onTableEditorCreated?.('TableMover', div);\n }\n\n dispose(): void {\n this.disposer?.();\n this.disposer = undefined;\n super.dispose();\n }\n}\n\nfunction setDivPosition(context: TableMoverContext, trigger: HTMLElement) {\n const { rect } = context;\n if (rect) {\n trigger.style.top = `${rect.top - TABLE_MOVER_LENGTH}px`;\n trigger.style.left = `${rect.left - TABLE_MOVER_LENGTH - 2}px`;\n }\n}\n\nfunction isTableTopVisible(editor: IEditor, rect: Rect | null, contentDiv?: Node | null): boolean {\n const visibleViewport = editor.getVisibleViewport();\n if (isNodeOfType(contentDiv, 'ELEMENT_NODE') && visibleViewport && rect) {\n const containerRect = normalizeRect(contentDiv.getBoundingClientRect());\n\n return !!containerRect && containerRect.top <= rect.top && visibleViewport.top <= rect.top;\n }\n\n return true;\n}\n\nfunction setTableMoverCursor(editor: IEditor, state: boolean, type?: 'move' | 'copy') {\n editor?.setEditorStyle(TABLE_MOVER_STYLE_KEY, state ? 'cursor: ' + type ?? 'move' : null);\n}\n\n/**\n * @internal\n * Exported for testing\n */\nexport function onDragStart(context: TableMoverContext): TableMoverInitValue {\n context.onStart();\n\n const { editor, table, div } = context;\n\n setTableMoverCursor(editor, true, 'move');\n\n // Create table outline rectangle\n const trect = table.getBoundingClientRect();\n const createElementData = {\n tag: 'div',\n style: 'position: fixed; user-select: none; border: 1px solid #808080',\n };\n const tableRect = createElement(createElementData, editor.getDocument()) as HTMLDivElement;\n tableRect.style.width = `${trect.width}px`;\n tableRect.style.height = `${trect.height}px`;\n tableRect.style.top = `${trect.top}px`;\n tableRect.style.left = `${trect.left}px`;\n div.parentNode?.appendChild(tableRect);\n\n // Get drag start selection\n const initialSelection = editor.getDOMSelection();\n\n // Get Table block in content model\n const cmTable = getCMTableFromTable(editor, table);\n\n return {\n cmTable,\n initialSelection,\n tableRect,\n };\n}\n\n/**\n * @internal\n * Exported for testing\n */\nexport function onDragging(\n context: TableMoverContext,\n event: MouseEvent,\n initValue: TableMoverInitValue\n) {\n const { tableRect } = initValue;\n const { editor } = context;\n\n // Move table outline rectangle\n tableRect.style.top = `${event.clientY + TABLE_MOVER_LENGTH}px`;\n tableRect.style.left = `${event.clientX + TABLE_MOVER_LENGTH}px`;\n\n const pos = getNodePositionFromEvent(\n editor.getDocument(),\n editor.getDOMHelper(),\n event.clientX,\n event.clientY\n );\n if (pos) {\n const range = editor.getDocument().createRange();\n range.setStart(pos.node, pos.offset);\n range.collapse(true);\n\n editor.setDOMSelection({ type: 'range', range, isReverted: false });\n return true;\n }\n return false;\n}\n\n/**\n * @internal\n * Exported for testing\n */\nexport function onDragEnd(\n context: TableMoverContext,\n event: MouseEvent,\n initValue: TableMoverInitValue | undefined\n) {\n const { editor, table, onFinishDragging: selectWholeTable, disableMovement } = context;\n const element = event.target;\n\n // Remove table outline rectangle\n initValue?.tableRect.remove();\n\n // Reset cursor\n setTableMoverCursor(editor, false);\n\n if (element == context.div) {\n // Table mover was only clicked, select whole table and do not dismiss the handler element.\n selectWholeTable(table);\n context.onEnd(false /* disposeHandler */);\n return true;\n } else {\n // Check if table was dragged on itself, element is not in editor, or movement is disabled\n if (\n table.contains(element as Node) ||\n !editor.getDOMHelper().isNodeInEditor(element as Node) ||\n disableMovement\n ) {\n editor.setDOMSelection(initValue?.initialSelection ?? null);\n context.onEnd(true /* disposeHandler */);\n return false;\n }\n\n let insertionSuccess: boolean = false;\n\n // Get position to insert table\n const insertPosition = getNodePositionFromEvent(\n editor.getDocument(),\n editor.getDOMHelper(),\n event.clientX,\n event.clientY\n );\n if (insertPosition) {\n // Move table to new position\n formatInsertPointWithContentModel(\n editor,\n insertPosition,\n (model, context, ip) => {\n // Remove old table\n const [oldTable, path] = getFirstSelectedTable(model);\n if (oldTable) {\n const index = path[0].blocks.indexOf(oldTable);\n mutateBlock(path[0]).blocks.splice(index, 1);\n }\n\n if (ip && initValue?.cmTable) {\n // Insert new table\n const doc: ShallowMutableContentModelDocument = createContentModelDocument();\n doc.blocks.push(oldTable ?? mutateBlock(initValue.cmTable));\n insertionSuccess = !!mergeModel(model, cloneModel(doc), context, {\n mergeFormat: 'none',\n insertPosition: ip,\n });\n\n if (insertionSuccess) {\n // After mergeModel, the new table should be selected\n const finalTable = getFirstSelectedTable(model)[0] ?? initValue.cmTable;\n if (finalTable) {\n // Add selection marker to the first cell of the table\n const firstCell = finalTable.rows[0].cells[0];\n const markerParagraph = firstCell?.blocks[0];\n\n if (markerParagraph?.blockType == 'Paragraph') {\n const marker = createSelectionMarker(model.format);\n\n mutateBlock(markerParagraph).segments.unshift(marker);\n setParagraphNotImplicit(markerParagraph);\n setSelection(model, marker);\n }\n }\n }\n return insertionSuccess;\n }\n },\n {\n // Select first cell of the old table\n selectionOverride: {\n type: 'table',\n firstColumn: 0,\n firstRow: 0,\n lastColumn: 0,\n lastRow: 0,\n table: table,\n },\n apiName: 'TableMover',\n }\n );\n } else {\n // No movement, restore initial selection\n editor.setDOMSelection(initValue?.initialSelection ?? null);\n }\n context.onEnd(true /* disposeHandler */);\n return insertionSuccess;\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TouchPlugin = void 0;
4
- var getNodePositionFromEvent_1 = require("../utils/getNodePositionFromEvent");
4
+ var roosterjs_content_model_dom_1 = require("roosterjs-content-model-dom");
5
5
  var MAX_TOUCH_MOVE_DISTANCE = 6; // the max number of offsets for the touch selection to move
6
6
  var POINTER_DETECTION_DELAY = 150; // Delay time to wait for selection to be updated and also detect if pointerup is a tap or part of double tap
7
7
  var PUNCTUATION_MATCHING_REGEX = /[.,;:!]/;
@@ -69,7 +69,7 @@ var TouchPlugin = /** @class */ (function () {
69
69
  if (_this.editor) {
70
70
  if (!_this.isDblClicked) {
71
71
  _this.editor.focus();
72
- var caretPosition = (0, getNodePositionFromEvent_1.getNodePositionFromEvent)(_this.editor, event.rawEvent.x, event.rawEvent.y);
72
+ var caretPosition = (0, roosterjs_content_model_dom_1.getNodePositionFromEvent)(_this.editor.getDocument(), _this.editor.getDOMHelper(), event.rawEvent.x, event.rawEvent.y);
73
73
  var newRange = _this.editor.getDocument().createRange();
74
74
  if (caretPosition) {
75
75
  var node = caretPosition.node, offset = caretPosition.offset;
@@ -117,7 +117,7 @@ var TouchPlugin = /** @class */ (function () {
117
117
  if (this.isTouchPenPointerEvent) {
118
118
  event.rawEvent.preventDefault();
119
119
  this.isDblClicked = true;
120
- var caretPosition = (0, getNodePositionFromEvent_1.getNodePositionFromEvent)(this.editor, event.rawEvent.x, event.rawEvent.y);
120
+ var caretPosition = (0, roosterjs_content_model_dom_1.getNodePositionFromEvent)(this.editor.getDocument(), this.editor.getDOMHelper(), event.rawEvent.x, event.rawEvent.y);
121
121
  if (caretPosition) {
122
122
  var node = caretPosition.node, offset = caretPosition.offset;
123
123
  if (node.nodeType !== Node.TEXT_NODE) {