roosterjs-content-model-plugins 9.46.0 → 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 (37) hide show
  1. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.js +2 -0
  2. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  3. package/lib/paste/parsers/adjustWordListMarginParser.d.ts +9 -0
  4. package/lib/paste/parsers/adjustWordListMarginParser.js +26 -0
  5. package/lib/paste/parsers/adjustWordListMarginParser.js.map +1 -0
  6. package/lib/tableEdit/editors/features/TableMover.js +2 -3
  7. package/lib/tableEdit/editors/features/TableMover.js.map +1 -1
  8. package/lib/touch/TouchPlugin.js +3 -3
  9. package/lib/touch/TouchPlugin.js.map +1 -1
  10. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.js +2 -1
  11. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  12. package/lib-amd/paste/parsers/adjustWordListMarginParser.d.ts +9 -0
  13. package/lib-amd/paste/parsers/adjustWordListMarginParser.js +27 -0
  14. package/lib-amd/paste/parsers/adjustWordListMarginParser.js.map +1 -0
  15. package/lib-amd/tableEdit/editors/features/TableMover.js +3 -3
  16. package/lib-amd/tableEdit/editors/features/TableMover.js.map +1 -1
  17. package/lib-amd/touch/TouchPlugin.js +3 -3
  18. package/lib-amd/touch/TouchPlugin.js.map +1 -1
  19. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.js +2 -0
  20. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  21. package/lib-mjs/paste/parsers/adjustWordListMarginParser.d.ts +9 -0
  22. package/lib-mjs/paste/parsers/adjustWordListMarginParser.js +22 -0
  23. package/lib-mjs/paste/parsers/adjustWordListMarginParser.js.map +1 -0
  24. package/lib-mjs/tableEdit/editors/features/TableMover.js +3 -4
  25. package/lib-mjs/tableEdit/editors/features/TableMover.js.map +1 -1
  26. package/lib-mjs/touch/TouchPlugin.js +3 -3
  27. package/lib-mjs/touch/TouchPlugin.js.map +1 -1
  28. package/package.json +5 -5
  29. package/lib/utils/getNodePositionFromEvent.d.ts +0 -5
  30. package/lib/utils/getNodePositionFromEvent.js +0 -34
  31. package/lib/utils/getNodePositionFromEvent.js.map +0 -1
  32. package/lib-amd/utils/getNodePositionFromEvent.d.ts +0 -5
  33. package/lib-amd/utils/getNodePositionFromEvent.js +0 -36
  34. package/lib-amd/utils/getNodePositionFromEvent.js.map +0 -1
  35. package/lib-mjs/utils/getNodePositionFromEvent.d.ts +0 -5
  36. package/lib-mjs/utils/getNodePositionFromEvent.js +0 -30
  37. package/lib-mjs/utils/getNodePositionFromEvent.js.map +0 -1
@@ -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) {
@@ -1 +1 @@
1
- {"version":3,"file":"TouchPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/touch/TouchPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { getNodePositionFromEvent } from '../utils/getNodePositionFromEvent';\nimport type { EditorPlugin, IEditor, PluginEvent } from 'roosterjs-content-model-types';\n\nconst MAX_TOUCH_MOVE_DISTANCE = 6; // the max number of offsets for the touch selection to move\nconst 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\nconst PUNCTUATION_MATCHING_REGEX = /[.,;:!]/;\nconst SPACE_MATCHING_REGEX = /\\s/;\n\n/**\n * Touch plugin to manage touch behaviors\n */\nexport class TouchPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n private timer = 0;\n private isDblClicked: boolean = false;\n private isTouchPenPointerEvent: boolean = false;\n\n /**\n * Create an instance of Touch plugin\n */\n constructor() {}\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Touch';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.isDblClicked = false;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n if (this.timer) {\n this.editor?.getDocument()?.defaultView?.clearTimeout(this.timer);\n this.timer = 0;\n }\n this.editor = null;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (!this.editor) {\n return;\n }\n switch (event.eventType) {\n case 'pointerDown':\n this.isDblClicked = false;\n this.isTouchPenPointerEvent = true;\n event.originalEvent.preventDefault();\n\n const targetWindow = this.editor.getDocument().defaultView;\n\n if (targetWindow) {\n if (this.timer) {\n targetWindow.clearTimeout(this.timer);\n }\n\n this.timer = targetWindow.setTimeout(() => {\n this.timer = 0;\n\n if (this.editor) {\n if (!this.isDblClicked) {\n this.editor.focus();\n const caretPosition = getNodePositionFromEvent(\n this.editor,\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n const newRange = this.editor.getDocument().createRange();\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n // Place cursor at same position of browser handler by default\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset);\n\n const nodeTextContent = node.textContent || '';\n const charAtSelection = nodeTextContent[offset];\n if (\n node.nodeType === Node.TEXT_NODE &&\n charAtSelection &&\n !SPACE_MATCHING_REGEX.test(charAtSelection) &&\n !PUNCTUATION_MATCHING_REGEX.test(charAtSelection)\n ) {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n\n // Move cursor to the calculated offset\n const leftCursorWordLength = offset - wordStart;\n const rightCursorWordLength = wordEnd - offset;\n let movingOffset: number =\n leftCursorWordLength >= rightCursorWordLength\n ? rightCursorWordLength\n : -leftCursorWordLength;\n movingOffset =\n Math.abs(movingOffset) > MAX_TOUCH_MOVE_DISTANCE\n ? 0\n : movingOffset;\n const newOffsetPosition = offset + movingOffset;\n if (\n movingOffset !== 0 &&\n nodeTextContent.length >= newOffsetPosition\n ) {\n newRange.setStart(node, newOffsetPosition);\n newRange.setEnd(node, newOffsetPosition);\n }\n }\n }\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n\n // reset values\n this.isTouchPenPointerEvent = false;\n }\n }\n }, POINTER_DETECTION_DELAY);\n }\n break;\n case 'doubleClick':\n if (this.isTouchPenPointerEvent) {\n event.rawEvent.preventDefault();\n\n this.isDblClicked = true;\n const caretPosition = getNodePositionFromEvent(\n this.editor,\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n if (node.nodeType !== Node.TEXT_NODE) {\n return;\n }\n\n const nodeTextContent = node.nodeValue || '';\n const char = nodeTextContent.charAt(offset);\n\n // Check if the clicked character is a punctuation mark, then highlight that character only\n if (PUNCTUATION_MATCHING_REGEX.test(char)) {\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n } else if (SPACE_MATCHING_REGEX.test(char)) {\n // If the clicked character is an open space with no word of right side\n const rightSideOfChar = nodeTextContent.substring(\n offset,\n nodeTextContent.length\n );\n const isRightSideAllSpaces =\n rightSideOfChar.length > 0 && !/\\S/.test(rightSideOfChar);\n if (isRightSideAllSpaces) {\n // select the first space only\n let start = offset;\n while (\n start > 0 &&\n SPACE_MATCHING_REGEX.test(nodeTextContent.charAt(start - 1))\n ) {\n start--;\n }\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, start);\n newRange.setEnd(node, start + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n } else {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, wordStart);\n newRange.setEnd(node, wordEnd);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n }\n }\n break;\n }\n }\n}\n\n/**\n * @internal\n * Finds the start and end indices of the word at the given offset in the text.\n * @param text The string to search within.\n * @param offset The index within the string to find the word boundaries around.\n * @returns An object containing wordStart and wordEnd indices.\n */\nfunction findWordBoundaries(text: string, offset: number) {\n let start = offset;\n let end = offset;\n\n // Move start backwards to find word start\n while (\n start > 0 &&\n !SPACE_MATCHING_REGEX.test(text[start - 1]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[start - 1])\n ) {\n start--;\n }\n\n // Move end forward to find word end\n while (\n end < text.length &&\n !SPACE_MATCHING_REGEX.test(text[end]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[end])\n ) {\n end++;\n }\n\n return {\n wordStart: start,\n wordEnd: end,\n };\n}\n"]}
1
+ {"version":3,"file":"TouchPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/touch/TouchPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { getNodePositionFromEvent } from 'roosterjs-content-model-dom';\nimport type { EditorPlugin, IEditor, PluginEvent } from 'roosterjs-content-model-types';\n\nconst MAX_TOUCH_MOVE_DISTANCE = 6; // the max number of offsets for the touch selection to move\nconst 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\nconst PUNCTUATION_MATCHING_REGEX = /[.,;:!]/;\nconst SPACE_MATCHING_REGEX = /\\s/;\n\n/**\n * Touch plugin to manage touch behaviors\n */\nexport class TouchPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n private timer = 0;\n private isDblClicked: boolean = false;\n private isTouchPenPointerEvent: boolean = false;\n\n /**\n * Create an instance of Touch plugin\n */\n constructor() {}\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Touch';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.isDblClicked = false;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n if (this.timer) {\n this.editor?.getDocument()?.defaultView?.clearTimeout(this.timer);\n this.timer = 0;\n }\n this.editor = null;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (!this.editor) {\n return;\n }\n switch (event.eventType) {\n case 'pointerDown':\n this.isDblClicked = false;\n this.isTouchPenPointerEvent = true;\n event.originalEvent.preventDefault();\n\n const targetWindow = this.editor.getDocument().defaultView;\n\n if (targetWindow) {\n if (this.timer) {\n targetWindow.clearTimeout(this.timer);\n }\n\n this.timer = targetWindow.setTimeout(() => {\n this.timer = 0;\n\n if (this.editor) {\n if (!this.isDblClicked) {\n this.editor.focus();\n const caretPosition = getNodePositionFromEvent(\n this.editor.getDocument(),\n this.editor.getDOMHelper(),\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n const newRange = this.editor.getDocument().createRange();\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n // Place cursor at same position of browser handler by default\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset);\n\n const nodeTextContent = node.textContent || '';\n const charAtSelection = nodeTextContent[offset];\n if (\n node.nodeType === Node.TEXT_NODE &&\n charAtSelection &&\n !SPACE_MATCHING_REGEX.test(charAtSelection) &&\n !PUNCTUATION_MATCHING_REGEX.test(charAtSelection)\n ) {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n\n // Move cursor to the calculated offset\n const leftCursorWordLength = offset - wordStart;\n const rightCursorWordLength = wordEnd - offset;\n let movingOffset: number =\n leftCursorWordLength >= rightCursorWordLength\n ? rightCursorWordLength\n : -leftCursorWordLength;\n movingOffset =\n Math.abs(movingOffset) > MAX_TOUCH_MOVE_DISTANCE\n ? 0\n : movingOffset;\n const newOffsetPosition = offset + movingOffset;\n if (\n movingOffset !== 0 &&\n nodeTextContent.length >= newOffsetPosition\n ) {\n newRange.setStart(node, newOffsetPosition);\n newRange.setEnd(node, newOffsetPosition);\n }\n }\n }\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n\n // reset values\n this.isTouchPenPointerEvent = false;\n }\n }\n }, POINTER_DETECTION_DELAY);\n }\n break;\n case 'doubleClick':\n if (this.isTouchPenPointerEvent) {\n event.rawEvent.preventDefault();\n\n this.isDblClicked = true;\n const caretPosition = getNodePositionFromEvent(\n this.editor.getDocument(),\n this.editor.getDOMHelper(),\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n if (node.nodeType !== Node.TEXT_NODE) {\n return;\n }\n\n const nodeTextContent = node.nodeValue || '';\n const char = nodeTextContent.charAt(offset);\n\n // Check if the clicked character is a punctuation mark, then highlight that character only\n if (PUNCTUATION_MATCHING_REGEX.test(char)) {\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n } else if (SPACE_MATCHING_REGEX.test(char)) {\n // If the clicked character is an open space with no word of right side\n const rightSideOfChar = nodeTextContent.substring(\n offset,\n nodeTextContent.length\n );\n const isRightSideAllSpaces =\n rightSideOfChar.length > 0 && !/\\S/.test(rightSideOfChar);\n if (isRightSideAllSpaces) {\n // select the first space only\n let start = offset;\n while (\n start > 0 &&\n SPACE_MATCHING_REGEX.test(nodeTextContent.charAt(start - 1))\n ) {\n start--;\n }\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, start);\n newRange.setEnd(node, start + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n } else {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, wordStart);\n newRange.setEnd(node, wordEnd);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n }\n }\n break;\n }\n }\n}\n\n/**\n * @internal\n * Finds the start and end indices of the word at the given offset in the text.\n * @param text The string to search within.\n * @param offset The index within the string to find the word boundaries around.\n * @returns An object containing wordStart and wordEnd indices.\n */\nfunction findWordBoundaries(text: string, offset: number) {\n let start = offset;\n let end = offset;\n\n // Move start backwards to find word start\n while (\n start > 0 &&\n !SPACE_MATCHING_REGEX.test(text[start - 1]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[start - 1])\n ) {\n start--;\n }\n\n // Move end forward to find word end\n while (\n end < text.length &&\n !SPACE_MATCHING_REGEX.test(text[end]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[end])\n ) {\n end++;\n }\n\n return {\n wordStart: start,\n wordEnd: end,\n };\n}\n"]}
@@ -1,4 +1,4 @@
1
- define(["require", "exports", "../utils/addParser", "../parsers/adjustPercentileLineHeightParser", "./getStyleMetadata", "../utils/getStyles", "../parsers/listLevelParser", "./processWordComments", "./processWordLists", "../parsers/removeNegativeTextIndentParser", "../utils/setProcessor", "../parsers/wordContainerParser", "../parsers/wordTableParser"], function (require, exports, addParser_1, adjustPercentileLineHeightParser_1, getStyleMetadata_1, getStyles_1, listLevelParser_1, processWordComments_1, processWordLists_1, removeNegativeTextIndentParser_1, setProcessor_1, wordContainerParser_1, wordTableParser_1) {
1
+ define(["require", "exports", "../utils/addParser", "../parsers/adjustPercentileLineHeightParser", "./getStyleMetadata", "../utils/getStyles", "../parsers/listLevelParser", "./processWordComments", "./processWordLists", "../parsers/adjustWordListMarginParser", "../parsers/removeNegativeTextIndentParser", "../utils/setProcessor", "../parsers/wordContainerParser", "../parsers/wordTableParser"], function (require, exports, addParser_1, adjustPercentileLineHeightParser_1, getStyleMetadata_1, getStyles_1, listLevelParser_1, processWordComments_1, processWordLists_1, adjustWordListMarginParser_1, removeNegativeTextIndentParser_1, setProcessor_1, wordContainerParser_1, wordTableParser_1) {
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.processPastedContentFromWordDesktop = void 0;
@@ -14,6 +14,7 @@ define(["require", "exports", "../utils/addParser", "../parsers/adjustPercentile
14
14
  (0, addParser_1.addParser)(domToModelOption, 'block', adjustPercentileLineHeightParser_1.adjustPercentileLineHeight);
15
15
  (0, addParser_1.addParser)(domToModelOption, 'block', removeNegativeTextIndentParser_1.removeNegativeTextIndentParser);
16
16
  (0, addParser_1.addParser)(domToModelOption, 'listItemElement', removeNegativeTextIndentParser_1.removeNegativeTextIndentParser);
17
+ (0, addParser_1.addParser)(domToModelOption, 'listItemElement', adjustWordListMarginParser_1.adjustWordListMarginParser);
17
18
  (0, addParser_1.addParser)(domToModelOption, 'listLevel', listLevelParser_1.listLevelParser);
18
19
  (0, addParser_1.addParser)(domToModelOption, 'container', wordContainerParser_1.wordContainerParser);
19
20
  (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":";;;;IAcA;;;;;OAKG;IACH,SAAgB,mCAAmC,CAC/C,gBAAkC,EAClC,UAAkB;QAElB,IAAM,WAAW,GAA8B,IAAA,mCAAgB,EAAC,UAAU,CAAC,CAAC;QAE5E,IAAA,2BAAY,EAAC,gBAAgB,EAAE,SAAS,EAAE,2BAA2B,CAAC,WAAW,CAAC,CAAC,CAAC;QACpF,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,6DAA0B,CAAC,CAAC;QACjE,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,+DAA8B,CAAC,CAAC;QACrE,IAAA,qBAAS,EAAC,gBAAgB,EAAE,iBAAiB,EAAE,+DAA8B,CAAC,CAAC;QAC/E,IAAA,qBAAS,EAAC,gBAAgB,EAAE,WAAW,EAAE,iCAAe,CAAC,CAAC;QAC1D,IAAA,qBAAS,EAAC,gBAAgB,EAAE,WAAW,EAAE,yCAAmB,CAAC,CAAC;QAC9D,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,iCAAe,CAAC,CAAC;IAC1D,CAAC;IAbD,kFAaC;IAED,IAAM,2BAA2B,GAAG,UAChC,WAAsC;QAEtC,OAAO,UAAC,KAAK,EAAE,OAAO,EAAE,OAAO;YAC3B,IAAM,MAAM,GAAG,IAAA,qBAAS,EAAC,OAAO,CAAC,CAAC;YAClC,4FAA4F;YAC5F,IACI,CAAC,CACG,IAAA,kCAAe,EAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC;gBAC7D,IAAA,yCAAmB,EAAC,MAAM,EAAE,OAAO,CAAC,CACvC,EACH;gBACE,OAAO,CAAC,wBAAwB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;aACrE;QACL,CAAC,CAAC;IACN,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":";;;;IAeA;;;;;OAKG;IACH,SAAgB,mCAAmC,CAC/C,gBAAkC,EAClC,UAAkB;QAElB,IAAM,WAAW,GAA8B,IAAA,mCAAgB,EAAC,UAAU,CAAC,CAAC;QAE5E,IAAA,2BAAY,EAAC,gBAAgB,EAAE,SAAS,EAAE,2BAA2B,CAAC,WAAW,CAAC,CAAC,CAAC;QACpF,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,6DAA0B,CAAC,CAAC;QACjE,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,+DAA8B,CAAC,CAAC;QACrE,IAAA,qBAAS,EAAC,gBAAgB,EAAE,iBAAiB,EAAE,+DAA8B,CAAC,CAAC;QAC/E,IAAA,qBAAS,EAAC,gBAAgB,EAAE,iBAAiB,EAAE,uDAA0B,CAAC,CAAC;QAC3E,IAAA,qBAAS,EAAC,gBAAgB,EAAE,WAAW,EAAE,iCAAe,CAAC,CAAC;QAC1D,IAAA,qBAAS,EAAC,gBAAgB,EAAE,WAAW,EAAE,yCAAmB,CAAC,CAAC;QAC9D,IAAA,qBAAS,EAAC,gBAAgB,EAAE,OAAO,EAAE,iCAAe,CAAC,CAAC;IAC1D,CAAC;IAdD,kFAcC;IAED,IAAM,2BAA2B,GAAG,UAChC,WAAsC;QAEtC,OAAO,UAAC,KAAK,EAAE,OAAO,EAAE,OAAO;YAC3B,IAAM,MAAM,GAAG,IAAA,qBAAS,EAAC,OAAO,CAAC,CAAC;YAClC,4FAA4F;YAC5F,IACI,CAAC,CACG,IAAA,kCAAe,EAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC;gBAC7D,IAAA,yCAAmB,EAAC,MAAM,EAAE,OAAO,CAAC,CACvC,EACH;gBACE,OAAO,CAAC,wBAAwB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;aACrE;QACL,CAAC,CAAC;IACN,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,27 @@
1
+ define(["require", "exports", "roosterjs-content-model-dom"], function (require, exports, roosterjs_content_model_dom_1) {
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.adjustWordListMarginParser = void 0;
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
+ });
27
+ //# 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":";;;;IAGA,IAAM,wBAAwB,GAAG,kBAAkB,CAAC;IAEpD,8FAA8F;IAC9F,IAAM,iCAAiC,GAAG,MAAM,CAAC;IAEjD;;;;;;OAMG;IACI,IAAM,0BAA0B,GAA+B,UAClE,MAAoB,EACpB,OAAoB;QAEpB,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,wBAAwB,CAAC,IAAI,MAAM,CAAC,UAAU,EAAE;YAC3E,IAAM,SAAS,GAAG,IAAA,gDAAkB,EAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACjE,IAAM,SAAS,GAAG,IAAA,gDAAkB,EAAC,iCAAiC,CAAC,CAAC;YACxE,IAAM,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;YAErC,IAAI,MAAM,GAAG,CAAC,EAAE;gBACZ,MAAM,CAAC,UAAU,GAAM,MAAM,OAAI,CAAC;aACrC;SACJ;IACL,CAAC,CAAC;IAbW,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"]}
@@ -1,4 +1,4 @@
1
- define(["require", "exports", "tslib", "../../../pluginUtils/CreateElement/createElement", "../../../pluginUtils/DragAndDrop/DragAndDropHelper", "roosterjs-content-model-api", "../utils/getTableFromContentModel", "../../../utils/getNodePositionFromEvent", "roosterjs-content-model-dom"], function (require, exports, tslib_1, createElement_1, DragAndDropHelper_1, roosterjs_content_model_api_1, getTableFromContentModel_1, getNodePositionFromEvent_1, roosterjs_content_model_dom_1) {
1
+ define(["require", "exports", "tslib", "../../../pluginUtils/CreateElement/createElement", "../../../pluginUtils/DragAndDrop/DragAndDropHelper", "roosterjs-content-model-api", "../utils/getTableFromContentModel", "roosterjs-content-model-dom"], function (require, exports, tslib_1, createElement_1, DragAndDropHelper_1, roosterjs_content_model_api_1, getTableFromContentModel_1, roosterjs_content_model_dom_1) {
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.onDragEnd = exports.onDragging = exports.onDragStart = exports.createTableMover = exports.TABLE_MOVER_ID = void 0;
@@ -128,7 +128,7 @@ define(["require", "exports", "tslib", "../../../pluginUtils/CreateElement/creat
128
128
  // Move table outline rectangle
129
129
  tableRect.style.top = event.clientY + TABLE_MOVER_LENGTH + "px";
130
130
  tableRect.style.left = event.clientX + TABLE_MOVER_LENGTH + "px";
131
- var pos = (0, getNodePositionFromEvent_1.getNodePositionFromEvent)(editor, event.clientX, event.clientY);
131
+ var pos = (0, roosterjs_content_model_dom_1.getNodePositionFromEvent)(editor.getDocument(), editor.getDOMHelper(), event.clientX, event.clientY);
132
132
  if (pos) {
133
133
  var range = editor.getDocument().createRange();
134
134
  range.setStart(pos.node, pos.offset);
@@ -168,7 +168,7 @@ define(["require", "exports", "tslib", "../../../pluginUtils/CreateElement/creat
168
168
  }
169
169
  var insertionSuccess_1 = false;
170
170
  // Get position to insert table
171
- var insertPosition = (0, getNodePositionFromEvent_1.getNodePositionFromEvent)(editor, event.clientX, event.clientY);
171
+ var insertPosition = (0, roosterjs_content_model_dom_1.getNodePositionFromEvent)(editor.getDocument(), editor.getDOMHelper(), event.clientX, event.clientY);
172
172
  if (insertPosition) {
173
173
  // Move table to new position
174
174
  (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,4 +1,4 @@
1
- define(["require", "exports", "../utils/getNodePositionFromEvent"], function (require, exports, getNodePositionFromEvent_1) {
1
+ define(["require", "exports", "roosterjs-content-model-dom"], function (require, exports, roosterjs_content_model_dom_1) {
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.TouchPlugin = void 0;
@@ -69,7 +69,7 @@ define(["require", "exports", "../utils/getNodePositionFromEvent"], function (re
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 @@ define(["require", "exports", "../utils/getNodePositionFromEvent"], function (re
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) {
@@ -1 +1 @@
1
- {"version":3,"file":"TouchPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/touch/TouchPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { getNodePositionFromEvent } from '../utils/getNodePositionFromEvent';\nimport type { EditorPlugin, IEditor, PluginEvent } from 'roosterjs-content-model-types';\n\nconst MAX_TOUCH_MOVE_DISTANCE = 6; // the max number of offsets for the touch selection to move\nconst 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\nconst PUNCTUATION_MATCHING_REGEX = /[.,;:!]/;\nconst SPACE_MATCHING_REGEX = /\\s/;\n\n/**\n * Touch plugin to manage touch behaviors\n */\nexport class TouchPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n private timer = 0;\n private isDblClicked: boolean = false;\n private isTouchPenPointerEvent: boolean = false;\n\n /**\n * Create an instance of Touch plugin\n */\n constructor() {}\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Touch';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.isDblClicked = false;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n if (this.timer) {\n this.editor?.getDocument()?.defaultView?.clearTimeout(this.timer);\n this.timer = 0;\n }\n this.editor = null;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (!this.editor) {\n return;\n }\n switch (event.eventType) {\n case 'pointerDown':\n this.isDblClicked = false;\n this.isTouchPenPointerEvent = true;\n event.originalEvent.preventDefault();\n\n const targetWindow = this.editor.getDocument().defaultView;\n\n if (targetWindow) {\n if (this.timer) {\n targetWindow.clearTimeout(this.timer);\n }\n\n this.timer = targetWindow.setTimeout(() => {\n this.timer = 0;\n\n if (this.editor) {\n if (!this.isDblClicked) {\n this.editor.focus();\n const caretPosition = getNodePositionFromEvent(\n this.editor,\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n const newRange = this.editor.getDocument().createRange();\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n // Place cursor at same position of browser handler by default\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset);\n\n const nodeTextContent = node.textContent || '';\n const charAtSelection = nodeTextContent[offset];\n if (\n node.nodeType === Node.TEXT_NODE &&\n charAtSelection &&\n !SPACE_MATCHING_REGEX.test(charAtSelection) &&\n !PUNCTUATION_MATCHING_REGEX.test(charAtSelection)\n ) {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n\n // Move cursor to the calculated offset\n const leftCursorWordLength = offset - wordStart;\n const rightCursorWordLength = wordEnd - offset;\n let movingOffset: number =\n leftCursorWordLength >= rightCursorWordLength\n ? rightCursorWordLength\n : -leftCursorWordLength;\n movingOffset =\n Math.abs(movingOffset) > MAX_TOUCH_MOVE_DISTANCE\n ? 0\n : movingOffset;\n const newOffsetPosition = offset + movingOffset;\n if (\n movingOffset !== 0 &&\n nodeTextContent.length >= newOffsetPosition\n ) {\n newRange.setStart(node, newOffsetPosition);\n newRange.setEnd(node, newOffsetPosition);\n }\n }\n }\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n\n // reset values\n this.isTouchPenPointerEvent = false;\n }\n }\n }, POINTER_DETECTION_DELAY);\n }\n break;\n case 'doubleClick':\n if (this.isTouchPenPointerEvent) {\n event.rawEvent.preventDefault();\n\n this.isDblClicked = true;\n const caretPosition = getNodePositionFromEvent(\n this.editor,\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n if (node.nodeType !== Node.TEXT_NODE) {\n return;\n }\n\n const nodeTextContent = node.nodeValue || '';\n const char = nodeTextContent.charAt(offset);\n\n // Check if the clicked character is a punctuation mark, then highlight that character only\n if (PUNCTUATION_MATCHING_REGEX.test(char)) {\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n } else if (SPACE_MATCHING_REGEX.test(char)) {\n // If the clicked character is an open space with no word of right side\n const rightSideOfChar = nodeTextContent.substring(\n offset,\n nodeTextContent.length\n );\n const isRightSideAllSpaces =\n rightSideOfChar.length > 0 && !/\\S/.test(rightSideOfChar);\n if (isRightSideAllSpaces) {\n // select the first space only\n let start = offset;\n while (\n start > 0 &&\n SPACE_MATCHING_REGEX.test(nodeTextContent.charAt(start - 1))\n ) {\n start--;\n }\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, start);\n newRange.setEnd(node, start + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n } else {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, wordStart);\n newRange.setEnd(node, wordEnd);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n }\n }\n break;\n }\n }\n}\n\n/**\n * @internal\n * Finds the start and end indices of the word at the given offset in the text.\n * @param text The string to search within.\n * @param offset The index within the string to find the word boundaries around.\n * @returns An object containing wordStart and wordEnd indices.\n */\nfunction findWordBoundaries(text: string, offset: number) {\n let start = offset;\n let end = offset;\n\n // Move start backwards to find word start\n while (\n start > 0 &&\n !SPACE_MATCHING_REGEX.test(text[start - 1]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[start - 1])\n ) {\n start--;\n }\n\n // Move end forward to find word end\n while (\n end < text.length &&\n !SPACE_MATCHING_REGEX.test(text[end]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[end])\n ) {\n end++;\n }\n\n return {\n wordStart: start,\n wordEnd: end,\n };\n}\n"]}
1
+ {"version":3,"file":"TouchPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/touch/TouchPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { getNodePositionFromEvent } from 'roosterjs-content-model-dom';\nimport type { EditorPlugin, IEditor, PluginEvent } from 'roosterjs-content-model-types';\n\nconst MAX_TOUCH_MOVE_DISTANCE = 6; // the max number of offsets for the touch selection to move\nconst 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\nconst PUNCTUATION_MATCHING_REGEX = /[.,;:!]/;\nconst SPACE_MATCHING_REGEX = /\\s/;\n\n/**\n * Touch plugin to manage touch behaviors\n */\nexport class TouchPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n private timer = 0;\n private isDblClicked: boolean = false;\n private isTouchPenPointerEvent: boolean = false;\n\n /**\n * Create an instance of Touch plugin\n */\n constructor() {}\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Touch';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.isDblClicked = false;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n if (this.timer) {\n this.editor?.getDocument()?.defaultView?.clearTimeout(this.timer);\n this.timer = 0;\n }\n this.editor = null;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (!this.editor) {\n return;\n }\n switch (event.eventType) {\n case 'pointerDown':\n this.isDblClicked = false;\n this.isTouchPenPointerEvent = true;\n event.originalEvent.preventDefault();\n\n const targetWindow = this.editor.getDocument().defaultView;\n\n if (targetWindow) {\n if (this.timer) {\n targetWindow.clearTimeout(this.timer);\n }\n\n this.timer = targetWindow.setTimeout(() => {\n this.timer = 0;\n\n if (this.editor) {\n if (!this.isDblClicked) {\n this.editor.focus();\n const caretPosition = getNodePositionFromEvent(\n this.editor.getDocument(),\n this.editor.getDOMHelper(),\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n const newRange = this.editor.getDocument().createRange();\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n // Place cursor at same position of browser handler by default\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset);\n\n const nodeTextContent = node.textContent || '';\n const charAtSelection = nodeTextContent[offset];\n if (\n node.nodeType === Node.TEXT_NODE &&\n charAtSelection &&\n !SPACE_MATCHING_REGEX.test(charAtSelection) &&\n !PUNCTUATION_MATCHING_REGEX.test(charAtSelection)\n ) {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n\n // Move cursor to the calculated offset\n const leftCursorWordLength = offset - wordStart;\n const rightCursorWordLength = wordEnd - offset;\n let movingOffset: number =\n leftCursorWordLength >= rightCursorWordLength\n ? rightCursorWordLength\n : -leftCursorWordLength;\n movingOffset =\n Math.abs(movingOffset) > MAX_TOUCH_MOVE_DISTANCE\n ? 0\n : movingOffset;\n const newOffsetPosition = offset + movingOffset;\n if (\n movingOffset !== 0 &&\n nodeTextContent.length >= newOffsetPosition\n ) {\n newRange.setStart(node, newOffsetPosition);\n newRange.setEnd(node, newOffsetPosition);\n }\n }\n }\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n\n // reset values\n this.isTouchPenPointerEvent = false;\n }\n }\n }, POINTER_DETECTION_DELAY);\n }\n break;\n case 'doubleClick':\n if (this.isTouchPenPointerEvent) {\n event.rawEvent.preventDefault();\n\n this.isDblClicked = true;\n const caretPosition = getNodePositionFromEvent(\n this.editor.getDocument(),\n this.editor.getDOMHelper(),\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n if (node.nodeType !== Node.TEXT_NODE) {\n return;\n }\n\n const nodeTextContent = node.nodeValue || '';\n const char = nodeTextContent.charAt(offset);\n\n // Check if the clicked character is a punctuation mark, then highlight that character only\n if (PUNCTUATION_MATCHING_REGEX.test(char)) {\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n } else if (SPACE_MATCHING_REGEX.test(char)) {\n // If the clicked character is an open space with no word of right side\n const rightSideOfChar = nodeTextContent.substring(\n offset,\n nodeTextContent.length\n );\n const isRightSideAllSpaces =\n rightSideOfChar.length > 0 && !/\\S/.test(rightSideOfChar);\n if (isRightSideAllSpaces) {\n // select the first space only\n let start = offset;\n while (\n start > 0 &&\n SPACE_MATCHING_REGEX.test(nodeTextContent.charAt(start - 1))\n ) {\n start--;\n }\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, start);\n newRange.setEnd(node, start + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n } else {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, wordStart);\n newRange.setEnd(node, wordEnd);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n }\n }\n break;\n }\n }\n}\n\n/**\n * @internal\n * Finds the start and end indices of the word at the given offset in the text.\n * @param text The string to search within.\n * @param offset The index within the string to find the word boundaries around.\n * @returns An object containing wordStart and wordEnd indices.\n */\nfunction findWordBoundaries(text: string, offset: number) {\n let start = offset;\n let end = offset;\n\n // Move start backwards to find word start\n while (\n start > 0 &&\n !SPACE_MATCHING_REGEX.test(text[start - 1]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[start - 1])\n ) {\n start--;\n }\n\n // Move end forward to find word end\n while (\n end < text.length &&\n !SPACE_MATCHING_REGEX.test(text[end]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[end])\n ) {\n end++;\n }\n\n return {\n wordStart: start,\n wordEnd: end,\n };\n}\n"]}
@@ -5,6 +5,7 @@ import { getStyles } from '../utils/getStyles';
5
5
  import { listLevelParser } from '../parsers/listLevelParser';
6
6
  import { processWordComments } from './processWordComments';
7
7
  import { processWordList } from './processWordLists';
8
+ import { adjustWordListMarginParser } from '../parsers/adjustWordListMarginParser';
8
9
  import { removeNegativeTextIndentParser } from '../parsers/removeNegativeTextIndentParser';
9
10
  import { setProcessor } from '../utils/setProcessor';
10
11
  import { wordContainerParser } from '../parsers/wordContainerParser';
@@ -21,6 +22,7 @@ export function processPastedContentFromWordDesktop(domToModelOption, htmlString
21
22
  addParser(domToModelOption, 'block', adjustPercentileLineHeight);
22
23
  addParser(domToModelOption, 'block', removeNegativeTextIndentParser);
23
24
  addParser(domToModelOption, 'listItemElement', removeNegativeTextIndentParser);
25
+ addParser(domToModelOption, 'listItemElement', adjustWordListMarginParser);
24
26
  addParser(domToModelOption, 'listLevel', listLevelParser);
25
27
  addParser(domToModelOption, 'container', wordContainerParser);
26
28
  addParser(domToModelOption, 'table', wordTableParser);
@@ -1 +1 @@
1
- {"version":3,"file":"processPastedContentFromWordDesktop.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/WordDesktop/processPastedContentFromWordDesktop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,6CAA6C,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,8BAA8B,EAAE,MAAM,2CAA2C,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAI7D;;;;;GAKG;AACH,MAAM,UAAU,mCAAmC,CAC/C,gBAAkC,EAClC,UAAkB;IAElB,IAAM,WAAW,GAA8B,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAE5E,YAAY,CAAC,gBAAgB,EAAE,SAAS,EAAE,2BAA2B,CAAC,WAAW,CAAC,CAAC,CAAC;IACpF,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,0BAA0B,CAAC,CAAC;IACjE,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,8BAA8B,CAAC,CAAC;IACrE,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,8BAA8B,CAAC,CAAC;IAC/E,SAAS,CAAC,gBAAgB,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;IAC1D,SAAS,CAAC,gBAAgB,EAAE,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAC9D,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;AAC1D,CAAC;AAED,IAAM,2BAA2B,GAAG,UAChC,WAAsC;IAEtC,OAAO,UAAC,KAAK,EAAE,OAAO,EAAE,OAAO;QAC3B,IAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,4FAA4F;QAC5F,IACI,CAAC,CACG,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC;YAC7D,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CACvC,EACH;YACE,OAAO,CAAC,wBAAwB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SACrE;IACL,CAAC,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { adjustPercentileLineHeight } from '../parsers/adjustPercentileLineHeightParser';\nimport { getStyleMetadata } from './getStyleMetadata';\nimport { getStyles } from '../utils/getStyles';\nimport { listLevelParser } from '../parsers/listLevelParser';\nimport { processWordComments } from './processWordComments';\nimport { processWordList } from './processWordLists';\nimport { 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,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,6CAA6C,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,8BAA8B,EAAE,MAAM,2CAA2C,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAI7D;;;;;GAKG;AACH,MAAM,UAAU,mCAAmC,CAC/C,gBAAkC,EAClC,UAAkB;IAElB,IAAM,WAAW,GAA8B,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAE5E,YAAY,CAAC,gBAAgB,EAAE,SAAS,EAAE,2BAA2B,CAAC,WAAW,CAAC,CAAC,CAAC;IACpF,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,0BAA0B,CAAC,CAAC;IACjE,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,8BAA8B,CAAC,CAAC;IACrE,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,8BAA8B,CAAC,CAAC;IAC/E,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,0BAA0B,CAAC,CAAC;IAC3E,SAAS,CAAC,gBAAgB,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;IAC1D,SAAS,CAAC,gBAAgB,EAAE,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAC9D,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;AAC1D,CAAC;AAED,IAAM,2BAA2B,GAAG,UAChC,WAAsC;IAEtC,OAAO,UAAC,KAAK,EAAE,OAAO,EAAE,OAAO;QAC3B,IAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,4FAA4F;QAC5F,IACI,CAAC,CACG,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC;YAC7D,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CACvC,EACH;YACE,OAAO,CAAC,wBAAwB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SACrE;IACL,CAAC,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { adjustPercentileLineHeight } from '../parsers/adjustPercentileLineHeightParser';\nimport { getStyleMetadata } from './getStyleMetadata';\nimport { getStyles } from '../utils/getStyles';\nimport { listLevelParser } from '../parsers/listLevelParser';\nimport { processWordComments } from './processWordComments';\nimport { processWordList } from './processWordLists';\nimport { adjustWordListMarginParser } from '../parsers/adjustWordListMarginParser';\nimport { removeNegativeTextIndentParser } from '../parsers/removeNegativeTextIndentParser';\nimport { setProcessor } from '../utils/setProcessor';\nimport { wordContainerParser } from '../parsers/wordContainerParser';\nimport { wordTableParser } from '../parsers/wordTableParser';\nimport type { WordMetadata } from './WordMetadata';\nimport type { DomToModelOption, ElementProcessor } from 'roosterjs-content-model-types';\n\n/**\n * @internal\n * Handles pasted content when the source is Word Desktop.\n * @param domToModelOption Options for DOM to Content Model conversion\n * @param htmlString The HTML string to process\n */\nexport function processPastedContentFromWordDesktop(\n domToModelOption: DomToModelOption,\n htmlString: string\n) {\n const metadataMap: Map<string, WordMetadata> = getStyleMetadata(htmlString);\n\n setProcessor(domToModelOption, 'element', wordDesktopElementProcessor(metadataMap));\n addParser(domToModelOption, 'block', adjustPercentileLineHeight);\n addParser(domToModelOption, 'block', removeNegativeTextIndentParser);\n addParser(domToModelOption, 'listItemElement', removeNegativeTextIndentParser);\n addParser(domToModelOption, 'listItemElement', adjustWordListMarginParser);\n addParser(domToModelOption, 'listLevel', listLevelParser);\n addParser(domToModelOption, 'container', wordContainerParser);\n addParser(domToModelOption, 'table', wordTableParser);\n}\n\nconst wordDesktopElementProcessor = (\n metadataKey: Map<string, WordMetadata>\n): ElementProcessor<HTMLElement> => {\n return (group, element, context) => {\n const styles = getStyles(element);\n // Process Word Lists or Word Commands, otherwise use the default processor on this element.\n if (\n !(\n processWordList(styles, group, element, context, metadataKey) ||\n processWordComments(styles, element)\n )\n ) {\n context.defaultElementProcessors.element(group, element, context);\n }\n };\n};\n"]}
@@ -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,22 @@
1
+ import { parseValueWithUnit } from 'roosterjs-content-model-dom';
2
+ var MSO_LIST_PARAGRAPH_CLASS = 'MsoListParagraph';
3
+ // Default list padding from the HTML user-agent stylesheet (paddingInlineStart for <ul>/<ol>)
4
+ var DEFAULT_LIST_PADDING_INLINE_START = '40px';
5
+ /**
6
+ * @internal
7
+ * Parser that subtracts the default list format (paddingInlineStart: 40px) from
8
+ * the marginLeft of list item elements that have the MsoListParagraph class,
9
+ * since Word adds the full indentation as margin on the paragraph, which
10
+ * duplicates the padding the list element already provides.
11
+ */
12
+ export var adjustWordListMarginParser = function (format, element) {
13
+ if (element.classList.contains(MSO_LIST_PARAGRAPH_CLASS) && format.marginLeft) {
14
+ var currentPx = parseValueWithUnit(format.marginLeft, element);
15
+ var defaultPx = parseValueWithUnit(DEFAULT_LIST_PADDING_INLINE_START);
16
+ var result = currentPx - defaultPx;
17
+ if (result > 0) {
18
+ format.marginLeft = result + "px";
19
+ }
20
+ }
21
+ };
22
+ //# 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,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAGjE,IAAM,wBAAwB,GAAG,kBAAkB,CAAC;AAEpD,8FAA8F;AAC9F,IAAM,iCAAiC,GAAG,MAAM,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,CAAC,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,kBAAkB,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjE,IAAM,SAAS,GAAG,kBAAkB,CAAC,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","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"]}
@@ -3,8 +3,7 @@ import { createElement } from '../../../pluginUtils/CreateElement/createElement'
3
3
  import { DragAndDropHelper } from '../../../pluginUtils/DragAndDrop/DragAndDropHelper';
4
4
  import { formatInsertPointWithContentModel } from 'roosterjs-content-model-api';
5
5
  import { getCMTableFromTable } from '../utils/getTableFromContentModel';
6
- import { getNodePositionFromEvent } from '../../../utils/getNodePositionFromEvent';
7
- import { cloneModel, createContentModelDocument, createSelectionMarker, getFirstSelectedTable, isNodeOfType, mergeModel, mutateBlock, normalizeRect, setParagraphNotImplicit, setSelection, } from 'roosterjs-content-model-dom';
6
+ import { cloneModel, createContentModelDocument, createSelectionMarker, getFirstSelectedTable, getNodePositionFromEvent, isNodeOfType, mergeModel, mutateBlock, normalizeRect, setParagraphNotImplicit, setSelection, } from 'roosterjs-content-model-dom';
8
7
  var TABLE_MOVER_LENGTH = 12;
9
8
  /**
10
9
  * @internal
@@ -129,7 +128,7 @@ export function onDragging(context, event, initValue) {
129
128
  // Move table outline rectangle
130
129
  tableRect.style.top = event.clientY + TABLE_MOVER_LENGTH + "px";
131
130
  tableRect.style.left = event.clientX + TABLE_MOVER_LENGTH + "px";
132
- var pos = getNodePositionFromEvent(editor, event.clientX, event.clientY);
131
+ var pos = getNodePositionFromEvent(editor.getDocument(), editor.getDOMHelper(), event.clientX, event.clientY);
133
132
  if (pos) {
134
133
  var range = editor.getDocument().createRange();
135
134
  range.setStart(pos.node, pos.offset);
@@ -168,7 +167,7 @@ export function onDragEnd(context, event, initValue) {
168
167
  }
169
168
  var insertionSuccess_1 = false;
170
169
  // Get position to insert table
171
- var insertPosition = getNodePositionFromEvent(editor, event.clientX, event.clientY);
170
+ var insertPosition = getNodePositionFromEvent(editor.getDocument(), editor.getDOMHelper(), event.clientX, event.clientY);
172
171
  if (insertPosition) {
173
172
  // Move table to new position
174
173
  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,4 +1,4 @@
1
- import { getNodePositionFromEvent } from '../utils/getNodePositionFromEvent';
1
+ import { getNodePositionFromEvent } from 'roosterjs-content-model-dom';
2
2
  var MAX_TOUCH_MOVE_DISTANCE = 6; // the max number of offsets for the touch selection to move
3
3
  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
4
4
  var PUNCTUATION_MATCHING_REGEX = /[.,;:!]/;
@@ -66,7 +66,7 @@ var TouchPlugin = /** @class */ (function () {
66
66
  if (_this.editor) {
67
67
  if (!_this.isDblClicked) {
68
68
  _this.editor.focus();
69
- var caretPosition = getNodePositionFromEvent(_this.editor, event.rawEvent.x, event.rawEvent.y);
69
+ var caretPosition = getNodePositionFromEvent(_this.editor.getDocument(), _this.editor.getDOMHelper(), event.rawEvent.x, event.rawEvent.y);
70
70
  var newRange = _this.editor.getDocument().createRange();
71
71
  if (caretPosition) {
72
72
  var node = caretPosition.node, offset = caretPosition.offset;
@@ -114,7 +114,7 @@ var TouchPlugin = /** @class */ (function () {
114
114
  if (this.isTouchPenPointerEvent) {
115
115
  event.rawEvent.preventDefault();
116
116
  this.isDblClicked = true;
117
- var caretPosition = getNodePositionFromEvent(this.editor, event.rawEvent.x, event.rawEvent.y);
117
+ var caretPosition = getNodePositionFromEvent(this.editor.getDocument(), this.editor.getDOMHelper(), event.rawEvent.x, event.rawEvent.y);
118
118
  if (caretPosition) {
119
119
  var node = caretPosition.node, offset = caretPosition.offset;
120
120
  if (node.nodeType !== Node.TEXT_NODE) {
@@ -1 +1 @@
1
- {"version":3,"file":"TouchPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/touch/TouchPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { getNodePositionFromEvent } from '../utils/getNodePositionFromEvent';\nimport type { EditorPlugin, IEditor, PluginEvent } from 'roosterjs-content-model-types';\n\nconst MAX_TOUCH_MOVE_DISTANCE = 6; // the max number of offsets for the touch selection to move\nconst 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\nconst PUNCTUATION_MATCHING_REGEX = /[.,;:!]/;\nconst SPACE_MATCHING_REGEX = /\\s/;\n\n/**\n * Touch plugin to manage touch behaviors\n */\nexport class TouchPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n private timer = 0;\n private isDblClicked: boolean = false;\n private isTouchPenPointerEvent: boolean = false;\n\n /**\n * Create an instance of Touch plugin\n */\n constructor() {}\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Touch';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.isDblClicked = false;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n if (this.timer) {\n this.editor?.getDocument()?.defaultView?.clearTimeout(this.timer);\n this.timer = 0;\n }\n this.editor = null;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (!this.editor) {\n return;\n }\n switch (event.eventType) {\n case 'pointerDown':\n this.isDblClicked = false;\n this.isTouchPenPointerEvent = true;\n event.originalEvent.preventDefault();\n\n const targetWindow = this.editor.getDocument().defaultView;\n\n if (targetWindow) {\n if (this.timer) {\n targetWindow.clearTimeout(this.timer);\n }\n\n this.timer = targetWindow.setTimeout(() => {\n this.timer = 0;\n\n if (this.editor) {\n if (!this.isDblClicked) {\n this.editor.focus();\n const caretPosition = getNodePositionFromEvent(\n this.editor,\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n const newRange = this.editor.getDocument().createRange();\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n // Place cursor at same position of browser handler by default\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset);\n\n const nodeTextContent = node.textContent || '';\n const charAtSelection = nodeTextContent[offset];\n if (\n node.nodeType === Node.TEXT_NODE &&\n charAtSelection &&\n !SPACE_MATCHING_REGEX.test(charAtSelection) &&\n !PUNCTUATION_MATCHING_REGEX.test(charAtSelection)\n ) {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n\n // Move cursor to the calculated offset\n const leftCursorWordLength = offset - wordStart;\n const rightCursorWordLength = wordEnd - offset;\n let movingOffset: number =\n leftCursorWordLength >= rightCursorWordLength\n ? rightCursorWordLength\n : -leftCursorWordLength;\n movingOffset =\n Math.abs(movingOffset) > MAX_TOUCH_MOVE_DISTANCE\n ? 0\n : movingOffset;\n const newOffsetPosition = offset + movingOffset;\n if (\n movingOffset !== 0 &&\n nodeTextContent.length >= newOffsetPosition\n ) {\n newRange.setStart(node, newOffsetPosition);\n newRange.setEnd(node, newOffsetPosition);\n }\n }\n }\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n\n // reset values\n this.isTouchPenPointerEvent = false;\n }\n }\n }, POINTER_DETECTION_DELAY);\n }\n break;\n case 'doubleClick':\n if (this.isTouchPenPointerEvent) {\n event.rawEvent.preventDefault();\n\n this.isDblClicked = true;\n const caretPosition = getNodePositionFromEvent(\n this.editor,\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n if (node.nodeType !== Node.TEXT_NODE) {\n return;\n }\n\n const nodeTextContent = node.nodeValue || '';\n const char = nodeTextContent.charAt(offset);\n\n // Check if the clicked character is a punctuation mark, then highlight that character only\n if (PUNCTUATION_MATCHING_REGEX.test(char)) {\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n } else if (SPACE_MATCHING_REGEX.test(char)) {\n // If the clicked character is an open space with no word of right side\n const rightSideOfChar = nodeTextContent.substring(\n offset,\n nodeTextContent.length\n );\n const isRightSideAllSpaces =\n rightSideOfChar.length > 0 && !/\\S/.test(rightSideOfChar);\n if (isRightSideAllSpaces) {\n // select the first space only\n let start = offset;\n while (\n start > 0 &&\n SPACE_MATCHING_REGEX.test(nodeTextContent.charAt(start - 1))\n ) {\n start--;\n }\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, start);\n newRange.setEnd(node, start + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n } else {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, wordStart);\n newRange.setEnd(node, wordEnd);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n }\n }\n break;\n }\n }\n}\n\n/**\n * @internal\n * Finds the start and end indices of the word at the given offset in the text.\n * @param text The string to search within.\n * @param offset The index within the string to find the word boundaries around.\n * @returns An object containing wordStart and wordEnd indices.\n */\nfunction findWordBoundaries(text: string, offset: number) {\n let start = offset;\n let end = offset;\n\n // Move start backwards to find word start\n while (\n start > 0 &&\n !SPACE_MATCHING_REGEX.test(text[start - 1]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[start - 1])\n ) {\n start--;\n }\n\n // Move end forward to find word end\n while (\n end < text.length &&\n !SPACE_MATCHING_REGEX.test(text[end]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[end])\n ) {\n end++;\n }\n\n return {\n wordStart: start,\n wordEnd: end,\n };\n}\n"]}
1
+ {"version":3,"file":"TouchPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/touch/TouchPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { getNodePositionFromEvent } from 'roosterjs-content-model-dom';\nimport type { EditorPlugin, IEditor, PluginEvent } from 'roosterjs-content-model-types';\n\nconst MAX_TOUCH_MOVE_DISTANCE = 6; // the max number of offsets for the touch selection to move\nconst 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\nconst PUNCTUATION_MATCHING_REGEX = /[.,;:!]/;\nconst SPACE_MATCHING_REGEX = /\\s/;\n\n/**\n * Touch plugin to manage touch behaviors\n */\nexport class TouchPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n private timer = 0;\n private isDblClicked: boolean = false;\n private isTouchPenPointerEvent: boolean = false;\n\n /**\n * Create an instance of Touch plugin\n */\n constructor() {}\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Touch';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.isDblClicked = false;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n if (this.timer) {\n this.editor?.getDocument()?.defaultView?.clearTimeout(this.timer);\n this.timer = 0;\n }\n this.editor = null;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (!this.editor) {\n return;\n }\n switch (event.eventType) {\n case 'pointerDown':\n this.isDblClicked = false;\n this.isTouchPenPointerEvent = true;\n event.originalEvent.preventDefault();\n\n const targetWindow = this.editor.getDocument().defaultView;\n\n if (targetWindow) {\n if (this.timer) {\n targetWindow.clearTimeout(this.timer);\n }\n\n this.timer = targetWindow.setTimeout(() => {\n this.timer = 0;\n\n if (this.editor) {\n if (!this.isDblClicked) {\n this.editor.focus();\n const caretPosition = getNodePositionFromEvent(\n this.editor.getDocument(),\n this.editor.getDOMHelper(),\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n const newRange = this.editor.getDocument().createRange();\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n // Place cursor at same position of browser handler by default\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset);\n\n const nodeTextContent = node.textContent || '';\n const charAtSelection = nodeTextContent[offset];\n if (\n node.nodeType === Node.TEXT_NODE &&\n charAtSelection &&\n !SPACE_MATCHING_REGEX.test(charAtSelection) &&\n !PUNCTUATION_MATCHING_REGEX.test(charAtSelection)\n ) {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n\n // Move cursor to the calculated offset\n const leftCursorWordLength = offset - wordStart;\n const rightCursorWordLength = wordEnd - offset;\n let movingOffset: number =\n leftCursorWordLength >= rightCursorWordLength\n ? rightCursorWordLength\n : -leftCursorWordLength;\n movingOffset =\n Math.abs(movingOffset) > MAX_TOUCH_MOVE_DISTANCE\n ? 0\n : movingOffset;\n const newOffsetPosition = offset + movingOffset;\n if (\n movingOffset !== 0 &&\n nodeTextContent.length >= newOffsetPosition\n ) {\n newRange.setStart(node, newOffsetPosition);\n newRange.setEnd(node, newOffsetPosition);\n }\n }\n }\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n\n // reset values\n this.isTouchPenPointerEvent = false;\n }\n }\n }, POINTER_DETECTION_DELAY);\n }\n break;\n case 'doubleClick':\n if (this.isTouchPenPointerEvent) {\n event.rawEvent.preventDefault();\n\n this.isDblClicked = true;\n const caretPosition = getNodePositionFromEvent(\n this.editor.getDocument(),\n this.editor.getDOMHelper(),\n event.rawEvent.x,\n event.rawEvent.y\n );\n\n if (caretPosition) {\n const { node, offset } = caretPosition;\n\n if (node.nodeType !== Node.TEXT_NODE) {\n return;\n }\n\n const nodeTextContent = node.nodeValue || '';\n const char = nodeTextContent.charAt(offset);\n\n // Check if the clicked character is a punctuation mark, then highlight that character only\n if (PUNCTUATION_MATCHING_REGEX.test(char)) {\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, offset);\n newRange.setEnd(node, offset + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n } else if (SPACE_MATCHING_REGEX.test(char)) {\n // If the clicked character is an open space with no word of right side\n const rightSideOfChar = nodeTextContent.substring(\n offset,\n nodeTextContent.length\n );\n const isRightSideAllSpaces =\n rightSideOfChar.length > 0 && !/\\S/.test(rightSideOfChar);\n if (isRightSideAllSpaces) {\n // select the first space only\n let start = offset;\n while (\n start > 0 &&\n SPACE_MATCHING_REGEX.test(nodeTextContent.charAt(start - 1))\n ) {\n start--;\n }\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, start);\n newRange.setEnd(node, start + 1);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n } else {\n const { wordStart, wordEnd } = findWordBoundaries(\n nodeTextContent,\n offset\n );\n const newRange = this.editor.getDocument()?.createRange();\n if (newRange) {\n newRange.setStart(node, wordStart);\n newRange.setEnd(node, wordEnd);\n this.editor.setDOMSelection({\n type: 'range',\n range: newRange,\n isReverted: false,\n });\n }\n }\n }\n }\n break;\n }\n }\n}\n\n/**\n * @internal\n * Finds the start and end indices of the word at the given offset in the text.\n * @param text The string to search within.\n * @param offset The index within the string to find the word boundaries around.\n * @returns An object containing wordStart and wordEnd indices.\n */\nfunction findWordBoundaries(text: string, offset: number) {\n let start = offset;\n let end = offset;\n\n // Move start backwards to find word start\n while (\n start > 0 &&\n !SPACE_MATCHING_REGEX.test(text[start - 1]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[start - 1])\n ) {\n start--;\n }\n\n // Move end forward to find word end\n while (\n end < text.length &&\n !SPACE_MATCHING_REGEX.test(text[end]) &&\n !PUNCTUATION_MATCHING_REGEX.test(text[end])\n ) {\n end++;\n }\n\n return {\n wordStart: start,\n wordEnd: end,\n };\n}\n"]}
package/package.json CHANGED
@@ -3,12 +3,12 @@
3
3
  "description": "Plugins for roosterjs",
4
4
  "dependencies": {
5
5
  "tslib": "^2.3.1",
6
- "roosterjs-content-model-core": "^9.46.0",
7
- "roosterjs-content-model-dom": "^9.46.0",
8
- "roosterjs-content-model-types": "^9.46.0",
9
- "roosterjs-content-model-api": "^9.46.0"
6
+ "roosterjs-content-model-core": "^9.47.0",
7
+ "roosterjs-content-model-dom": "^9.47.0",
8
+ "roosterjs-content-model-types": "^9.47.0",
9
+ "roosterjs-content-model-api": "^9.47.0"
10
10
  },
11
- "version": "9.46.0",
11
+ "version": "9.47.0",
12
12
  "main": "./lib/index.js",
13
13
  "typings": "./lib/index.d.ts",
14
14
  "module": "./lib-mjs/index.js",
@@ -1,5 +0,0 @@
1
- import type { DOMInsertPoint, IEditor } from 'roosterjs-content-model-types';
2
- /**
3
- * @internal Get insertion point from coordinate.
4
- */
5
- export declare function getNodePositionFromEvent(editor: IEditor, x: number, y: number): DOMInsertPoint | null;
@@ -1,34 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getNodePositionFromEvent = void 0;
4
- /**
5
- * @internal Get insertion point from coordinate.
6
- */
7
- function getNodePositionFromEvent(editor, x, y) {
8
- var doc = editor.getDocument();
9
- var domHelper = editor.getDOMHelper();
10
- if ('caretPositionFromPoint' in doc) {
11
- // Firefox, Chrome, Edge, Safari, Opera
12
- var pos = doc.caretPositionFromPoint(x, y);
13
- if (pos && domHelper.isNodeInEditor(pos.offsetNode)) {
14
- return { node: pos.offsetNode, offset: pos.offset };
15
- }
16
- }
17
- if (doc.caretRangeFromPoint) {
18
- // Safari
19
- var range = doc.caretRangeFromPoint(x, y);
20
- if (range && domHelper.isNodeInEditor(range.startContainer)) {
21
- return { node: range.startContainer, offset: range.startOffset };
22
- }
23
- }
24
- if (doc.elementFromPoint) {
25
- // Fallback
26
- var element = doc.elementFromPoint(x, y);
27
- if (element && domHelper.isNodeInEditor(element)) {
28
- return { node: element, offset: 0 };
29
- }
30
- }
31
- return null;
32
- }
33
- exports.getNodePositionFromEvent = getNodePositionFromEvent;
34
- //# sourceMappingURL=getNodePositionFromEvent.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getNodePositionFromEvent.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/utils/getNodePositionFromEvent.ts"],"names":[],"mappings":";;;AAEA;;GAEG;AACH,SAAgB,wBAAwB,CACpC,MAAe,EACf,CAAS,EACT,CAAS;IAET,IAAM,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACjC,IAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;IAExC,IAAI,wBAAwB,IAAI,GAAG,EAAE;QACjC,uCAAuC;QACvC,IAAM,GAAG,GAAI,GAAW,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtD,IAAI,GAAG,IAAI,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE;YACjD,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;SACvD;KACJ;IAED,IAAI,GAAG,CAAC,mBAAmB,EAAE;QACzB,SAAS;QACT,IAAM,KAAK,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5C,IAAI,KAAK,IAAI,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE;YACzD,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;SACpE;KACJ;IAED,IAAI,GAAG,CAAC,gBAAgB,EAAE;QACtB,WAAW;QACX,IAAM,OAAO,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3C,IAAI,OAAO,IAAI,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE;YAC9C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;SACvC;KACJ;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAjCD,4DAiCC","sourcesContent":["import type { DOMInsertPoint, IEditor } from 'roosterjs-content-model-types';\n\n/**\n * @internal Get insertion point from coordinate.\n */\nexport function getNodePositionFromEvent(\n editor: IEditor,\n x: number,\n y: number\n): DOMInsertPoint | null {\n const doc = editor.getDocument();\n const domHelper = editor.getDOMHelper();\n\n if ('caretPositionFromPoint' in doc) {\n // Firefox, Chrome, Edge, Safari, Opera\n const pos = (doc as any).caretPositionFromPoint(x, y);\n if (pos && domHelper.isNodeInEditor(pos.offsetNode)) {\n return { node: pos.offsetNode, offset: pos.offset };\n }\n }\n\n if (doc.caretRangeFromPoint) {\n // Safari\n const range = doc.caretRangeFromPoint(x, y);\n if (range && domHelper.isNodeInEditor(range.startContainer)) {\n return { node: range.startContainer, offset: range.startOffset };\n }\n }\n\n if (doc.elementFromPoint) {\n // Fallback\n const element = doc.elementFromPoint(x, y);\n if (element && domHelper.isNodeInEditor(element)) {\n return { node: element, offset: 0 };\n }\n }\n\n return null;\n}\n"]}
@@ -1,5 +0,0 @@
1
- import type { DOMInsertPoint, IEditor } from 'roosterjs-content-model-types';
2
- /**
3
- * @internal Get insertion point from coordinate.
4
- */
5
- export declare function getNodePositionFromEvent(editor: IEditor, x: number, y: number): DOMInsertPoint | null;
@@ -1,36 +0,0 @@
1
- define(["require", "exports"], function (require, exports) {
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.getNodePositionFromEvent = void 0;
5
- /**
6
- * @internal Get insertion point from coordinate.
7
- */
8
- function getNodePositionFromEvent(editor, x, y) {
9
- var doc = editor.getDocument();
10
- var domHelper = editor.getDOMHelper();
11
- if ('caretPositionFromPoint' in doc) {
12
- // Firefox, Chrome, Edge, Safari, Opera
13
- var pos = doc.caretPositionFromPoint(x, y);
14
- if (pos && domHelper.isNodeInEditor(pos.offsetNode)) {
15
- return { node: pos.offsetNode, offset: pos.offset };
16
- }
17
- }
18
- if (doc.caretRangeFromPoint) {
19
- // Safari
20
- var range = doc.caretRangeFromPoint(x, y);
21
- if (range && domHelper.isNodeInEditor(range.startContainer)) {
22
- return { node: range.startContainer, offset: range.startOffset };
23
- }
24
- }
25
- if (doc.elementFromPoint) {
26
- // Fallback
27
- var element = doc.elementFromPoint(x, y);
28
- if (element && domHelper.isNodeInEditor(element)) {
29
- return { node: element, offset: 0 };
30
- }
31
- }
32
- return null;
33
- }
34
- exports.getNodePositionFromEvent = getNodePositionFromEvent;
35
- });
36
- //# sourceMappingURL=getNodePositionFromEvent.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getNodePositionFromEvent.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/utils/getNodePositionFromEvent.ts"],"names":[],"mappings":";;;;IAEA;;OAEG;IACH,SAAgB,wBAAwB,CACpC,MAAe,EACf,CAAS,EACT,CAAS;QAET,IAAM,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QACjC,IAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;QAExC,IAAI,wBAAwB,IAAI,GAAG,EAAE;YACjC,uCAAuC;YACvC,IAAM,GAAG,GAAI,GAAW,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACtD,IAAI,GAAG,IAAI,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE;gBACjD,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;aACvD;SACJ;QAED,IAAI,GAAG,CAAC,mBAAmB,EAAE;YACzB,SAAS;YACT,IAAM,KAAK,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5C,IAAI,KAAK,IAAI,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE;gBACzD,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;aACpE;SACJ;QAED,IAAI,GAAG,CAAC,gBAAgB,EAAE;YACtB,WAAW;YACX,IAAM,OAAO,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3C,IAAI,OAAO,IAAI,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE;gBAC9C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;aACvC;SACJ;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAjCD,4DAiCC","sourcesContent":["import type { DOMInsertPoint, IEditor } from 'roosterjs-content-model-types';\n\n/**\n * @internal Get insertion point from coordinate.\n */\nexport function getNodePositionFromEvent(\n editor: IEditor,\n x: number,\n y: number\n): DOMInsertPoint | null {\n const doc = editor.getDocument();\n const domHelper = editor.getDOMHelper();\n\n if ('caretPositionFromPoint' in doc) {\n // Firefox, Chrome, Edge, Safari, Opera\n const pos = (doc as any).caretPositionFromPoint(x, y);\n if (pos && domHelper.isNodeInEditor(pos.offsetNode)) {\n return { node: pos.offsetNode, offset: pos.offset };\n }\n }\n\n if (doc.caretRangeFromPoint) {\n // Safari\n const range = doc.caretRangeFromPoint(x, y);\n if (range && domHelper.isNodeInEditor(range.startContainer)) {\n return { node: range.startContainer, offset: range.startOffset };\n }\n }\n\n if (doc.elementFromPoint) {\n // Fallback\n const element = doc.elementFromPoint(x, y);\n if (element && domHelper.isNodeInEditor(element)) {\n return { node: element, offset: 0 };\n }\n }\n\n return null;\n}\n"]}
@@ -1,5 +0,0 @@
1
- import type { DOMInsertPoint, IEditor } from 'roosterjs-content-model-types';
2
- /**
3
- * @internal Get insertion point from coordinate.
4
- */
5
- export declare function getNodePositionFromEvent(editor: IEditor, x: number, y: number): DOMInsertPoint | null;
@@ -1,30 +0,0 @@
1
- /**
2
- * @internal Get insertion point from coordinate.
3
- */
4
- export function getNodePositionFromEvent(editor, x, y) {
5
- var doc = editor.getDocument();
6
- var domHelper = editor.getDOMHelper();
7
- if ('caretPositionFromPoint' in doc) {
8
- // Firefox, Chrome, Edge, Safari, Opera
9
- var pos = doc.caretPositionFromPoint(x, y);
10
- if (pos && domHelper.isNodeInEditor(pos.offsetNode)) {
11
- return { node: pos.offsetNode, offset: pos.offset };
12
- }
13
- }
14
- if (doc.caretRangeFromPoint) {
15
- // Safari
16
- var range = doc.caretRangeFromPoint(x, y);
17
- if (range && domHelper.isNodeInEditor(range.startContainer)) {
18
- return { node: range.startContainer, offset: range.startOffset };
19
- }
20
- }
21
- if (doc.elementFromPoint) {
22
- // Fallback
23
- var element = doc.elementFromPoint(x, y);
24
- if (element && domHelper.isNodeInEditor(element)) {
25
- return { node: element, offset: 0 };
26
- }
27
- }
28
- return null;
29
- }
30
- //# sourceMappingURL=getNodePositionFromEvent.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getNodePositionFromEvent.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/utils/getNodePositionFromEvent.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,wBAAwB,CACpC,MAAe,EACf,CAAS,EACT,CAAS;IAET,IAAM,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACjC,IAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;IAExC,IAAI,wBAAwB,IAAI,GAAG,EAAE;QACjC,uCAAuC;QACvC,IAAM,GAAG,GAAI,GAAW,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtD,IAAI,GAAG,IAAI,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE;YACjD,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;SACvD;KACJ;IAED,IAAI,GAAG,CAAC,mBAAmB,EAAE;QACzB,SAAS;QACT,IAAM,KAAK,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5C,IAAI,KAAK,IAAI,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE;YACzD,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;SACpE;KACJ;IAED,IAAI,GAAG,CAAC,gBAAgB,EAAE;QACtB,WAAW;QACX,IAAM,OAAO,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3C,IAAI,OAAO,IAAI,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE;YAC9C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;SACvC;KACJ;IAED,OAAO,IAAI,CAAC;AAChB,CAAC","sourcesContent":["import type { DOMInsertPoint, IEditor } from 'roosterjs-content-model-types';\n\n/**\n * @internal Get insertion point from coordinate.\n */\nexport function getNodePositionFromEvent(\n editor: IEditor,\n x: number,\n y: number\n): DOMInsertPoint | null {\n const doc = editor.getDocument();\n const domHelper = editor.getDOMHelper();\n\n if ('caretPositionFromPoint' in doc) {\n // Firefox, Chrome, Edge, Safari, Opera\n const pos = (doc as any).caretPositionFromPoint(x, y);\n if (pos && domHelper.isNodeInEditor(pos.offsetNode)) {\n return { node: pos.offsetNode, offset: pos.offset };\n }\n }\n\n if (doc.caretRangeFromPoint) {\n // Safari\n const range = doc.caretRangeFromPoint(x, y);\n if (range && domHelper.isNodeInEditor(range.startContainer)) {\n return { node: range.startContainer, offset: range.startOffset };\n }\n }\n\n if (doc.elementFromPoint) {\n // Fallback\n const element = doc.elementFromPoint(x, y);\n if (element && domHelper.isNodeInEditor(element)) {\n return { node: element, offset: 0 };\n }\n }\n\n return null;\n}\n"]}