roosterjs-content-model-core 9.52.0 → 9.54.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 (136) hide show
  1. package/lib/command/cutCopy/getContentForCopy.js +4 -1
  2. package/lib/command/cutCopy/getContentForCopy.js.map +1 -1
  3. package/lib/coreApi/announce/announce.js +1 -0
  4. package/lib/coreApi/announce/announce.js.map +1 -1
  5. package/lib/coreApi/createContentModel/createContentModel.js +3 -0
  6. package/lib/coreApi/createContentModel/createContentModel.js.map +1 -1
  7. package/lib/coreApi/getDOMSelection/getDOMSelection.js +12 -9
  8. package/lib/coreApi/getDOMSelection/getDOMSelection.js.map +1 -1
  9. package/lib/coreApi/setDOMSelection/setDOMSelection.js +7 -8
  10. package/lib/coreApi/setDOMSelection/setDOMSelection.js.map +1 -1
  11. package/lib/coreApi/setEditorStyle/ensureUniqueId.js +2 -2
  12. package/lib/coreApi/setEditorStyle/ensureUniqueId.js.map +1 -1
  13. package/lib/coreApi/setEditorStyle/setEditorStyle.js +1 -1
  14. package/lib/coreApi/setEditorStyle/setEditorStyle.js.map +1 -1
  15. package/lib/corePlugin/cache/CachePlugin.js +5 -0
  16. package/lib/corePlugin/cache/CachePlugin.js.map +1 -1
  17. package/lib/corePlugin/cache/MutationType.d.ts +12 -1
  18. package/lib/corePlugin/cache/MutationType.js.map +1 -1
  19. package/lib/corePlugin/cache/areSameSelections.d.ts +0 -4
  20. package/lib/corePlugin/cache/areSameSelections.js +3 -10
  21. package/lib/corePlugin/cache/areSameSelections.js.map +1 -1
  22. package/lib/corePlugin/cache/domIndexerImpl.d.ts +1 -0
  23. package/lib/corePlugin/cache/domIndexerImpl.js +41 -6
  24. package/lib/corePlugin/cache/domIndexerImpl.js.map +1 -1
  25. package/lib/corePlugin/cache/textMutationObserver.js +10 -0
  26. package/lib/corePlugin/cache/textMutationObserver.js.map +1 -1
  27. package/lib/corePlugin/lifecycle/LifecyclePlugin.js +1 -0
  28. package/lib/corePlugin/lifecycle/LifecyclePlugin.js.map +1 -1
  29. package/lib/corePlugin/selection/SelectionPlugin.js +10 -7
  30. package/lib/corePlugin/selection/SelectionPlugin.js.map +1 -1
  31. package/lib/editor/core/DOMHelperImpl.d.ts +4 -0
  32. package/lib/editor/core/DOMHelperImpl.js +61 -1
  33. package/lib/editor/core/DOMHelperImpl.js.map +1 -1
  34. package/lib/editor/core/createEditorCore.js +4 -1
  35. package/lib/editor/core/createEditorCore.js.map +1 -1
  36. package/lib/override/containerSizeFormatParser.js +2 -0
  37. package/lib/override/containerSizeFormatParser.js.map +1 -1
  38. package/lib/utils/areSameRanges.d.ts +5 -0
  39. package/lib/utils/areSameRanges.js +13 -0
  40. package/lib/utils/areSameRanges.js.map +1 -0
  41. package/lib/utils/createAriaLiveElement.js +0 -1
  42. package/lib/utils/createAriaLiveElement.js.map +1 -1
  43. package/lib-amd/command/cutCopy/getContentForCopy.js +4 -1
  44. package/lib-amd/command/cutCopy/getContentForCopy.js.map +1 -1
  45. package/lib-amd/coreApi/announce/announce.js +1 -0
  46. package/lib-amd/coreApi/announce/announce.js.map +1 -1
  47. package/lib-amd/coreApi/createContentModel/createContentModel.js +3 -0
  48. package/lib-amd/coreApi/createContentModel/createContentModel.js.map +1 -1
  49. package/lib-amd/coreApi/getDOMSelection/getDOMSelection.js +12 -9
  50. package/lib-amd/coreApi/getDOMSelection/getDOMSelection.js.map +1 -1
  51. package/lib-amd/coreApi/setDOMSelection/setDOMSelection.js +8 -8
  52. package/lib-amd/coreApi/setDOMSelection/setDOMSelection.js.map +1 -1
  53. package/lib-amd/coreApi/setEditorStyle/ensureUniqueId.js +2 -2
  54. package/lib-amd/coreApi/setEditorStyle/ensureUniqueId.js.map +1 -1
  55. package/lib-amd/coreApi/setEditorStyle/setEditorStyle.js +1 -1
  56. package/lib-amd/coreApi/setEditorStyle/setEditorStyle.js.map +1 -1
  57. package/lib-amd/corePlugin/cache/CachePlugin.js +5 -0
  58. package/lib-amd/corePlugin/cache/CachePlugin.js.map +1 -1
  59. package/lib-amd/corePlugin/cache/MutationType.d.ts +12 -1
  60. package/lib-amd/corePlugin/cache/MutationType.js.map +1 -1
  61. package/lib-amd/corePlugin/cache/areSameSelections.d.ts +0 -4
  62. package/lib-amd/corePlugin/cache/areSameSelections.js +3 -11
  63. package/lib-amd/corePlugin/cache/areSameSelections.js.map +1 -1
  64. package/lib-amd/corePlugin/cache/domIndexerImpl.d.ts +1 -0
  65. package/lib-amd/corePlugin/cache/domIndexerImpl.js +41 -6
  66. package/lib-amd/corePlugin/cache/domIndexerImpl.js.map +1 -1
  67. package/lib-amd/corePlugin/cache/textMutationObserver.js +10 -0
  68. package/lib-amd/corePlugin/cache/textMutationObserver.js.map +1 -1
  69. package/lib-amd/corePlugin/lifecycle/LifecyclePlugin.js +1 -0
  70. package/lib-amd/corePlugin/lifecycle/LifecyclePlugin.js.map +1 -1
  71. package/lib-amd/corePlugin/selection/SelectionPlugin.js +10 -7
  72. package/lib-amd/corePlugin/selection/SelectionPlugin.js.map +1 -1
  73. package/lib-amd/editor/core/DOMHelperImpl.d.ts +4 -0
  74. package/lib-amd/editor/core/DOMHelperImpl.js +61 -2
  75. package/lib-amd/editor/core/DOMHelperImpl.js.map +1 -1
  76. package/lib-amd/editor/core/createEditorCore.js +4 -1
  77. package/lib-amd/editor/core/createEditorCore.js.map +1 -1
  78. package/lib-amd/override/containerSizeFormatParser.js +2 -0
  79. package/lib-amd/override/containerSizeFormatParser.js.map +1 -1
  80. package/lib-amd/utils/areSameRanges.d.ts +5 -0
  81. package/lib-amd/utils/areSameRanges.js +15 -0
  82. package/lib-amd/utils/areSameRanges.js.map +1 -0
  83. package/lib-amd/utils/createAriaLiveElement.js +0 -1
  84. package/lib-amd/utils/createAriaLiveElement.js.map +1 -1
  85. package/lib-mjs/command/cutCopy/getContentForCopy.js +5 -2
  86. package/lib-mjs/command/cutCopy/getContentForCopy.js.map +1 -1
  87. package/lib-mjs/coreApi/announce/announce.js +1 -0
  88. package/lib-mjs/coreApi/announce/announce.js.map +1 -1
  89. package/lib-mjs/coreApi/createContentModel/createContentModel.js +3 -0
  90. package/lib-mjs/coreApi/createContentModel/createContentModel.js.map +1 -1
  91. package/lib-mjs/coreApi/getDOMSelection/getDOMSelection.js +12 -9
  92. package/lib-mjs/coreApi/getDOMSelection/getDOMSelection.js.map +1 -1
  93. package/lib-mjs/coreApi/setDOMSelection/setDOMSelection.js +7 -8
  94. package/lib-mjs/coreApi/setDOMSelection/setDOMSelection.js.map +1 -1
  95. package/lib-mjs/coreApi/setEditorStyle/ensureUniqueId.js +2 -2
  96. package/lib-mjs/coreApi/setEditorStyle/ensureUniqueId.js.map +1 -1
  97. package/lib-mjs/coreApi/setEditorStyle/setEditorStyle.js +1 -1
  98. package/lib-mjs/coreApi/setEditorStyle/setEditorStyle.js.map +1 -1
  99. package/lib-mjs/corePlugin/cache/CachePlugin.js +5 -0
  100. package/lib-mjs/corePlugin/cache/CachePlugin.js.map +1 -1
  101. package/lib-mjs/corePlugin/cache/MutationType.d.ts +12 -1
  102. package/lib-mjs/corePlugin/cache/MutationType.js.map +1 -1
  103. package/lib-mjs/corePlugin/cache/areSameSelections.d.ts +0 -4
  104. package/lib-mjs/corePlugin/cache/areSameSelections.js +1 -7
  105. package/lib-mjs/corePlugin/cache/areSameSelections.js.map +1 -1
  106. package/lib-mjs/corePlugin/cache/domIndexerImpl.d.ts +1 -0
  107. package/lib-mjs/corePlugin/cache/domIndexerImpl.js +41 -6
  108. package/lib-mjs/corePlugin/cache/domIndexerImpl.js.map +1 -1
  109. package/lib-mjs/corePlugin/cache/textMutationObserver.js +10 -0
  110. package/lib-mjs/corePlugin/cache/textMutationObserver.js.map +1 -1
  111. package/lib-mjs/corePlugin/lifecycle/LifecyclePlugin.js +1 -0
  112. package/lib-mjs/corePlugin/lifecycle/LifecyclePlugin.js.map +1 -1
  113. package/lib-mjs/corePlugin/selection/SelectionPlugin.js +10 -7
  114. package/lib-mjs/corePlugin/selection/SelectionPlugin.js.map +1 -1
  115. package/lib-mjs/editor/core/DOMHelperImpl.d.ts +4 -0
  116. package/lib-mjs/editor/core/DOMHelperImpl.js +61 -1
  117. package/lib-mjs/editor/core/DOMHelperImpl.js.map +1 -1
  118. package/lib-mjs/editor/core/createEditorCore.js +4 -1
  119. package/lib-mjs/editor/core/createEditorCore.js.map +1 -1
  120. package/lib-mjs/override/containerSizeFormatParser.js +2 -0
  121. package/lib-mjs/override/containerSizeFormatParser.js.map +1 -1
  122. package/lib-mjs/utils/areSameRanges.d.ts +5 -0
  123. package/lib-mjs/utils/areSameRanges.js +9 -0
  124. package/lib-mjs/utils/areSameRanges.js.map +1 -0
  125. package/lib-mjs/utils/createAriaLiveElement.js +0 -1
  126. package/lib-mjs/utils/createAriaLiveElement.js.map +1 -1
  127. package/package.json +3 -3
  128. package/lib/coreApi/setDOMSelection/addRangeToSelection.d.ts +0 -4
  129. package/lib/coreApi/setDOMSelection/addRangeToSelection.js +0 -27
  130. package/lib/coreApi/setDOMSelection/addRangeToSelection.js.map +0 -1
  131. package/lib-amd/coreApi/setDOMSelection/addRangeToSelection.d.ts +0 -4
  132. package/lib-amd/coreApi/setDOMSelection/addRangeToSelection.js +0 -28
  133. package/lib-amd/coreApi/setDOMSelection/addRangeToSelection.js.map +0 -1
  134. package/lib-mjs/coreApi/setDOMSelection/addRangeToSelection.d.ts +0 -4
  135. package/lib-mjs/coreApi/setDOMSelection/addRangeToSelection.js +0 -23
  136. package/lib-mjs/coreApi/setDOMSelection/addRangeToSelection.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"getContentForCopy.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/command/cutCopy/getContentForCopy.ts"],"names":[],"mappings":"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","sourcesContent":["import { adjustImageSelectionOnSafari } from './adjustImageSelectionOnSafari';\nimport { adjustSelectionForCopyCut } from './adjustSelectionForCopyCut';\nimport { onCreateCopyEntityNode } from '../../override/pasteCopyBlockEntityParser';\nimport {\n contentModelToDom,\n contentModelToText,\n createModelToDomContext,\n trimModelForSelection,\n isElementOfType,\n isNodeOfType,\n wrap,\n} from 'roosterjs-content-model-dom';\nimport type {\n DOMSelection,\n IEditor,\n OnNodeCreated,\n TextAndHtmlContentForCopy,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n * Exported only for unit testing\n */\nexport const onNodeCreated: OnNodeCreated = (modelElement, node): void => {\n if (isNodeOfType(node, 'ELEMENT_NODE') && isElementOfType(node, 'table')) {\n wrap(node.ownerDocument, node, 'div');\n }\n if (isNodeOfType(node, 'ELEMENT_NODE') && !node.isContentEditable) {\n node.removeAttribute('contenteditable');\n }\n onCreateCopyEntityNode(modelElement, node);\n};\n\n/**\n * Get the content for the copy event\n * @param editor The editor object\n * @param isCut if the event cut the content.\n * @param event the clipboard event that triggered the copy/cut\n * @returns\n */\nexport function getContentForCopy(\n editor: IEditor,\n isCut: boolean,\n event: ClipboardEvent\n): TextAndHtmlContentForCopy | null {\n const selection = editor.getDOMSelection();\n adjustImageSelectionOnSafari(editor, selection);\n\n if (selection && (selection.type !== 'range' || !selection.range.collapsed)) {\n const pasteModel = editor.getContentModelCopy('disconnected');\n const context = createModelToDomContext();\n trimModelForSelection(pasteModel, selection);\n\n if (selection.type === 'range') {\n adjustSelectionForCopyCut(pasteModel);\n }\n\n context.onNodeCreated = onNodeCreated;\n const doc = editor.getDocument();\n const tempDiv = doc.createElement('div');\n\n const selectionForCopy = contentModelToDom(doc, tempDiv, pasteModel, context);\n const newRange = selectionForCopy ? domSelectionToRange(doc, selectionForCopy) : null;\n if (newRange) {\n const { clonedRoot } = editor.triggerEvent('beforeCutCopy', {\n clonedRoot: tempDiv,\n range: newRange,\n rawEvent: event,\n isCut,\n });\n\n return {\n htmlContent: clonedRoot,\n textContent: contentModelToText(pasteModel),\n };\n }\n }\n return null;\n}\n\nfunction domSelectionToRange(doc: Document, selection: DOMSelection): Range | null {\n let newRange: Range | null = null;\n\n if (selection.type === 'table') {\n const table = selection.table;\n const elementToSelect =\n table.parentElement?.childElementCount == 1 ? table.parentElement : table;\n\n newRange = doc.createRange();\n newRange.selectNode(elementToSelect);\n } else if (selection.type === 'image') {\n newRange = doc.createRange();\n newRange.selectNode(selection.image);\n } else {\n newRange = selection.range;\n }\n\n return newRange;\n}\n"]}
1
+ {"version":3,"file":"getContentForCopy.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/command/cutCopy/getContentForCopy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACnF,OAAO,EACH,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,IAAI,GACP,MAAM,6BAA6B,CAAC;AAQrC;;;GAGG;AACH,MAAM,CAAC,IAAM,aAAa,GAAkB,UAAC,YAAY,EAAE,IAAI;IAC3D,IAAI,YAAY,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;QACtE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;KACzC;IACD,IAAI,YAAY,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;QAC/D,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC;KAC3C;IACD,sBAAsB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC7B,MAAe,EACf,KAAc,EACd,KAAqB;IAErB,IAAM,SAAS,GAAG,MAAM,CAAC,eAAe,EAAE,CAAC;IAC3C,4BAA4B,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAEhD,IAAI,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE;QACzE,IAAM,UAAU,GAAG,MAAM,CAAC,mBAAmB,CAAC,cAAc,CAAC,CAAC;QAC9D,IAAM,OAAO,GAAG,uBAAuB,EAAE,CAAC;QAC1C,qBAAqB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAE7C,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,EAAE;YAC5B,yBAAyB,CAAC,UAAU,CAAC,CAAC;SACzC;QAED,OAAO,CAAC,aAAa,GAAG,aAAa,CAAC;QACtC,IAAM,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QACjC,IAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAEzC,IAAM,gBAAgB,GAAG,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QAC9E,IAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACtF,IAAI,QAAQ,EAAE;YACF,IAAA,UAAU,GAAK,MAAM,CAAC,YAAY,CAAC,eAAe,EAAE;gBACxD,UAAU,EAAE,OAAO;gBACnB,KAAK,EAAE,QAAQ;gBACf,QAAQ,EAAE,KAAK;gBACf,KAAK,OAAA;aACR,CAAC,WALgB,CAKf;YAEH,uFAAuF;YACvF,8FAA8F;YAC9F,IAAM,SAAS,GAAG,iBAAiB,CAAC,UAAU,EAAE,uBAAuB,EAAE,CAAC,CAAC;YAE3E,OAAO;gBACH,WAAW,EAAE,UAAU;gBACvB,WAAW,EAAE,kBAAkB,CAAC,SAAS,CAAC;aAC7C,CAAC;SACL;KACJ;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAa,EAAE,SAAuB;;IAC/D,IAAI,QAAQ,GAAiB,IAAI,CAAC;IAElC,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,EAAE;QAC5B,IAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;QAC9B,IAAM,eAAe,GACjB,CAAA,MAAA,KAAK,CAAC,aAAa,0CAAE,iBAAiB,KAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC;QAE9E,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QAC7B,QAAQ,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;KACxC;SAAM,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,EAAE;QACnC,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QAC7B,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;KACxC;SAAM;QACH,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC;KAC9B;IAED,OAAO,QAAQ,CAAC;AACpB,CAAC","sourcesContent":["import { adjustImageSelectionOnSafari } from './adjustImageSelectionOnSafari';\nimport { adjustSelectionForCopyCut } from './adjustSelectionForCopyCut';\nimport { onCreateCopyEntityNode } from '../../override/pasteCopyBlockEntityParser';\nimport {\n contentModelToDom,\n contentModelToText,\n createDomToModelContext,\n createModelToDomContext,\n domToContentModel,\n trimModelForSelection,\n isElementOfType,\n isNodeOfType,\n wrap,\n} from 'roosterjs-content-model-dom';\nimport type {\n DOMSelection,\n IEditor,\n OnNodeCreated,\n TextAndHtmlContentForCopy,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n * Exported only for unit testing\n */\nexport const onNodeCreated: OnNodeCreated = (modelElement, node): void => {\n if (isNodeOfType(node, 'ELEMENT_NODE') && isElementOfType(node, 'table')) {\n wrap(node.ownerDocument, node, 'div');\n }\n if (isNodeOfType(node, 'ELEMENT_NODE') && !node.isContentEditable) {\n node.removeAttribute('contenteditable');\n }\n onCreateCopyEntityNode(modelElement, node);\n};\n\n/**\n * Get the content for the copy event\n * @param editor The editor object\n * @param isCut if the event cut the content.\n * @param event the clipboard event that triggered the copy/cut\n * @returns\n */\nexport function getContentForCopy(\n editor: IEditor,\n isCut: boolean,\n event: ClipboardEvent\n): TextAndHtmlContentForCopy | null {\n const selection = editor.getDOMSelection();\n adjustImageSelectionOnSafari(editor, selection);\n\n if (selection && (selection.type !== 'range' || !selection.range.collapsed)) {\n const pasteModel = editor.getContentModelCopy('disconnected');\n const context = createModelToDomContext();\n trimModelForSelection(pasteModel, selection);\n\n if (selection.type === 'range') {\n adjustSelectionForCopyCut(pasteModel);\n }\n\n context.onNodeCreated = onNodeCreated;\n const doc = editor.getDocument();\n const tempDiv = doc.createElement('div');\n\n const selectionForCopy = contentModelToDom(doc, tempDiv, pasteModel, context);\n const newRange = selectionForCopy ? domSelectionToRange(doc, selectionForCopy) : null;\n if (newRange) {\n const { clonedRoot } = editor.triggerEvent('beforeCutCopy', {\n clonedRoot: tempDiv,\n range: newRange,\n rawEvent: event,\n isCut,\n });\n\n // Build the text content from the (possibly modified) cloned root DOM tree so that any\n // changes made by beforeCutCopy event handlers are reflected in the plain text result as well\n const textModel = domToContentModel(clonedRoot, createDomToModelContext());\n\n return {\n htmlContent: clonedRoot,\n textContent: contentModelToText(textModel),\n };\n }\n }\n return null;\n}\n\nfunction domSelectionToRange(doc: Document, selection: DOMSelection): Range | null {\n let newRange: Range | null = null;\n\n if (selection.type === 'table') {\n const table = selection.table;\n const elementToSelect =\n table.parentElement?.childElementCount == 1 ? table.parentElement : table;\n\n newRange = doc.createRange();\n newRange.selectNode(elementToSelect);\n } else if (selection.type === 'image') {\n newRange = doc.createRange();\n newRange.selectNode(selection.image);\n } else {\n newRange = selection.range;\n }\n\n return newRange;\n}\n"]}
@@ -13,6 +13,7 @@ export var announce = function (core, announceData) {
13
13
  var textToAnnounce = formatString(template || text, formatStrings);
14
14
  if (!core.lifecycle.announceContainer) {
15
15
  core.lifecycle.announceContainer = createAriaLiveElement(core.physicalRoot.ownerDocument);
16
+ core.domHelper.appendToRoot(core.lifecycle.announceContainer);
16
17
  }
17
18
  if (textToAnnounce && core.lifecycle.announceContainer) {
18
19
  var announceContainer = core.lifecycle.announceContainer;
@@ -1 +1 @@
1
- {"version":3,"file":"announce.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/announce/announce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAG1E,IAAM,UAAU,GAAG,GAAG,CAAC;AAEvB;;;;;GAKG;AACH,MAAM,CAAC,IAAM,QAAQ,GAAa,UAAC,IAAI,EAAE,YAAY;IACzC,IAAA,IAAI,GAAqE,YAAY,KAAjF,EAAE,cAAc,GAAqD,YAAY,eAAjE,EAAE,KAAmD,YAAY,cAA7C,EAAlB,aAAa,mBAAG,EAAE,KAAA,EAAE,KAA+B,YAAY,aAAjB,EAA1B,YAAY,mBAAG,WAAW,KAAA,CAAkB;IACtF,IAAA,qBAAqB,GAAK,IAAI,CAAC,SAAS,sBAAnB,CAAoB;IACjD,IAAM,QAAQ,GAAG,cAAc,KAAI,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAG,cAAc,CAAC,CAAA,CAAC;IAC3E,IAAI,cAAc,GAAG,YAAY,CAAC,QAAQ,IAAI,IAAI,EAAE,aAAa,CAAC,CAAC;IAEnE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE;QACnC,IAAI,CAAC,SAAS,CAAC,iBAAiB,GAAG,qBAAqB,CAAC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;KAC7F;IAED,IAAI,cAAc,IAAI,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE;QAC5C,IAAA,iBAAiB,GAAK,IAAI,CAAC,SAAS,kBAAnB,CAAoB;QAC7C,IAAI,iBAAiB,CAAC,QAAQ,IAAI,YAAY,EAAE;YAC5C,iBAAiB,CAAC,QAAQ,GAAG,YAAY,CAAC;SAC7C;QAED,IAAI,cAAc,IAAI,iBAAiB,CAAC,WAAW,EAAE;YACjD,cAAc,IAAI,UAAU,CAAC;SAChC;QAED,IAAI,iBAAiB,EAAE;YACnB,iBAAiB,CAAC,WAAW,GAAG,cAAc,CAAC;SAClD;KACJ;AACL,CAAC,CAAC;AAEF,SAAS,YAAY,CAAC,IAAwB,EAAE,aAAuB;IACnE,IAAI,IAAI,IAAI,SAAS,EAAE;QACnB,OAAO,IAAI,CAAC;KACf;IAED,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,UAAC,CAAC,EAAE,GAAW;QAC7C,IAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QACrC,OAAO,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AAChB,CAAC","sourcesContent":["import { createAriaLiveElement } from '../../utils/createAriaLiveElement';\nimport type { Announce } from 'roosterjs-content-model-types';\n\nconst DOT_STRING = '.';\n\n/**\n * @internal\n * Announce the given data\n * @param core The EditorCore object\n * @param announceData Data to announce\n */\nexport const announce: Announce = (core, announceData) => {\n const { text, defaultStrings, formatStrings = [], ariaLiveMode = 'assertive' } = announceData;\n const { announcerStringGetter } = core.lifecycle;\n const template = defaultStrings && announcerStringGetter?.(defaultStrings);\n let textToAnnounce = formatString(template || text, formatStrings);\n\n if (!core.lifecycle.announceContainer) {\n core.lifecycle.announceContainer = createAriaLiveElement(core.physicalRoot.ownerDocument);\n }\n\n if (textToAnnounce && core.lifecycle.announceContainer) {\n const { announceContainer } = core.lifecycle;\n if (announceContainer.ariaLive != ariaLiveMode) {\n announceContainer.ariaLive = ariaLiveMode;\n }\n\n if (textToAnnounce == announceContainer.textContent) {\n textToAnnounce += DOT_STRING;\n }\n\n if (announceContainer) {\n announceContainer.textContent = textToAnnounce;\n }\n }\n};\n\nfunction formatString(text: string | undefined, formatStrings: string[]) {\n if (text == undefined) {\n return text;\n }\n\n text = text.replace(/\\{(\\d+)\\}/g, (_, sub: string) => {\n const index = parseInt(sub);\n const replace = formatStrings[index];\n return replace ?? '';\n });\n\n return text;\n}\n"]}
1
+ {"version":3,"file":"announce.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/announce/announce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAG1E,IAAM,UAAU,GAAG,GAAG,CAAC;AAEvB;;;;;GAKG;AACH,MAAM,CAAC,IAAM,QAAQ,GAAa,UAAC,IAAI,EAAE,YAAY;IACzC,IAAA,IAAI,GAAqE,YAAY,KAAjF,EAAE,cAAc,GAAqD,YAAY,eAAjE,EAAE,KAAmD,YAAY,cAA7C,EAAlB,aAAa,mBAAG,EAAE,KAAA,EAAE,KAA+B,YAAY,aAAjB,EAA1B,YAAY,mBAAG,WAAW,KAAA,CAAkB;IACtF,IAAA,qBAAqB,GAAK,IAAI,CAAC,SAAS,sBAAnB,CAAoB;IACjD,IAAM,QAAQ,GAAG,cAAc,KAAI,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAG,cAAc,CAAC,CAAA,CAAC;IAC3E,IAAI,cAAc,GAAG,YAAY,CAAC,QAAQ,IAAI,IAAI,EAAE,aAAa,CAAC,CAAC;IAEnE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE;QACnC,IAAI,CAAC,SAAS,CAAC,iBAAiB,GAAG,qBAAqB,CAAC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAC1F,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;KACjE;IAED,IAAI,cAAc,IAAI,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE;QAC5C,IAAA,iBAAiB,GAAK,IAAI,CAAC,SAAS,kBAAnB,CAAoB;QAC7C,IAAI,iBAAiB,CAAC,QAAQ,IAAI,YAAY,EAAE;YAC5C,iBAAiB,CAAC,QAAQ,GAAG,YAAY,CAAC;SAC7C;QAED,IAAI,cAAc,IAAI,iBAAiB,CAAC,WAAW,EAAE;YACjD,cAAc,IAAI,UAAU,CAAC;SAChC;QAED,IAAI,iBAAiB,EAAE;YACnB,iBAAiB,CAAC,WAAW,GAAG,cAAc,CAAC;SAClD;KACJ;AACL,CAAC,CAAC;AAEF,SAAS,YAAY,CAAC,IAAwB,EAAE,aAAuB;IACnE,IAAI,IAAI,IAAI,SAAS,EAAE;QACnB,OAAO,IAAI,CAAC;KACf;IAED,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,UAAC,CAAC,EAAE,GAAW;QAC7C,IAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QACrC,OAAO,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AAChB,CAAC","sourcesContent":["import { createAriaLiveElement } from '../../utils/createAriaLiveElement';\nimport type { Announce } from 'roosterjs-content-model-types';\n\nconst DOT_STRING = '.';\n\n/**\n * @internal\n * Announce the given data\n * @param core The EditorCore object\n * @param announceData Data to announce\n */\nexport const announce: Announce = (core, announceData) => {\n const { text, defaultStrings, formatStrings = [], ariaLiveMode = 'assertive' } = announceData;\n const { announcerStringGetter } = core.lifecycle;\n const template = defaultStrings && announcerStringGetter?.(defaultStrings);\n let textToAnnounce = formatString(template || text, formatStrings);\n\n if (!core.lifecycle.announceContainer) {\n core.lifecycle.announceContainer = createAriaLiveElement(core.physicalRoot.ownerDocument);\n core.domHelper.appendToRoot(core.lifecycle.announceContainer);\n }\n\n if (textToAnnounce && core.lifecycle.announceContainer) {\n const { announceContainer } = core.lifecycle;\n if (announceContainer.ariaLive != ariaLiveMode) {\n announceContainer.ariaLive = ariaLiveMode;\n }\n\n if (textToAnnounce == announceContainer.textContent) {\n textToAnnounce += DOT_STRING;\n }\n\n if (announceContainer) {\n announceContainer.textContent = textToAnnounce;\n }\n }\n};\n\nfunction formatString(text: string | undefined, formatStrings: string[]) {\n if (text == undefined) {\n return text;\n }\n\n text = text.replace(/\\{(\\d+)\\}/g, (_, sub: string) => {\n const index = parseInt(sub);\n const replace = formatStrings[index];\n return replace ?? '';\n });\n\n return text;\n}\n"]}
@@ -31,6 +31,9 @@ export var createContentModel = function (core, option, selectionOverride) {
31
31
  var domToModelContext = option
32
32
  ? createDomToModelContext(editorContext, settings.builtIn, settings.customized, option)
33
33
  : createDomToModelContextWithConfig(settings.calculated, editorContext);
34
+ if (option === null || option === void 0 ? void 0 : option.skipFormatContainerFallbackCheck) {
35
+ domToModelContext.skipFormatContainerFallbackCheck = true;
36
+ }
34
37
  if (selection) {
35
38
  domToModelContext.selection = selection;
36
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createContentModel.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/createContentModel/createContentModel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,EACH,UAAU,EACV,uBAAuB,EACvB,iCAAiC,EACjC,iBAAiB,GACpB,MAAM,6BAA6B,CAAC;AAGrC;;;;;;GAMG;AACH,MAAM,CAAC,IAAM,kBAAkB,GAAuB,UAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB;;IAClF,6EAA6E;IAC7E,MAAA,IAAI,CAAC,KAAK,CAAC,oBAAoB,0CAAE,cAAc,EAAE,CAAC;IAClD,IAAM,eAAe,GACjB,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,OAAO,MAAM,CAAC,oBAAoB,KAAK,WAAW,CAAC,CAAC;IAE9F,IAAI,CAAC,iBAAiB,IAAI,eAAe,EAAE;QACvC,IAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;QAE3C,IAAI,WAAW,EAAE;YACb,6EAA6E;YAC7E,OAAO,IAAI,CAAC,SAAS,CAAC,kBAAkB;gBACpC,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC;gBACzD,CAAC,CAAC,WAAW,CAAC;SACrB;KACJ;IAED,IAAM,SAAS,GACX,iBAAiB,IAAI,MAAM;QACvB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,iBAAiB,IAAI,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;IAC3E,IAAM,SAAS,GAAG,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC;IAChD,IAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAEpE,aAAa,CAAC,oBAAoB,GAAG,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,oBAAoB,CAAC;IAElE,IAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC;IACrD,IAAM,iBAAiB,GAAG,MAAM;QAC5B,CAAC,CAAC,uBAAuB,CAAC,aAAa,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QACvF,CAAC,CAAC,iCAAiC,CAAC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAE5E,IAAI,SAAS,EAAE;QACX,iBAAiB,CAAC,SAAS,GAAG,SAAS,CAAC;KAC3C;IAED,IAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;IAErE,IAAI,SAAS,EAAE;QACX,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;KAC7C;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC","sourcesContent":["import { updateCache } from '../../corePlugin/cache/updateCache';\nimport {\n cloneModel,\n createDomToModelContext,\n createDomToModelContextWithConfig,\n domToContentModel,\n} from 'roosterjs-content-model-dom';\nimport type { CreateContentModel } from 'roosterjs-content-model-types';\n\n/**\n * @internal\n * Create Content Model from DOM tree in this editor\n * @param core The editor core object\n * @param option The option to customize the behavior of DOM to Content Model conversion\n * @param selectionOverride When passed, use this selection range instead of current selection in editor\n */\nexport const createContentModel: CreateContentModel = (core, option, selectionOverride) => {\n // Flush all mutations if any, so that we can get an up-to-date Content Model\n core.cache.textMutationObserver?.flushMutations();\n const tryGetFromCache =\n !option || (option.tryGetFromCache && typeof option.recalculateTableSize === 'undefined');\n\n if (!selectionOverride && tryGetFromCache) {\n const cachedModel = core.cache.cachedModel;\n\n if (cachedModel) {\n // When in shadow edit, use a cloned model so we won't pollute the cached one\n return core.lifecycle.shadowEditFragment\n ? cloneModel(cachedModel, { includeCachedElement: true })\n : cachedModel;\n }\n }\n\n const selection =\n selectionOverride == 'none'\n ? undefined\n : selectionOverride || core.api.getDOMSelection(core) || undefined;\n const saveIndex = !option && !selectionOverride;\n const editorContext = core.api.createEditorContext(core, saveIndex);\n\n editorContext.recalculateTableSize = option?.recalculateTableSize;\n\n const settings = core.environment.domToModelSettings;\n const domToModelContext = option\n ? createDomToModelContext(editorContext, settings.builtIn, settings.customized, option)\n : createDomToModelContextWithConfig(settings.calculated, editorContext);\n\n if (selection) {\n domToModelContext.selection = selection;\n }\n\n const model = domToContentModel(core.logicalRoot, domToModelContext);\n\n if (saveIndex) {\n updateCache(core.cache, model, selection);\n }\n\n return model;\n};\n"]}
1
+ {"version":3,"file":"createContentModel.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/createContentModel/createContentModel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,EACH,UAAU,EACV,uBAAuB,EACvB,iCAAiC,EACjC,iBAAiB,GACpB,MAAM,6BAA6B,CAAC;AAGrC;;;;;;GAMG;AACH,MAAM,CAAC,IAAM,kBAAkB,GAAuB,UAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB;;IAClF,6EAA6E;IAC7E,MAAA,IAAI,CAAC,KAAK,CAAC,oBAAoB,0CAAE,cAAc,EAAE,CAAC;IAClD,IAAM,eAAe,GACjB,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,OAAO,MAAM,CAAC,oBAAoB,KAAK,WAAW,CAAC,CAAC;IAE9F,IAAI,CAAC,iBAAiB,IAAI,eAAe,EAAE;QACvC,IAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;QAE3C,IAAI,WAAW,EAAE;YACb,6EAA6E;YAC7E,OAAO,IAAI,CAAC,SAAS,CAAC,kBAAkB;gBACpC,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC;gBACzD,CAAC,CAAC,WAAW,CAAC;SACrB;KACJ;IAED,IAAM,SAAS,GACX,iBAAiB,IAAI,MAAM;QACvB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,iBAAiB,IAAI,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;IAC3E,IAAM,SAAS,GAAG,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC;IAChD,IAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAEpE,aAAa,CAAC,oBAAoB,GAAG,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,oBAAoB,CAAC;IAElE,IAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC;IACrD,IAAM,iBAAiB,GAAG,MAAM;QAC5B,CAAC,CAAC,uBAAuB,CAAC,aAAa,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QACvF,CAAC,CAAC,iCAAiC,CAAC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAE5E,IAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,gCAAgC,EAAE;QAC1C,iBAAiB,CAAC,gCAAgC,GAAG,IAAI,CAAC;KAC7D;IAED,IAAI,SAAS,EAAE;QACX,iBAAiB,CAAC,SAAS,GAAG,SAAS,CAAC;KAC3C;IAED,IAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;IAErE,IAAI,SAAS,EAAE;QACX,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;KAC7C;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC","sourcesContent":["import { updateCache } from '../../corePlugin/cache/updateCache';\nimport {\n cloneModel,\n createDomToModelContext,\n createDomToModelContextWithConfig,\n domToContentModel,\n} from 'roosterjs-content-model-dom';\nimport type { CreateContentModel } from 'roosterjs-content-model-types';\n\n/**\n * @internal\n * Create Content Model from DOM tree in this editor\n * @param core The editor core object\n * @param option The option to customize the behavior of DOM to Content Model conversion\n * @param selectionOverride When passed, use this selection range instead of current selection in editor\n */\nexport const createContentModel: CreateContentModel = (core, option, selectionOverride) => {\n // Flush all mutations if any, so that we can get an up-to-date Content Model\n core.cache.textMutationObserver?.flushMutations();\n const tryGetFromCache =\n !option || (option.tryGetFromCache && typeof option.recalculateTableSize === 'undefined');\n\n if (!selectionOverride && tryGetFromCache) {\n const cachedModel = core.cache.cachedModel;\n\n if (cachedModel) {\n // When in shadow edit, use a cloned model so we won't pollute the cached one\n return core.lifecycle.shadowEditFragment\n ? cloneModel(cachedModel, { includeCachedElement: true })\n : cachedModel;\n }\n }\n\n const selection =\n selectionOverride == 'none'\n ? undefined\n : selectionOverride || core.api.getDOMSelection(core) || undefined;\n const saveIndex = !option && !selectionOverride;\n const editorContext = core.api.createEditorContext(core, saveIndex);\n\n editorContext.recalculateTableSize = option?.recalculateTableSize;\n\n const settings = core.environment.domToModelSettings;\n const domToModelContext = option\n ? createDomToModelContext(editorContext, settings.builtIn, settings.customized, option)\n : createDomToModelContextWithConfig(settings.calculated, editorContext);\n\n if (option?.skipFormatContainerFallbackCheck) {\n domToModelContext.skipFormatContainerFallbackCheck = true;\n }\n\n if (selection) {\n domToModelContext.selection = selection;\n }\n\n const model = domToContentModel(core.logicalRoot, domToModelContext);\n\n if (saveIndex) {\n updateCache(core.cache, model, selection);\n }\n\n return model;\n};\n"]}
@@ -14,15 +14,18 @@ export var getDOMSelection = function (core) {
14
14
  };
15
15
  function getNewSelection(core) {
16
16
  var _a;
17
+ var range = core.domHelper.getSelectionRange();
18
+ if (!range || !core.logicalRoot.contains(range.commonAncestorContainer)) {
19
+ return null;
20
+ }
17
21
  var selection = (_a = core.logicalRoot.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
18
- var range = selection && selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
19
- return selection && range && core.logicalRoot.contains(range.commonAncestorContainer)
20
- ? {
21
- type: 'range',
22
- range: range,
23
- isReverted: selection.focusNode != range.endContainer ||
24
- selection.focusOffset != range.endOffset,
25
- }
26
- : null;
22
+ var isReverted = selection
23
+ ? selection.focusNode != range.endContainer || selection.focusOffset != range.endOffset
24
+ : false;
25
+ return {
26
+ type: 'range',
27
+ range: range,
28
+ isReverted: isReverted,
29
+ };
27
30
  }
28
31
  //# sourceMappingURL=getDOMSelection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getDOMSelection.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/getDOMSelection/getDOMSelection.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,IAAM,eAAe,GAAoB,UAAA,IAAI;IAChD,IAAI,IAAI,CAAC,SAAS,CAAC,kBAAkB,EAAE;QACnC,OAAO,IAAI,CAAC;KACf;SAAM;QACH,IAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;QAE3C,OAAO,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YACzE,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;KAC/B;AACL,CAAC,CAAC;AAEF,SAAS,eAAe,CAAC,IAAgB;;IACrC,IAAM,SAAS,GAAG,MAAA,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,WAAW,0CAAE,YAAY,EAAE,CAAC;IAC7E,IAAM,KAAK,GAAG,SAAS,IAAI,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAErF,OAAO,SAAS,IAAI,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,uBAAuB,CAAC;QACjF,CAAC,CAAC;YACI,IAAI,EAAE,OAAO;YACb,KAAK,OAAA;YACL,UAAU,EACN,SAAS,CAAC,SAAS,IAAI,KAAK,CAAC,YAAY;gBACzC,SAAS,CAAC,WAAW,IAAI,KAAK,CAAC,SAAS;SAC/C;QACH,CAAC,CAAC,IAAI,CAAC;AACf,CAAC","sourcesContent":["import type { DOMSelection, GetDOMSelection, EditorCore } from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\nexport const getDOMSelection: GetDOMSelection = core => {\n if (core.lifecycle.shadowEditFragment) {\n return null;\n } else {\n const selection = core.selection.selection;\n\n return selection && (selection.type != 'range' || !core.domHelper.hasFocus())\n ? selection\n : getNewSelection(core);\n }\n};\n\nfunction getNewSelection(core: EditorCore): DOMSelection | null {\n const selection = core.logicalRoot.ownerDocument.defaultView?.getSelection();\n const range = selection && selection.rangeCount > 0 ? selection.getRangeAt(0) : null;\n\n return selection && range && core.logicalRoot.contains(range.commonAncestorContainer)\n ? {\n type: 'range',\n range,\n isReverted:\n selection.focusNode != range.endContainer ||\n selection.focusOffset != range.endOffset,\n }\n : null;\n}\n"]}
1
+ {"version":3,"file":"getDOMSelection.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/getDOMSelection/getDOMSelection.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,IAAM,eAAe,GAAoB,UAAA,IAAI;IAChD,IAAI,IAAI,CAAC,SAAS,CAAC,kBAAkB,EAAE;QACnC,OAAO,IAAI,CAAC;KACf;SAAM;QACH,IAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;QAE3C,OAAO,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YACzE,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;KAC/B;AACL,CAAC,CAAC;AAEF,SAAS,eAAe,CAAC,IAAgB;;IACrC,IAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC;IAEjD,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,uBAAuB,CAAC,EAAE;QACrE,OAAO,IAAI,CAAC;KACf;IAED,IAAM,SAAS,GAAG,MAAA,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,WAAW,0CAAE,YAAY,EAAE,CAAC;IAC7E,IAAM,UAAU,GAAG,SAAS;QACxB,CAAC,CAAC,SAAS,CAAC,SAAS,IAAI,KAAK,CAAC,YAAY,IAAI,SAAS,CAAC,WAAW,IAAI,KAAK,CAAC,SAAS;QACvF,CAAC,CAAC,KAAK,CAAC;IAEZ,OAAO;QACH,IAAI,EAAE,OAAO;QACb,KAAK,OAAA;QACL,UAAU,YAAA;KACb,CAAC;AACN,CAAC","sourcesContent":["import type { DOMSelection, GetDOMSelection, EditorCore } from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\nexport const getDOMSelection: GetDOMSelection = core => {\n if (core.lifecycle.shadowEditFragment) {\n return null;\n } else {\n const selection = core.selection.selection;\n\n return selection && (selection.type != 'range' || !core.domHelper.hasFocus())\n ? selection\n : getNewSelection(core);\n }\n};\n\nfunction getNewSelection(core: EditorCore): DOMSelection | null {\n const range = core.domHelper.getSelectionRange();\n\n if (!range || !core.logicalRoot.contains(range.commonAncestorContainer)) {\n return null;\n }\n\n const selection = core.logicalRoot.ownerDocument.defaultView?.getSelection();\n const isReverted = selection\n ? selection.focusNode != range.endContainer || selection.focusOffset != range.endOffset\n : false;\n\n return {\n type: 'range',\n range,\n isReverted,\n };\n}\n"]}
@@ -1,4 +1,3 @@
1
- import { addRangeToSelection } from './addRangeToSelection';
2
1
  import { areSameSelections } from '../../corePlugin/cache/areSameSelections';
3
2
  import { ensureUniqueId } from '../setEditorStyle/ensureUniqueId';
4
3
  import { findLastedCoInMergedCell } from './findLastedCoInMergedCell';
@@ -24,7 +23,6 @@ export var setDOMSelection = function (core, selection, skipSelectionChangedEven
24
23
  // We are applying a new selection, so we don't need to apply cached selection in DOMEventPlugin.
25
24
  // Set skipReselectOnFocus to skip this behavior
26
25
  var skipReselectOnFocus = core.selection.skipReselectOnFocus;
27
- var doc = core.physicalRoot.ownerDocument;
28
26
  var isDarkMode = core.lifecycle.isDarkMode;
29
27
  core.selection.skipReselectOnFocus = true;
30
28
  core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, null /*cssRule*/);
@@ -40,7 +38,7 @@ export var setDOMSelection = function (core, selection, skipSelectionChangedEven
40
38
  : core.selection.imageSelectionBorderColor;
41
39
  core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, "outline-style:solid!important; outline-color:" + (imageSelectionColor || DEFAULT_SELECTION_BORDER_COLOR) + "!important;", [getSafeIdSelector(ensureUniqueId(image, IMAGE_ID))]);
42
40
  core.api.setEditorStyle(core, HIDE_SELECTION_CSS_KEY, TRANSPARENT_SELECTION_CSS_RULE, [SELECTION_SELECTOR]);
43
- setRangeSelection(doc, image, false /* collapse */);
41
+ setRangeSelection(core, image, false /* collapse */);
44
42
  break;
45
43
  case 'table':
46
44
  var table = selection.table, firstColumn = selection.firstColumn, firstRow = selection.firstRow, lastColumn = selection.lastColumn, lastRow = selection.lastRow;
@@ -77,11 +75,11 @@ export var setDOMSelection = function (core, selection, skipSelectionChangedEven
77
75
  toggleCaret(core, true /* hide */);
78
76
  var nodeToSelect = ((_a = firstCell.cell) === null || _a === void 0 ? void 0 : _a.firstElementChild) || firstCell.cell;
79
77
  if (nodeToSelect) {
80
- setRangeSelection(doc, nodeToSelect || undefined, true /* collapse */);
78
+ setRangeSelection(core, nodeToSelect || undefined, true /* collapse */);
81
79
  }
82
80
  break;
83
81
  case 'range':
84
- addRangeToSelection(doc, selection.range, selection.isReverted);
82
+ core.domHelper.setSelectionRange(selection.range, selection.isReverted);
85
83
  core.selection.selection = core.domHelper.hasFocus() ? null : selection;
86
84
  break;
87
85
  default:
@@ -100,9 +98,10 @@ export var setDOMSelection = function (core, selection, skipSelectionChangedEven
100
98
  core.api.triggerEvent(core, eventData, true /*broadcast*/);
101
99
  }
102
100
  };
103
- function setRangeSelection(doc, element, collapse) {
101
+ function setRangeSelection(core, element, collapse) {
104
102
  var _a;
105
- if (element && doc.contains(element)) {
103
+ if (element && core.domHelper.isNodeInEditor(element)) {
104
+ var doc = core.physicalRoot.ownerDocument;
106
105
  var range = doc.createRange();
107
106
  var isReverted = undefined;
108
107
  range.selectNode(element);
@@ -118,7 +117,7 @@ function setRangeSelection(doc, element, collapse) {
118
117
  selection.focusOffset != range_1.endOffset;
119
118
  }
120
119
  }
121
- addRangeToSelection(doc, range, isReverted);
120
+ core.domHelper.setSelectionRange(range, isReverted);
122
121
  }
123
122
  }
124
123
  //# sourceMappingURL=setDOMSelection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setDOMSelection.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/setDOMSelection.ts"],"names":[],"mappings":"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","sourcesContent":["import { addRangeToSelection } from './addRangeToSelection';\nimport { areSameSelections } from '../../corePlugin/cache/areSameSelections';\nimport { ensureUniqueId } from '../setEditorStyle/ensureUniqueId';\nimport { findLastedCoInMergedCell } from './findLastedCoInMergedCell';\nimport { findTableCellElement } from './findTableCellElement';\nimport { getSafeIdSelector, parseTableCells } from 'roosterjs-content-model-dom';\nimport { setTableCellsStyle } from './setTableCellsStyle';\nimport { toggleCaret } from './toggleCaret';\nimport type { SelectionChangedEvent, SetDOMSelection } from 'roosterjs-content-model-types';\n\nconst DOM_SELECTION_CSS_KEY = '_DOMSelection';\nconst HIDE_SELECTION_CSS_KEY = '_DOMSelectionHideSelection';\nconst IMAGE_ID = 'image';\nconst TRANSPARENT_SELECTION_CSS_RULE = 'background-color: transparent !important;';\nconst SELECTION_SELECTOR = '*::selection';\nconst DEFAULT_SELECTION_BORDER_COLOR = '#DB626C';\n\n/**\n * @internal\n */\nexport const setDOMSelection: SetDOMSelection = (core, selection, skipSelectionChangedEvent) => {\n const existingSelection = core.api.getDOMSelection(core);\n\n if (existingSelection && selection && areSameSelections(existingSelection, selection)) {\n return;\n }\n\n // We are applying a new selection, so we don't need to apply cached selection in DOMEventPlugin.\n // Set skipReselectOnFocus to skip this behavior\n const skipReselectOnFocus = core.selection.skipReselectOnFocus;\n\n const doc = core.physicalRoot.ownerDocument;\n const isDarkMode = core.lifecycle.isDarkMode;\n core.selection.skipReselectOnFocus = true;\n core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, null /*cssRule*/);\n core.api.setEditorStyle(core, HIDE_SELECTION_CSS_KEY, null /*cssRule*/);\n\n toggleCaret(core, false /* hide */);\n\n try {\n switch (selection?.type) {\n case 'image':\n const image = selection.image;\n\n core.selection.selection = selection;\n\n const imageSelectionColor = isDarkMode\n ? core.selection.imageSelectionBorderColorDark\n : core.selection.imageSelectionBorderColor;\n\n core.api.setEditorStyle(\n core,\n DOM_SELECTION_CSS_KEY,\n `outline-style:solid!important; outline-color:${\n imageSelectionColor || DEFAULT_SELECTION_BORDER_COLOR\n }!important;`,\n [getSafeIdSelector(ensureUniqueId(image, IMAGE_ID))]\n );\n core.api.setEditorStyle(\n core,\n HIDE_SELECTION_CSS_KEY,\n TRANSPARENT_SELECTION_CSS_RULE,\n [SELECTION_SELECTOR]\n );\n\n setRangeSelection(doc, image, false /* collapse */);\n break;\n case 'table':\n const { table, firstColumn, firstRow, lastColumn, lastRow } = selection;\n const parsedTable = parseTableCells(selection.table);\n let firstCell = {\n row: Math.min(firstRow, lastRow),\n col: Math.min(firstColumn, lastColumn),\n cell: <HTMLTableCellElement | null>null,\n };\n let lastCell = {\n row: Math.max(firstRow, lastRow),\n col: Math.max(firstColumn, lastColumn),\n };\n\n firstCell = findTableCellElement(parsedTable, firstCell) || firstCell;\n lastCell = findLastedCoInMergedCell(parsedTable, lastCell) || lastCell;\n\n if (\n isNaN(firstCell.row) ||\n isNaN(firstCell.col) ||\n isNaN(lastCell.row) ||\n isNaN(lastCell.col)\n ) {\n return;\n }\n\n selection = {\n type: 'table',\n table,\n firstRow: firstCell.row,\n firstColumn: firstCell.col,\n lastRow: lastCell.row,\n lastColumn: lastCell.col,\n tableSelectionInfo: selection.tableSelectionInfo,\n };\n\n core.selection.selection = selection;\n\n setTableCellsStyle(core, table, parsedTable, firstCell, lastCell);\n core.api.setEditorStyle(\n core,\n HIDE_SELECTION_CSS_KEY,\n TRANSPARENT_SELECTION_CSS_RULE,\n [SELECTION_SELECTOR]\n );\n\n toggleCaret(core, true /* hide */);\n\n const nodeToSelect = firstCell.cell?.firstElementChild || firstCell.cell;\n\n if (nodeToSelect) {\n setRangeSelection(\n doc,\n (nodeToSelect as HTMLElement) || undefined,\n true /* collapse */\n );\n }\n\n break;\n case 'range':\n addRangeToSelection(doc, selection.range, selection.isReverted);\n\n core.selection.selection = core.domHelper.hasFocus() ? null : selection;\n break;\n\n default:\n core.selection.selection = null;\n break;\n }\n } finally {\n core.selection.skipReselectOnFocus = skipReselectOnFocus;\n }\n\n if (!skipSelectionChangedEvent) {\n const eventData: SelectionChangedEvent = {\n eventType: 'selectionChanged',\n newSelection: selection,\n };\n\n core.api.triggerEvent(core, eventData, true /*broadcast*/);\n }\n};\n\nfunction setRangeSelection(doc: Document, element: HTMLElement | undefined, collapse: boolean) {\n if (element && doc.contains(element)) {\n const range = doc.createRange();\n let isReverted: boolean | undefined = undefined;\n\n range.selectNode(element);\n if (collapse) {\n range.collapse();\n } else {\n const selection = doc.defaultView?.getSelection();\n const range = selection && selection.rangeCount > 0 && selection.getRangeAt(0);\n if (selection && range) {\n isReverted =\n selection.focusNode != range.endContainer ||\n selection.focusOffset != range.endOffset;\n }\n }\n\n addRangeToSelection(doc, range, isReverted);\n }\n}\n"]}
1
+ {"version":3,"file":"setDOMSelection.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/setDOMSelection.ts"],"names":[],"mappings":"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","sourcesContent":["import { areSameSelections } from '../../corePlugin/cache/areSameSelections';\nimport { ensureUniqueId } from '../setEditorStyle/ensureUniqueId';\nimport { findLastedCoInMergedCell } from './findLastedCoInMergedCell';\nimport { findTableCellElement } from './findTableCellElement';\nimport { getSafeIdSelector, parseTableCells } from 'roosterjs-content-model-dom';\nimport { setTableCellsStyle } from './setTableCellsStyle';\nimport { toggleCaret } from './toggleCaret';\nimport type {\n EditorCore,\n SelectionChangedEvent,\n SetDOMSelection,\n} from 'roosterjs-content-model-types';\n\nconst DOM_SELECTION_CSS_KEY = '_DOMSelection';\nconst HIDE_SELECTION_CSS_KEY = '_DOMSelectionHideSelection';\nconst IMAGE_ID = 'image';\nconst TRANSPARENT_SELECTION_CSS_RULE = 'background-color: transparent !important;';\nconst SELECTION_SELECTOR = '*::selection';\nconst DEFAULT_SELECTION_BORDER_COLOR = '#DB626C';\n\n/**\n * @internal\n */\nexport const setDOMSelection: SetDOMSelection = (core, selection, skipSelectionChangedEvent) => {\n const existingSelection = core.api.getDOMSelection(core);\n\n if (existingSelection && selection && areSameSelections(existingSelection, selection)) {\n return;\n }\n\n // We are applying a new selection, so we don't need to apply cached selection in DOMEventPlugin.\n // Set skipReselectOnFocus to skip this behavior\n const skipReselectOnFocus = core.selection.skipReselectOnFocus;\n\n const isDarkMode = core.lifecycle.isDarkMode;\n core.selection.skipReselectOnFocus = true;\n core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, null /*cssRule*/);\n core.api.setEditorStyle(core, HIDE_SELECTION_CSS_KEY, null /*cssRule*/);\n\n toggleCaret(core, false /* hide */);\n\n try {\n switch (selection?.type) {\n case 'image':\n const image = selection.image;\n\n core.selection.selection = selection;\n\n const imageSelectionColor = isDarkMode\n ? core.selection.imageSelectionBorderColorDark\n : core.selection.imageSelectionBorderColor;\n\n core.api.setEditorStyle(\n core,\n DOM_SELECTION_CSS_KEY,\n `outline-style:solid!important; outline-color:${\n imageSelectionColor || DEFAULT_SELECTION_BORDER_COLOR\n }!important;`,\n [getSafeIdSelector(ensureUniqueId(image, IMAGE_ID))]\n );\n core.api.setEditorStyle(\n core,\n HIDE_SELECTION_CSS_KEY,\n TRANSPARENT_SELECTION_CSS_RULE,\n [SELECTION_SELECTOR]\n );\n\n setRangeSelection(core, image, false /* collapse */);\n break;\n case 'table':\n const { table, firstColumn, firstRow, lastColumn, lastRow } = selection;\n const parsedTable = parseTableCells(selection.table);\n let firstCell = {\n row: Math.min(firstRow, lastRow),\n col: Math.min(firstColumn, lastColumn),\n cell: <HTMLTableCellElement | null>null,\n };\n let lastCell = {\n row: Math.max(firstRow, lastRow),\n col: Math.max(firstColumn, lastColumn),\n };\n\n firstCell = findTableCellElement(parsedTable, firstCell) || firstCell;\n lastCell = findLastedCoInMergedCell(parsedTable, lastCell) || lastCell;\n\n if (\n isNaN(firstCell.row) ||\n isNaN(firstCell.col) ||\n isNaN(lastCell.row) ||\n isNaN(lastCell.col)\n ) {\n return;\n }\n\n selection = {\n type: 'table',\n table,\n firstRow: firstCell.row,\n firstColumn: firstCell.col,\n lastRow: lastCell.row,\n lastColumn: lastCell.col,\n tableSelectionInfo: selection.tableSelectionInfo,\n };\n\n core.selection.selection = selection;\n\n setTableCellsStyle(core, table, parsedTable, firstCell, lastCell);\n core.api.setEditorStyle(\n core,\n HIDE_SELECTION_CSS_KEY,\n TRANSPARENT_SELECTION_CSS_RULE,\n [SELECTION_SELECTOR]\n );\n\n toggleCaret(core, true /* hide */);\n\n const nodeToSelect = firstCell.cell?.firstElementChild || firstCell.cell;\n\n if (nodeToSelect) {\n setRangeSelection(\n core,\n (nodeToSelect as HTMLElement) || undefined,\n true /* collapse */\n );\n }\n\n break;\n case 'range':\n core.domHelper.setSelectionRange(selection.range, selection.isReverted);\n\n core.selection.selection = core.domHelper.hasFocus() ? null : selection;\n break;\n\n default:\n core.selection.selection = null;\n break;\n }\n } finally {\n core.selection.skipReselectOnFocus = skipReselectOnFocus;\n }\n\n if (!skipSelectionChangedEvent) {\n const eventData: SelectionChangedEvent = {\n eventType: 'selectionChanged',\n newSelection: selection,\n };\n\n core.api.triggerEvent(core, eventData, true /*broadcast*/);\n }\n};\n\nfunction setRangeSelection(core: EditorCore, element: HTMLElement | undefined, collapse: boolean) {\n if (element && core.domHelper.isNodeInEditor(element)) {\n const doc = core.physicalRoot.ownerDocument;\n const range = doc.createRange();\n let isReverted: boolean | undefined = undefined;\n\n range.selectNode(element);\n if (collapse) {\n range.collapse();\n } else {\n const selection = doc.defaultView?.getSelection();\n const range = selection && selection.rangeCount > 0 && selection.getRangeAt(0);\n if (selection && range) {\n isReverted =\n selection.focusNode != range.endContainer ||\n selection.focusOffset != range.endOffset;\n }\n }\n\n core.domHelper.setSelectionRange(range, isReverted);\n }\n}\n"]}
@@ -4,9 +4,9 @@ import { getSafeIdSelector } from 'roosterjs-content-model-dom';
4
4
  */
5
5
  export function ensureUniqueId(element, idPrefix) {
6
6
  idPrefix = element.id || idPrefix;
7
- var doc = element.ownerDocument;
7
+ var root = element.getRootNode();
8
8
  var i = 0;
9
- while (!element.id || doc.querySelectorAll(getSafeIdSelector(element.id)).length > 1) {
9
+ while (!element.id || root.querySelectorAll(getSafeIdSelector(element.id)).length > 1) {
10
10
  element.id = idPrefix + '_' + i++;
11
11
  }
12
12
  return element.id;
@@ -1 +1 @@
1
- {"version":3,"file":"ensureUniqueId.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/setEditorStyle/ensureUniqueId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAoB,EAAE,QAAgB;IACjE,QAAQ,GAAG,OAAO,CAAC,EAAE,IAAI,QAAQ,CAAC;IAElC,IAAM,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC;IAClC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,GAAG,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;QAClF,OAAO,CAAC,EAAE,GAAG,QAAQ,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC;KACrC;IAED,OAAO,OAAO,CAAC,EAAE,CAAC;AACtB,CAAC","sourcesContent":["import { getSafeIdSelector } from 'roosterjs-content-model-dom';\n\n/**\n * @internal\n */\nexport function ensureUniqueId(element: HTMLElement, idPrefix: string): string {\n idPrefix = element.id || idPrefix;\n\n const doc = element.ownerDocument;\n let i = 0;\n\n while (!element.id || doc.querySelectorAll(getSafeIdSelector(element.id)).length > 1) {\n element.id = idPrefix + '_' + i++;\n }\n\n return element.id;\n}\n"]}
1
+ {"version":3,"file":"ensureUniqueId.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/setEditorStyle/ensureUniqueId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAoB,EAAE,QAAgB;IACjE,QAAQ,GAAG,OAAO,CAAC,EAAE,IAAI,QAAQ,CAAC;IAElC,IAAM,IAAI,GAAG,OAAO,CAAC,WAAW,EAA2B,CAAC;IAC5D,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;QACnF,OAAO,CAAC,EAAE,GAAG,QAAQ,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC;KACrC;IAED,OAAO,OAAO,CAAC,EAAE,CAAC;AACtB,CAAC","sourcesContent":["import { getSafeIdSelector } from 'roosterjs-content-model-dom';\n\n/**\n * @internal\n */\nexport function ensureUniqueId(element: HTMLElement, idPrefix: string): string {\n idPrefix = element.id || idPrefix;\n\n const root = element.getRootNode() as Document | ShadowRoot;\n let i = 0;\n\n while (!element.id || root.querySelectorAll(getSafeIdSelector(element.id)).length > 1) {\n element.id = idPrefix + '_' + i++;\n }\n\n return element.id;\n}\n"]}
@@ -11,7 +11,7 @@ export var setEditorStyle = function (core, key, cssRule, subSelectors, maxRuleL
11
11
  if (!styleElement && cssRule) {
12
12
  var doc = core.physicalRoot.ownerDocument;
13
13
  styleElement = doc.createElement('style');
14
- doc.head.appendChild(styleElement);
14
+ core.domHelper.appendToRoot(styleElement);
15
15
  styleElement.dataset.roosterjsStyleKey = key;
16
16
  core.lifecycle.styleElements[key] = styleElement;
17
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"setEditorStyle.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/setEditorStyle/setEditorStyle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGhE,IAAM,wBAAwB,GAAG,IAAI,CAAC;AACtC,IAAM,cAAc,GAAG,YAAY,CAAC;AAEpC;;GAEG;AACH,MAAM,CAAC,IAAM,cAAc,GAAmB,UAC1C,IAAI,EACJ,GAAG,EACH,OAAO,EACP,YAAY,EACZ,aAAwC;IAAxC,8BAAA,EAAA,wCAAwC;IAExC,IAAI,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAErD,IAAI,CAAC,YAAY,IAAI,OAAO,EAAE;QAC1B,IAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC;QAE5C,YAAY,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC1C,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;QAEnC,YAAY,CAAC,OAAO,CAAC,iBAAiB,GAAG,GAAG,CAAC;QAC7C,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;KACpD;IAED,IAAM,KAAK,GAAG,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,KAAK,CAAC;IAElC,IAAI,KAAK,EAAE;QACP,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;YACjD,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;SACvB;QAED,IAAI,OAAO,EAAE;YACT,IAAM,YAAY,GAAG,iBAAiB,CAClC,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CACpD,CAAC;YACF,IAAM,SAAS,GAAG,CAAC,YAAY;gBAC3B,CAAC,CAAC,CAAC,YAAY,CAAC;gBAChB,CAAC,CAAC,OAAO,YAAY,KAAK,QAAQ;oBAClC,CAAC,CAAC,CAAI,YAAY,UAAK,YAAc,CAAC;oBACtC,CAAC,CAAC,cAAc,CACV,YAAY,EACZ,YAAY,EACZ,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,oBAAoB;qBAC1D,CAAC;YAER,SAAS,CAAC,OAAO,CAAC,UAAA,QAAQ;gBACtB,KAAK,CAAC,UAAU,CAAI,QAAQ,UAAK,OAAO,MAAG,CAAC,CAAC;YACjD,CAAC,CAAC,CAAC;SACN;KACJ;AACL,CAAC,CAAC;AAEF,SAAS,cAAc,CAAC,YAAoB,EAAE,YAAsB,EAAE,MAAc;IAChF,IAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,aAAa,GAAa,EAAE,CAAC;IACjC,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,YAAY,CAAC,OAAO,CAAC,UAAA,WAAW;QAC5B,IAAI,GAAG,IAAI,MAAM,EAAE;YACf,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACrC,aAAa,GAAG,EAAE,CAAC;YACnB,GAAG,GAAG,CAAC,CAAC;SACX;QAED,IAAM,QAAQ,GAAM,YAAY,SAAI,WAAa,CAAC;QAElD,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,4CAA4C;QACxE,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAErC,OAAO,MAAM,CAAC;AAClB,CAAC","sourcesContent":["import { ensureUniqueId } from './ensureUniqueId';\nimport { getSafeIdSelector } from 'roosterjs-content-model-dom';\nimport type { SetEditorStyle } from 'roosterjs-content-model-types';\n\nconst MAX_RULE_SELECTOR_LENGTH = 9000;\nconst CONTENT_DIV_ID = 'contentDiv';\n\n/**\n * @internal\n */\nexport const setEditorStyle: SetEditorStyle = (\n core,\n key,\n cssRule,\n subSelectors,\n maxRuleLength = MAX_RULE_SELECTOR_LENGTH\n) => {\n let styleElement = core.lifecycle.styleElements[key];\n\n if (!styleElement && cssRule) {\n const doc = core.physicalRoot.ownerDocument;\n\n styleElement = doc.createElement('style');\n doc.head.appendChild(styleElement);\n\n styleElement.dataset.roosterjsStyleKey = key;\n core.lifecycle.styleElements[key] = styleElement;\n }\n\n const sheet = styleElement?.sheet;\n\n if (sheet) {\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n sheet.deleteRule(i);\n }\n\n if (cssRule) {\n const rootSelector = getSafeIdSelector(\n ensureUniqueId(core.physicalRoot, CONTENT_DIV_ID)\n );\n const selectors = !subSelectors\n ? [rootSelector]\n : typeof subSelectors === 'string'\n ? [`${rootSelector}::${subSelectors}`]\n : buildSelectors(\n rootSelector,\n subSelectors,\n maxRuleLength - cssRule.length - 3 // minus 3 for \" {}\"\n );\n\n selectors.forEach(selector => {\n sheet.insertRule(`${selector} {${cssRule}}`);\n });\n }\n }\n};\n\nfunction buildSelectors(rootSelector: string, subSelectors: string[], maxLen: number): string[] {\n const result: string[] = [];\n\n let stringBuilder: string[] = [];\n let len = 0;\n\n subSelectors.forEach(subSelector => {\n if (len >= maxLen) {\n result.push(stringBuilder.join(','));\n stringBuilder = [];\n len = 0;\n }\n\n const selector = `${rootSelector} ${subSelector}`;\n\n len += selector.length + 1; // Add 1 for potential \",\" between selectors\n stringBuilder.push(selector);\n });\n\n result.push(stringBuilder.join(','));\n\n return result;\n}\n"]}
1
+ {"version":3,"file":"setEditorStyle.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/coreApi/setEditorStyle/setEditorStyle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGhE,IAAM,wBAAwB,GAAG,IAAI,CAAC;AACtC,IAAM,cAAc,GAAG,YAAY,CAAC;AAEpC;;GAEG;AACH,MAAM,CAAC,IAAM,cAAc,GAAmB,UAC1C,IAAI,EACJ,GAAG,EACH,OAAO,EACP,YAAY,EACZ,aAAwC;IAAxC,8BAAA,EAAA,wCAAwC;IAExC,IAAI,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAErD,IAAI,CAAC,YAAY,IAAI,OAAO,EAAE;QAC1B,IAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC;QAE5C,YAAY,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QAE1C,YAAY,CAAC,OAAO,CAAC,iBAAiB,GAAG,GAAG,CAAC;QAC7C,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;KACpD;IAED,IAAM,KAAK,GAAG,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,KAAK,CAAC;IAElC,IAAI,KAAK,EAAE;QACP,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;YACjD,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;SACvB;QAED,IAAI,OAAO,EAAE;YACT,IAAM,YAAY,GAAG,iBAAiB,CAClC,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CACpD,CAAC;YACF,IAAM,SAAS,GAAG,CAAC,YAAY;gBAC3B,CAAC,CAAC,CAAC,YAAY,CAAC;gBAChB,CAAC,CAAC,OAAO,YAAY,KAAK,QAAQ;oBAClC,CAAC,CAAC,CAAI,YAAY,UAAK,YAAc,CAAC;oBACtC,CAAC,CAAC,cAAc,CACV,YAAY,EACZ,YAAY,EACZ,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,oBAAoB;qBAC1D,CAAC;YAER,SAAS,CAAC,OAAO,CAAC,UAAA,QAAQ;gBACtB,KAAK,CAAC,UAAU,CAAI,QAAQ,UAAK,OAAO,MAAG,CAAC,CAAC;YACjD,CAAC,CAAC,CAAC;SACN;KACJ;AACL,CAAC,CAAC;AAEF,SAAS,cAAc,CAAC,YAAoB,EAAE,YAAsB,EAAE,MAAc;IAChF,IAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,aAAa,GAAa,EAAE,CAAC;IACjC,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,YAAY,CAAC,OAAO,CAAC,UAAA,WAAW;QAC5B,IAAI,GAAG,IAAI,MAAM,EAAE;YACf,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACrC,aAAa,GAAG,EAAE,CAAC;YACnB,GAAG,GAAG,CAAC,CAAC;SACX;QAED,IAAM,QAAQ,GAAM,YAAY,SAAI,WAAa,CAAC;QAElD,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,4CAA4C;QACxE,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAErC,OAAO,MAAM,CAAC;AAClB,CAAC","sourcesContent":["import { ensureUniqueId } from './ensureUniqueId';\nimport { getSafeIdSelector } from 'roosterjs-content-model-dom';\nimport type { SetEditorStyle } from 'roosterjs-content-model-types';\n\nconst MAX_RULE_SELECTOR_LENGTH = 9000;\nconst CONTENT_DIV_ID = 'contentDiv';\n\n/**\n * @internal\n */\nexport const setEditorStyle: SetEditorStyle = (\n core,\n key,\n cssRule,\n subSelectors,\n maxRuleLength = MAX_RULE_SELECTOR_LENGTH\n) => {\n let styleElement = core.lifecycle.styleElements[key];\n\n if (!styleElement && cssRule) {\n const doc = core.physicalRoot.ownerDocument;\n\n styleElement = doc.createElement('style');\n core.domHelper.appendToRoot(styleElement);\n\n styleElement.dataset.roosterjsStyleKey = key;\n core.lifecycle.styleElements[key] = styleElement;\n }\n\n const sheet = styleElement?.sheet;\n\n if (sheet) {\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n sheet.deleteRule(i);\n }\n\n if (cssRule) {\n const rootSelector = getSafeIdSelector(\n ensureUniqueId(core.physicalRoot, CONTENT_DIV_ID)\n );\n const selectors = !subSelectors\n ? [rootSelector]\n : typeof subSelectors === 'string'\n ? [`${rootSelector}::${subSelectors}`]\n : buildSelectors(\n rootSelector,\n subSelectors,\n maxRuleLength - cssRule.length - 3 // minus 3 for \" {}\"\n );\n\n selectors.forEach(selector => {\n sheet.insertRule(`${selector} {${cssRule}}`);\n });\n }\n }\n};\n\nfunction buildSelectors(rootSelector: string, subSelectors: string[], maxLen: number): string[] {\n const result: string[] = [];\n\n let stringBuilder: string[] = [];\n let len = 0;\n\n subSelectors.forEach(subSelector => {\n if (len >= maxLen) {\n result.push(stringBuilder.join(','));\n stringBuilder = [];\n len = 0;\n }\n\n const selector = `${rootSelector} ${subSelector}`;\n\n len += selector.length + 1; // Add 1 for potential \",\" between selectors\n stringBuilder.push(selector);\n });\n\n result.push(stringBuilder.join(','));\n\n return result;\n}\n"]}
@@ -32,6 +32,11 @@ var CachePlugin = /** @class */ (function () {
32
32
  _this.invalidateCache();
33
33
  }
34
34
  break;
35
+ case 'attribute':
36
+ if (!_this.state.domIndexer.reconcileImageAttribute(mutation.element, mutation.attributeName)) {
37
+ _this.invalidateCache();
38
+ }
39
+ break;
35
40
  case 'unknown':
36
41
  _this.invalidateCache();
37
42
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"CachePlugin.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/corePlugin/cache/CachePlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { areSameSelections } from './areSameSelections';\nimport { createParagraphMap } from './ParagraphMapImpl';\nimport { createTextMutationObserver } from './textMutationObserver';\nimport { DomIndexerImpl } from './domIndexerImpl';\nimport { updateCache } from './updateCache';\nimport type { Mutation } from './MutationType';\nimport type {\n CachePluginState,\n IEditor,\n PluginEvent,\n PluginWithState,\n EditorOptions,\n} from 'roosterjs-content-model-types';\n\n/**\n * ContentModel cache plugin manages cached Content Model, and refresh the cache when necessary\n */\nclass CachePlugin implements PluginWithState<CachePluginState> {\n private editor: IEditor | null = null;\n private state: CachePluginState;\n\n /**\n * Construct a new instance of CachePlugin class\n * @param option The editor option\n * @param contentDiv The editor content DIV\n */\n constructor(option: EditorOptions, contentDiv: HTMLDivElement) {\n this.state = {\n domIndexer: new DomIndexerImpl(\n option.experimentalFeatures &&\n option.experimentalFeatures.indexOf(\n 'KeepSelectionMarkerWhenEnteringTextNode'\n ) >= 0\n ),\n textMutationObserver: createTextMutationObserver(contentDiv, this.onMutation),\n };\n\n if (option.enableParagraphMap) {\n this.state.paragraphMap = createParagraphMap();\n }\n }\n\n /**\n * Get name of this plugin\n */\n getName() {\n return 'Cache';\n }\n\n /**\n * The first method that editor will call to a plugin when editor is initializing.\n * It will pass in the editor instance, plugin should take this chance to save the\n * editor reference so that it can call to any editor method or format API later.\n * @param editor The editor object\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.editor.getDocument().addEventListener('selectionchange', this.onNativeSelectionChange);\n\n this.state.textMutationObserver.startObserving();\n }\n\n /**\n * The last method that editor will call to a plugin before it is disposed.\n * Plugin can take this chance to clear the reference to editor. After this method is\n * called, plugin should not call to any editor method since it will result in error.\n */\n dispose() {\n this.state.textMutationObserver.stopObserving();\n\n if (this.editor) {\n this.editor\n .getDocument()\n .removeEventListener('selectionchange', this.onNativeSelectionChange);\n this.editor = null;\n }\n }\n\n /**\n * Get plugin state object\n */\n getState(): CachePluginState {\n return this.state;\n }\n\n /**\n * Core method for a plugin. Once an event happens in editor, editor will call this\n * method of each plugin to handle the event as long as the event is not handled\n * exclusively by another plugin.\n * @param event The event to handle:\n */\n onPluginEvent(event: PluginEvent) {\n if (!this.editor) {\n return;\n }\n\n switch (event.eventType) {\n case 'logicalRootChanged':\n this.invalidateCache();\n\n this.state.textMutationObserver.stopObserving();\n this.state.textMutationObserver = createTextMutationObserver(\n event.logicalRoot,\n this.onMutation\n );\n this.state.textMutationObserver.startObserving();\n break;\n\n case 'selectionChanged':\n this.updateCachedModel(this.editor);\n break;\n\n case 'contentChanged':\n const { contentModel, selection } = event;\n\n if (contentModel) {\n updateCache(this.state, contentModel, selection);\n }\n\n break;\n }\n }\n\n private onMutation = (mutation: Mutation) => {\n if (this.editor) {\n switch (mutation.type) {\n case 'childList':\n if (\n !this.state.domIndexer.reconcileChildList(\n mutation.addedNodes,\n mutation.removedNodes\n )\n ) {\n this.invalidateCache();\n }\n break;\n\n case 'text':\n this.updateCachedModel(this.editor, true /*forceUpdate*/);\n break;\n\n case 'elementId':\n const element = mutation.element;\n\n if (!this.state.domIndexer.reconcileElementId(element)) {\n this.invalidateCache();\n }\n\n break;\n\n case 'unknown':\n this.invalidateCache();\n break;\n }\n }\n };\n\n private onNativeSelectionChange = () => {\n if (this.editor?.hasFocus()) {\n this.updateCachedModel(this.editor);\n }\n };\n\n private invalidateCache() {\n if (!this.editor?.isInShadowEdit()) {\n if (this.state.cachedModel) {\n this.state.cachedModel = undefined;\n }\n\n if (this.state.cachedSelection) {\n this.state.cachedSelection = undefined;\n }\n\n // Clear paragraph indexer to prevent stale references to old paragraphs\n // It will be rebuild next time when we create a new Content Model\n this.state.paragraphMap?.clear();\n }\n }\n\n private updateCachedModel(editor: IEditor, forceUpdate?: boolean) {\n if (editor.isInShadowEdit()) {\n return;\n }\n\n const cachedSelection = this.state.cachedSelection;\n this.state.cachedSelection = undefined; // Clear it to force getDOMSelection() retrieve the latest selection range\n\n const newRangeEx = editor.getDOMSelection() || undefined;\n const model = this.state.cachedModel;\n const isSelectionChanged =\n forceUpdate ||\n !cachedSelection ||\n !newRangeEx ||\n !areSameSelections(newRangeEx, cachedSelection);\n\n if (isSelectionChanged) {\n if (\n !model ||\n !newRangeEx ||\n !this.state.domIndexer.reconcileSelection(model, newRangeEx, cachedSelection)\n ) {\n this.invalidateCache();\n } else {\n updateCache(this.state, model, newRangeEx);\n }\n } else {\n this.state.cachedSelection = cachedSelection;\n }\n }\n}\n\n/**\n * @internal\n * Create a new instance of CachePlugin class.\n * @param option The editor option\n * @param contentDiv The editor content DIV\n */\nexport function createCachePlugin(\n option: EditorOptions,\n contentDiv: HTMLDivElement\n): PluginWithState<CachePluginState> {\n return new CachePlugin(option, contentDiv);\n}\n"]}
1
+ {"version":3,"file":"CachePlugin.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/corePlugin/cache/CachePlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { areSameSelections } from './areSameSelections';\nimport { createParagraphMap } from './ParagraphMapImpl';\nimport { createTextMutationObserver } from './textMutationObserver';\nimport { DomIndexerImpl } from './domIndexerImpl';\nimport { updateCache } from './updateCache';\nimport type { Mutation } from './MutationType';\nimport type {\n CachePluginState,\n IEditor,\n PluginEvent,\n PluginWithState,\n EditorOptions,\n} from 'roosterjs-content-model-types';\n\n/**\n * ContentModel cache plugin manages cached Content Model, and refresh the cache when necessary\n */\nclass CachePlugin implements PluginWithState<CachePluginState> {\n private editor: IEditor | null = null;\n private state: CachePluginState;\n\n /**\n * Construct a new instance of CachePlugin class\n * @param option The editor option\n * @param contentDiv The editor content DIV\n */\n constructor(option: EditorOptions, contentDiv: HTMLDivElement) {\n this.state = {\n domIndexer: new DomIndexerImpl(\n option.experimentalFeatures &&\n option.experimentalFeatures.indexOf(\n 'KeepSelectionMarkerWhenEnteringTextNode'\n ) >= 0\n ),\n textMutationObserver: createTextMutationObserver(contentDiv, this.onMutation),\n };\n\n if (option.enableParagraphMap) {\n this.state.paragraphMap = createParagraphMap();\n }\n }\n\n /**\n * Get name of this plugin\n */\n getName() {\n return 'Cache';\n }\n\n /**\n * The first method that editor will call to a plugin when editor is initializing.\n * It will pass in the editor instance, plugin should take this chance to save the\n * editor reference so that it can call to any editor method or format API later.\n * @param editor The editor object\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.editor.getDocument().addEventListener('selectionchange', this.onNativeSelectionChange);\n\n this.state.textMutationObserver.startObserving();\n }\n\n /**\n * The last method that editor will call to a plugin before it is disposed.\n * Plugin can take this chance to clear the reference to editor. After this method is\n * called, plugin should not call to any editor method since it will result in error.\n */\n dispose() {\n this.state.textMutationObserver.stopObserving();\n\n if (this.editor) {\n this.editor\n .getDocument()\n .removeEventListener('selectionchange', this.onNativeSelectionChange);\n this.editor = null;\n }\n }\n\n /**\n * Get plugin state object\n */\n getState(): CachePluginState {\n return this.state;\n }\n\n /**\n * Core method for a plugin. Once an event happens in editor, editor will call this\n * method of each plugin to handle the event as long as the event is not handled\n * exclusively by another plugin.\n * @param event The event to handle:\n */\n onPluginEvent(event: PluginEvent) {\n if (!this.editor) {\n return;\n }\n\n switch (event.eventType) {\n case 'logicalRootChanged':\n this.invalidateCache();\n\n this.state.textMutationObserver.stopObserving();\n this.state.textMutationObserver = createTextMutationObserver(\n event.logicalRoot,\n this.onMutation\n );\n this.state.textMutationObserver.startObserving();\n break;\n\n case 'selectionChanged':\n this.updateCachedModel(this.editor);\n break;\n\n case 'contentChanged':\n const { contentModel, selection } = event;\n\n if (contentModel) {\n updateCache(this.state, contentModel, selection);\n }\n\n break;\n }\n }\n\n private onMutation = (mutation: Mutation) => {\n if (this.editor) {\n switch (mutation.type) {\n case 'childList':\n if (\n !this.state.domIndexer.reconcileChildList(\n mutation.addedNodes,\n mutation.removedNodes\n )\n ) {\n this.invalidateCache();\n }\n break;\n\n case 'text':\n this.updateCachedModel(this.editor, true /*forceUpdate*/);\n break;\n\n case 'elementId':\n const element = mutation.element;\n\n if (!this.state.domIndexer.reconcileElementId(element)) {\n this.invalidateCache();\n }\n\n break;\n\n case 'attribute':\n if (\n !this.state.domIndexer.reconcileImageAttribute(\n mutation.element,\n mutation.attributeName\n )\n ) {\n this.invalidateCache();\n }\n\n break;\n\n case 'unknown':\n this.invalidateCache();\n break;\n }\n }\n };\n\n private onNativeSelectionChange = () => {\n if (this.editor?.hasFocus()) {\n this.updateCachedModel(this.editor);\n }\n };\n\n private invalidateCache() {\n if (!this.editor?.isInShadowEdit()) {\n if (this.state.cachedModel) {\n this.state.cachedModel = undefined;\n }\n\n if (this.state.cachedSelection) {\n this.state.cachedSelection = undefined;\n }\n\n // Clear paragraph indexer to prevent stale references to old paragraphs\n // It will be rebuild next time when we create a new Content Model\n this.state.paragraphMap?.clear();\n }\n }\n\n private updateCachedModel(editor: IEditor, forceUpdate?: boolean) {\n if (editor.isInShadowEdit()) {\n return;\n }\n\n const cachedSelection = this.state.cachedSelection;\n this.state.cachedSelection = undefined; // Clear it to force getDOMSelection() retrieve the latest selection range\n\n const newRangeEx = editor.getDOMSelection() || undefined;\n const model = this.state.cachedModel;\n const isSelectionChanged =\n forceUpdate ||\n !cachedSelection ||\n !newRangeEx ||\n !areSameSelections(newRangeEx, cachedSelection);\n\n if (isSelectionChanged) {\n if (\n !model ||\n !newRangeEx ||\n !this.state.domIndexer.reconcileSelection(model, newRangeEx, cachedSelection)\n ) {\n this.invalidateCache();\n } else {\n updateCache(this.state, model, newRangeEx);\n }\n } else {\n this.state.cachedSelection = cachedSelection;\n }\n }\n}\n\n/**\n * @internal\n * Create a new instance of CachePlugin class.\n * @param option The editor option\n * @param contentDiv The editor content DIV\n */\nexport function createCachePlugin(\n option: EditorOptions,\n contentDiv: HTMLDivElement\n): PluginWithState<CachePluginState> {\n return new CachePlugin(option, contentDiv);\n}\n"]}
@@ -10,6 +10,10 @@ export declare type MutationType =
10
10
  * Element id is changed
11
11
  */
12
12
  | 'elementId'
13
+ /**
14
+ * An attribute (such as src or data-*) is changed on an element
15
+ */
16
+ | 'attribute'
13
17
  /**
14
18
  * Only text is changed
15
19
  */
@@ -35,6 +39,13 @@ export interface UnknownMutation extends MutationBase<'unknown'> {
35
39
  export interface ElementIdMutation extends MutationBase<'elementId'> {
36
40
  element: HTMLElement;
37
41
  }
42
+ /**
43
+ * @internal
44
+ */
45
+ export interface AttributeMutation extends MutationBase<'attribute'> {
46
+ element: HTMLElement;
47
+ attributeName: string;
48
+ }
38
49
  /**
39
50
  * @internal
40
51
  */
@@ -50,4 +61,4 @@ export interface ChildListMutation extends MutationBase<'childList'> {
50
61
  /**
51
62
  * @internal
52
63
  */
53
- export declare type Mutation = UnknownMutation | ElementIdMutation | TextMutation | ChildListMutation;
64
+ export declare type Mutation = UnknownMutation | ElementIdMutation | AttributeMutation | TextMutation | ChildListMutation;
@@ -1 +1 @@
1
- {"version":3,"file":"MutationType.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/corePlugin/cache/MutationType.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * @internal Type of mutations\n */\nexport type MutationType =\n /**\n * We found some change happened but we cannot handle it, so set mutation type as \"unknown\"\n */\n | 'unknown'\n /**\n * Element id is changed\n */\n | 'elementId'\n /**\n * Only text is changed\n */\n | 'text'\n /**\n * Child list is changed\n */\n | 'childList';\n\n/**\n * @internal\n */\nexport interface MutationBase<T extends MutationType> {\n type: T;\n}\n\n/**\n * @internal\n */\nexport interface UnknownMutation extends MutationBase<'unknown'> {}\n\n/**\n * @internal\n */\nexport interface ElementIdMutation extends MutationBase<'elementId'> {\n element: HTMLElement;\n}\n\n/**\n * @internal\n */\nexport interface TextMutation extends MutationBase<'text'> {}\n\n/**\n * @internal\n */\nexport interface ChildListMutation extends MutationBase<'childList'> {\n addedNodes: Node[];\n removedNodes: Node[];\n}\n\n/**\n * @internal\n */\nexport type Mutation = UnknownMutation | ElementIdMutation | TextMutation | ChildListMutation;\n"]}
1
+ {"version":3,"file":"MutationType.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/corePlugin/cache/MutationType.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * @internal Type of mutations\n */\nexport type MutationType =\n /**\n * We found some change happened but we cannot handle it, so set mutation type as \"unknown\"\n */\n | 'unknown'\n /**\n * Element id is changed\n */\n | 'elementId'\n /**\n * An attribute (such as src or data-*) is changed on an element\n */\n | 'attribute'\n /**\n * Only text is changed\n */\n | 'text'\n /**\n * Child list is changed\n */\n | 'childList';\n\n/**\n * @internal\n */\nexport interface MutationBase<T extends MutationType> {\n type: T;\n}\n\n/**\n * @internal\n */\nexport interface UnknownMutation extends MutationBase<'unknown'> {}\n\n/**\n * @internal\n */\nexport interface ElementIdMutation extends MutationBase<'elementId'> {\n element: HTMLElement;\n}\n\n/**\n * @internal\n */\nexport interface AttributeMutation extends MutationBase<'attribute'> {\n element: HTMLElement;\n attributeName: string;\n}\n\n/**\n * @internal\n */\nexport interface TextMutation extends MutationBase<'text'> {}\n\n/**\n * @internal\n */\nexport interface ChildListMutation extends MutationBase<'childList'> {\n addedNodes: Node[];\n removedNodes: Node[];\n}\n\n/**\n * @internal\n */\nexport type Mutation =\n | UnknownMutation\n | ElementIdMutation\n | AttributeMutation\n | TextMutation\n | ChildListMutation;\n"]}
@@ -8,7 +8,3 @@ export declare function areSameSelections(sel1: DOMSelection, sel2: DOMSelection
8
8
  * @internal
9
9
  */
10
10
  export declare function areSameTableSelections(t1: TableSelection, t2: TableSelection): boolean;
11
- /**
12
- * @internal
13
- */
14
- export declare function areSameRanges(r1: Range, r2: Range): boolean;
@@ -1,3 +1,4 @@
1
+ import { areSameRanges } from '../../utils/areSameRanges';
1
2
  /**
2
3
  * @internal
3
4
  * Check if the given selections are the same
@@ -41,19 +42,12 @@ var TableSelectionKeys = [
41
42
  'firstRow',
42
43
  'lastRow',
43
44
  ];
44
- var RangeKeys = ['startContainer', 'endContainer', 'startOffset', 'endOffset'];
45
45
  /**
46
46
  * @internal
47
47
  */
48
48
  export function areSameTableSelections(t1, t2) {
49
49
  return areSame(t1, t2, TableSelectionKeys);
50
50
  }
51
- /**
52
- * @internal
53
- */
54
- export function areSameRanges(r1, r2) {
55
- return areSame(r1, r2, RangeKeys);
56
- }
57
51
  function isCacheSelection(sel) {
58
52
  return !!sel.start;
59
53
  }
@@ -1 +1 @@
1
- {"version":3,"file":"areSameSelections.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC7B,IAAkB,EAClB,IAAmC;IAEnC,IAAI,IAAI,IAAI,IAAI,EAAE;QACd,OAAO,IAAI,CAAC;KACf;IAED,QAAQ,IAAI,CAAC,IAAI,EAAE;QACf,KAAK,OAAO;YACR,OAAO,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;QAE5D,KAAK,OAAO;YACR,OAAO,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,sBAAsB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAEtE,KAAK,OAAO,CAAC;QACb;YACI,IAAI,IAAI,CAAC,IAAI,IAAI,OAAO,EAAE;gBACtB,IAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;gBAE1B,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE;oBAChB,IAAA,KAAK,GAAU,IAAI,MAAd,EAAE,GAAG,GAAK,IAAI,IAAT,CAAU;oBAE5B,OAAO,CACH,MAAM,CAAC,cAAc,IAAI,KAAK,CAAC,IAAI;wBACnC,MAAM,CAAC,YAAY,IAAI,GAAG,CAAC,IAAI;wBAC/B,MAAM,CAAC,WAAW,IAAI,KAAK,CAAC,MAAM;wBAClC,MAAM,CAAC,SAAS,IAAI,GAAG,CAAC,MAAM,CACjC,CAAC;iBACL;qBAAM;oBACH,OAAO,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;iBAC5C;aACJ;iBAAM;gBACH,OAAO,KAAK,CAAC;aAChB;KACR;AACL,CAAC;AAED,SAAS,OAAO,CAAI,EAAK,EAAE,EAAK,EAAE,IAAiB;IAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,UAAA,CAAC,IAAI,OAAA,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAd,CAAc,CAAC,CAAC;AAC3C,CAAC;AAED,IAAM,kBAAkB,GAA6B;IACjD,OAAO;IACP,aAAa;IACb,YAAY;IACZ,UAAU;IACV,SAAS;CACZ,CAAC;AACF,IAAM,SAAS,GAAoB,CAAC,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;AAElG;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,EAAkB,EAAE,EAAkB;IACzE,OAAO,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,EAAS,EAAE,EAAS;IAC9C,OAAO,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,gBAAgB,CACrB,GAA4C;IAE5C,OAAO,CAAC,CAAE,GAA8B,CAAC,KAAK,CAAC;AACnD,CAAC","sourcesContent":["import type {\n CacheSelection,\n DOMSelection,\n RangeSelection,\n RangeSelectionForCache,\n TableSelection,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n * Check if the given selections are the same\n */\nexport function areSameSelections(\n sel1: DOMSelection,\n sel2: DOMSelection | CacheSelection\n): boolean {\n if (sel1 == sel2) {\n return true;\n }\n\n switch (sel1.type) {\n case 'image':\n return sel2.type == 'image' && sel2.image == sel1.image;\n\n case 'table':\n return sel2.type == 'table' && areSameTableSelections(sel1, sel2);\n\n case 'range':\n default:\n if (sel2.type == 'range') {\n const range1 = sel1.range;\n\n if (isCacheSelection(sel2)) {\n const { start, end } = sel2;\n\n return (\n range1.startContainer == start.node &&\n range1.endContainer == end.node &&\n range1.startOffset == start.offset &&\n range1.endOffset == end.offset\n );\n } else {\n return areSameRanges(range1, sel2.range);\n }\n } else {\n return false;\n }\n }\n}\n\nfunction areSame<O>(o1: O, o2: O, keys: (keyof O)[]) {\n return keys.every(k => o1[k] == o2[k]);\n}\n\nconst TableSelectionKeys: (keyof TableSelection)[] = [\n 'table',\n 'firstColumn',\n 'lastColumn',\n 'firstRow',\n 'lastRow',\n];\nconst RangeKeys: (keyof Range)[] = ['startContainer', 'endContainer', 'startOffset', 'endOffset'];\n\n/**\n * @internal\n */\nexport function areSameTableSelections(t1: TableSelection, t2: TableSelection): boolean {\n return areSame(t1, t2, TableSelectionKeys);\n}\n\n/**\n * @internal\n */\nexport function areSameRanges(r1: Range, r2: Range): boolean {\n return areSame(r1, r2, RangeKeys);\n}\n\nfunction isCacheSelection(\n sel: RangeSelectionForCache | RangeSelection\n): sel is RangeSelectionForCache {\n return !!(sel as RangeSelectionForCache).start;\n}\n"]}
1
+ {"version":3,"file":"areSameSelections.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAS1D;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC7B,IAAkB,EAClB,IAAmC;IAEnC,IAAI,IAAI,IAAI,IAAI,EAAE;QACd,OAAO,IAAI,CAAC;KACf;IAED,QAAQ,IAAI,CAAC,IAAI,EAAE;QACf,KAAK,OAAO;YACR,OAAO,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;QAE5D,KAAK,OAAO;YACR,OAAO,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,sBAAsB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAEtE,KAAK,OAAO,CAAC;QACb;YACI,IAAI,IAAI,CAAC,IAAI,IAAI,OAAO,EAAE;gBACtB,IAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;gBAE1B,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE;oBAChB,IAAA,KAAK,GAAU,IAAI,MAAd,EAAE,GAAG,GAAK,IAAI,IAAT,CAAU;oBAE5B,OAAO,CACH,MAAM,CAAC,cAAc,IAAI,KAAK,CAAC,IAAI;wBACnC,MAAM,CAAC,YAAY,IAAI,GAAG,CAAC,IAAI;wBAC/B,MAAM,CAAC,WAAW,IAAI,KAAK,CAAC,MAAM;wBAClC,MAAM,CAAC,SAAS,IAAI,GAAG,CAAC,MAAM,CACjC,CAAC;iBACL;qBAAM;oBACH,OAAO,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;iBAC5C;aACJ;iBAAM;gBACH,OAAO,KAAK,CAAC;aAChB;KACR;AACL,CAAC;AAED,SAAS,OAAO,CAAI,EAAK,EAAE,EAAK,EAAE,IAAiB;IAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,UAAA,CAAC,IAAI,OAAA,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAd,CAAc,CAAC,CAAC;AAC3C,CAAC;AAED,IAAM,kBAAkB,GAA6B;IACjD,OAAO;IACP,aAAa;IACb,YAAY;IACZ,UAAU;IACV,SAAS;CACZ,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,EAAkB,EAAE,EAAkB;IACzE,OAAO,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,gBAAgB,CACrB,GAA4C;IAE5C,OAAO,CAAC,CAAE,GAA8B,CAAC,KAAK,CAAC;AACnD,CAAC","sourcesContent":["import { areSameRanges } from '../../utils/areSameRanges';\nimport type {\n CacheSelection,\n DOMSelection,\n RangeSelection,\n RangeSelectionForCache,\n TableSelection,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n * Check if the given selections are the same\n */\nexport function areSameSelections(\n sel1: DOMSelection,\n sel2: DOMSelection | CacheSelection\n): boolean {\n if (sel1 == sel2) {\n return true;\n }\n\n switch (sel1.type) {\n case 'image':\n return sel2.type == 'image' && sel2.image == sel1.image;\n\n case 'table':\n return sel2.type == 'table' && areSameTableSelections(sel1, sel2);\n\n case 'range':\n default:\n if (sel2.type == 'range') {\n const range1 = sel1.range;\n\n if (isCacheSelection(sel2)) {\n const { start, end } = sel2;\n\n return (\n range1.startContainer == start.node &&\n range1.endContainer == end.node &&\n range1.startOffset == start.offset &&\n range1.endOffset == end.offset\n );\n } else {\n return areSameRanges(range1, sel2.range);\n }\n } else {\n return false;\n }\n }\n}\n\nfunction areSame<O>(o1: O, o2: O, keys: (keyof O)[]) {\n return keys.every(k => o1[k] == o2[k]);\n}\n\nconst TableSelectionKeys: (keyof TableSelection)[] = [\n 'table',\n 'firstColumn',\n 'lastColumn',\n 'firstRow',\n 'lastRow',\n];\n\n/**\n * @internal\n */\nexport function areSameTableSelections(t1: TableSelection, t2: TableSelection): boolean {\n return areSame(t1, t2, TableSelectionKeys);\n}\n\nfunction isCacheSelection(\n sel: RangeSelectionForCache | RangeSelection\n): sel is RangeSelectionForCache {\n return !!(sel as RangeSelectionForCache).start;\n}\n"]}
@@ -53,6 +53,7 @@ export declare class DomIndexerImpl implements DomIndexer {
53
53
  reconcileSelection(model: ContentModelDocument, newSelection: DOMSelection, oldSelection?: CacheSelection): boolean;
54
54
  reconcileChildList(addedNodes: ArrayLike<Node>, removedNodes: ArrayLike<Node>): boolean;
55
55
  reconcileElementId(element: HTMLElement): boolean;
56
+ reconcileImageAttribute(element: HTMLElement, attributeName: string): boolean;
56
57
  private onBlockEntityDelimiter;
57
58
  private isCollapsed;
58
59
  private reconcileNodeSelection;
@@ -158,7 +158,13 @@ var DomIndexerImpl = /** @class */ (function () {
158
158
  }
159
159
  else {
160
160
  var marker1 = this.reconcileNodeSelection(startContainer, startOffset);
161
- var marker2 = this.reconcileNodeSelection(endContainer, endOffset);
161
+ // Pass marker1 to the second call so its adjacent-marker cleanup
162
+ // does not consume the SelectionMarker we just inserted. Without
163
+ // this guard, when marker1 lands directly next to endContainer's
164
+ // segment in paragraph.segments (e.g. startOffset == startContainer
165
+ // text length), the second splice would absorb marker1 and leave
166
+ // setSelection with a dangling reference. See issue #3341.
167
+ var marker2 = this.reconcileNodeSelection(endContainer, endOffset, undefined, undefined, marker1);
162
168
  if (marker1 && marker2) {
163
169
  if (newSelection.isReverted) {
164
170
  model.hasRevertedRangeSelection = true;
@@ -224,6 +230,33 @@ var DomIndexerImpl = /** @class */ (function () {
224
230
  return false;
225
231
  }
226
232
  };
233
+ DomIndexerImpl.prototype.reconcileImageAttribute = function (element, attributeName) {
234
+ var _a, _b;
235
+ if (isElementOfType(element, 'img')) {
236
+ var image = (_a = getIndexedSegmentItem(element)) === null || _a === void 0 ? void 0 : _a.segments[0];
237
+ if ((image === null || image === void 0 ? void 0 : image.segmentType) == 'Image') {
238
+ if (attributeName == 'src') {
239
+ // Use getAttribute('src') instead of retrieving src directly, in case the src
240
+ // has port and may be stripped by browser. This matches imageProcessor.
241
+ image.src = (_b = element.getAttribute('src')) !== null && _b !== void 0 ? _b : '';
242
+ return true;
243
+ }
244
+ else if (attributeName.indexOf('data-') == 0) {
245
+ // A data-* attribute may be added, modified or removed. Rebuild the whole
246
+ // dataset from DOM to keep it in sync, the same way imageProcessor builds it.
247
+ var dataset_1 = image.dataset;
248
+ getObjectKeys(dataset_1).forEach(function (key) {
249
+ delete dataset_1[key];
250
+ });
251
+ getObjectKeys(element.dataset).forEach(function (key) {
252
+ dataset_1[key] = element.dataset[key] || '';
253
+ });
254
+ return true;
255
+ }
256
+ }
257
+ }
258
+ return false;
259
+ };
227
260
  DomIndexerImpl.prototype.onBlockEntityDelimiter = function (node, entity, parent) {
228
261
  if (isNodeOfType(node, 'ELEMENT_NODE') && isEntityDelimiter(node) && node.firstChild) {
229
262
  var indexedDelimiter = node.firstChild;
@@ -234,10 +267,10 @@ var DomIndexerImpl = /** @class */ (function () {
234
267
  var start = selection.start, end = selection.end;
235
268
  return start.node == end.node && start.offset == end.offset;
236
269
  };
237
- DomIndexerImpl.prototype.reconcileNodeSelection = function (node, offset, defaultFormat, selectionMarker) {
270
+ DomIndexerImpl.prototype.reconcileNodeSelection = function (node, offset, defaultFormat, selectionMarker, preserveMarker) {
238
271
  if (isNodeOfType(node, 'TEXT_NODE')) {
239
272
  if (isIndexedSegment(node)) {
240
- return this.reconcileTextSelection(node, offset, undefined, selectionMarker);
273
+ return this.reconcileTextSelection(node, offset, undefined, selectionMarker, preserveMarker);
241
274
  }
242
275
  else if (isIndexedDelimiter(node)) {
243
276
  return this.reconcileDelimiterSelection(node, defaultFormat);
@@ -267,7 +300,7 @@ var DomIndexerImpl = /** @class */ (function () {
267
300
  }
268
301
  return marker;
269
302
  };
270
- DomIndexerImpl.prototype.reconcileTextSelection = function (textNode, startOffset, endOffset, selectionMarker) {
303
+ DomIndexerImpl.prototype.reconcileTextSelection = function (textNode, startOffset, endOffset, selectionMarker, preserveMarker) {
271
304
  var _a;
272
305
  var _b, _c, _d, _e, _f, _g;
273
306
  var _h = textNode.__roosterjsContentModel, paragraph = _h.paragraph, segments = _h.segments;
@@ -320,11 +353,13 @@ var DomIndexerImpl = /** @class */ (function () {
320
353
  var lastIndex = paragraph.segments.indexOf(last);
321
354
  if (firstIndex >= 0 && lastIndex >= 0) {
322
355
  while (firstIndex > 0 &&
323
- paragraph.segments[firstIndex - 1].segmentType == 'SelectionMarker') {
356
+ paragraph.segments[firstIndex - 1].segmentType == 'SelectionMarker' &&
357
+ paragraph.segments[firstIndex - 1] !== preserveMarker) {
324
358
  firstIndex--;
325
359
  }
326
360
  while (lastIndex < paragraph.segments.length - 1 &&
327
- paragraph.segments[lastIndex + 1].segmentType == 'SelectionMarker') {
361
+ paragraph.segments[lastIndex + 1].segmentType == 'SelectionMarker' &&
362
+ paragraph.segments[lastIndex + 1] !== preserveMarker) {
328
363
  lastIndex++;
329
364
  }
330
365
  (_a = paragraph.segments).splice.apply(_a, __spreadArray([firstIndex, lastIndex - firstIndex + 1], __read(newSegments), false));