@globalpayments/vega 2.61.0 → 2.62.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 (417) hide show
  1. package/dist/cjs/{app-globals-7e624dd0.js → app-globals-8f5fa42a.js} +23 -15
  2. package/dist/cjs/base-renderer-0a3b62b7.js +9 -0
  3. package/dist/cjs/{child-nodes-event-prevent-slimmer-184fe3b2.js → child-nodes-event-prevent-slimmer-4e96270e.js} +1 -1
  4. package/dist/cjs/{code-block-ecb2df41.js → code-block-eb66d852.js} +73 -22
  5. package/dist/cjs/{component-value-history-controller-slimmer.abstract-58a0f64c.js → component-value-history-controller-slimmer.abstract-62cdf04c.js} +16 -182
  6. package/dist/cjs/{design-token-16f74439.js → design-token-76bb47bd.js} +1 -1
  7. package/dist/cjs/{dom-node-subject-factory-4eb1fec2.js → dom-node-subject-observer-factory-58e3c010.js} +41 -0
  8. package/dist/cjs/{content-state-d7b8e70b.js → dto-renderer-manager-f3894490.js} +1647 -1501
  9. package/dist/cjs/{element-appender-slimmer-c4816142.js → element-appender-slimmer-e8dac628.js} +7 -8
  10. package/dist/cjs/{event-emit-slimmer-2da7c9d6.js → event-emit-slimmer-428d8802.js} +3 -4
  11. package/dist/cjs/{form-field-controller-slimmer-dab30e5c.js → form-field-controller-slimmer-cc6e53a4.js} +4 -5
  12. package/dist/cjs/{image-annotation-action-7eaab3ce.js → image-annotation-action-a628ec9b.js} +24 -81
  13. package/dist/cjs/{index-da628bba.js → index-5505e8dd.js} +3 -3
  14. package/dist/cjs/index.cjs.js +49 -23
  15. package/dist/cjs/{icon-manager-9072356d.js → internal-icon-manager-32f9ed63.js} +51 -0
  16. package/dist/cjs/{internal-vega-event-manager-7b87c2f4.js → internal-vega-event-manager-28b957c8.js} +73 -73
  17. package/dist/cjs/language-extension-20a1dba5.js +207 -0
  18. package/dist/cjs/loader.cjs.js +14 -12
  19. package/dist/cjs/{public-rules-21622bd0.js → public-rules-5d0f3a5f.js} +5 -5
  20. package/dist/cjs/range-cfc45f9e.js +178 -0
  21. package/dist/cjs/{responsive-format-facade-0d22ff78.js → responsive-format-facade-7e933525.js} +4 -3
  22. package/dist/cjs/{rich-text-editor-required-rule-8d7e441a.js → rich-text-editor-required-rule-72170c10.js} +2 -2
  23. package/dist/cjs/{string-input-formatter-slimmer-5a744e71.js → string-input-formatter-slimmer-f6c7a255.js} +4 -4
  24. package/dist/cjs/{style-formatter-a66813a2.js → style-formatter-702df81e.js} +1 -1
  25. package/dist/cjs/{sub-state-notify-slimmer-9602b5bb.js → sub-state-notify-slimmer-bb64fcfc.js} +4 -4
  26. package/dist/cjs/{sub-state-observer-slimmer-df7df5bb.js → sub-state-observer-slimmer-84175d61.js} +4 -4
  27. package/dist/cjs/{vega-skeleton-loader-controller-9c54f3aa.js → token-extension-23ccff1d.js} +679 -3
  28. package/dist/cjs/vega-accordion.cjs.entry.js +15 -16
  29. package/dist/cjs/vega-app-header-button.cjs.entry.js +20 -21
  30. package/dist/cjs/vega-banner.cjs.entry.js +7 -9
  31. package/dist/cjs/vega-box.cjs.entry.js +13 -12
  32. package/dist/cjs/vega-brand-logo.cjs.entry.js +1 -2
  33. package/dist/cjs/vega-breadcrumb.cjs.entry.js +8 -9
  34. package/dist/cjs/vega-button-circle.cjs.entry.js +16 -16
  35. package/dist/cjs/vega-button-group_2.cjs.entry.js +11 -12
  36. package/dist/cjs/vega-button-link.cjs.entry.js +7 -8
  37. package/dist/cjs/vega-button.cjs.entry.js +15 -15
  38. package/dist/cjs/vega-calendar_4.cjs.entry.js +22 -24
  39. package/dist/cjs/vega-card.cjs.entry.js +12 -11
  40. package/dist/cjs/vega-carousel.cjs.entry.js +13 -13
  41. package/dist/cjs/vega-checkbox_2.cjs.entry.js +12 -13
  42. package/dist/cjs/vega-chip.cjs.entry.js +17 -17
  43. package/dist/cjs/vega-code-block.cjs.entry.js +16 -17
  44. package/dist/cjs/vega-color-picker.cjs.entry.js +6 -7
  45. package/dist/cjs/vega-combo-box.cjs.entry.js +14 -15
  46. package/dist/cjs/vega-date-picker_2.cjs.entry.js +30 -31
  47. package/dist/cjs/vega-dialog_2.cjs.entry.js +27 -27
  48. package/dist/cjs/vega-divider.cjs.entry.js +12 -11
  49. package/dist/cjs/vega-dropdown_5.cjs.entry.js +32 -32
  50. package/dist/cjs/vega-env-manager-23b8b23c.js +2 -2
  51. package/dist/cjs/vega-field-label.cjs.entry.js +6 -7
  52. package/dist/cjs/vega-file-uploader.cjs.entry.js +15 -17
  53. package/dist/cjs/vega-flag-icon.cjs.entry.js +13 -13
  54. package/dist/cjs/vega-flex.cjs.entry.js +12 -11
  55. package/dist/cjs/vega-font.cjs.entry.js +12 -11
  56. package/dist/cjs/vega-form.cjs.entry.js +13 -14
  57. package/dist/cjs/vega-grid.cjs.entry.js +12 -11
  58. package/dist/cjs/vega-icon.cjs.entry.js +15 -14
  59. package/dist/cjs/vega-image-uploader.cjs.entry.js +18 -18
  60. package/dist/cjs/vega-input-credit-card.cjs.entry.js +14 -16
  61. package/dist/cjs/vega-input-numeric.cjs.entry.js +10 -11
  62. package/dist/cjs/vega-input-phone-number.cjs.entry.js +20 -21
  63. package/dist/cjs/vega-input-range.cjs.entry.js +11 -12
  64. package/dist/cjs/vega-input-select.cjs.entry.js +27 -28
  65. package/dist/cjs/vega-input.cjs.entry.js +12 -13
  66. package/dist/cjs/vega-item-toggle.cjs.entry.js +5 -6
  67. package/dist/cjs/vega-left-nav_5.cjs.entry.js +33 -34
  68. package/dist/cjs/vega-loader-wrapper_2.cjs.entry.js +13 -12
  69. package/dist/cjs/vega-page-notification_2.cjs.entry.js +2 -3
  70. package/dist/cjs/vega-pagination-page-selector-mobile.cjs.entry.js +8 -9
  71. package/dist/cjs/vega-pagination-page-size-selector-mobile.cjs.entry.js +3 -4
  72. package/dist/cjs/vega-pagination.cjs.entry.js +18 -18
  73. package/dist/cjs/vega-popover_2.cjs.entry.js +18 -18
  74. package/dist/cjs/vega-progress-tracker.cjs.entry.js +5 -6
  75. package/dist/cjs/vega-radio_2.cjs.entry.js +13 -14
  76. package/dist/cjs/vega-rich-text-content.cjs.entry.js +53 -48
  77. package/dist/cjs/vega-rich-text-editor_4.cjs.entry.js +387 -261
  78. package/dist/cjs/vega-segment-control.cjs.entry.js +5 -6
  79. package/dist/cjs/vega-selection-chip_2.cjs.entry.js +20 -20
  80. package/dist/cjs/vega-selection-tile_2.cjs.entry.js +13 -14
  81. package/dist/cjs/vega-sidenav_3.cjs.entry.js +24 -25
  82. package/dist/cjs/vega-signature-capture.cjs.entry.js +16 -17
  83. package/dist/cjs/vega-stepper.cjs.entry.js +12 -13
  84. package/dist/cjs/vega-tab-group_2.cjs.entry.js +8 -9
  85. package/dist/cjs/vega-table_8.cjs.entry.js +58 -59
  86. package/dist/cjs/vega-textarea.cjs.entry.js +9 -10
  87. package/dist/cjs/vega-time-picker_2.cjs.entry.js +24 -24
  88. package/dist/cjs/vega-toggle-switch.cjs.entry.js +7 -8
  89. package/dist/cjs/vega-tooltip_2.cjs.entry.js +12 -12
  90. package/dist/cjs/vega.cjs.js +14 -12
  91. package/dist/collection/components/vega-rich-text-content/vega-rich-text-content.js +31 -0
  92. package/dist/collection/components/vega-rich-text-editor/constants/constant.js +10 -0
  93. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/action-handle-strategy-registry.js +11 -0
  94. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/apply-annotation-strategies/node-split-text-strategy.js +6 -3
  95. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-delete-text-or-decorator-node-strategy.js +12 -6
  96. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/code-block-remove-self-strategy.js +2 -2
  97. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/insert-node-to-nearest-root-strategy.js +57 -0
  98. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/update-cursor-position-strategy.js +2 -1
  99. package/dist/collection/components/vega-rich-text-editor/dto/actions/insert-node-to-nearest-root-action.js +14 -0
  100. package/dist/collection/components/vega-rich-text-editor/dto/actions/modify-content-action.abstract.js +1 -0
  101. package/dist/collection/components/vega-rich-text-editor/dto/actions/update-cursor-position-action.js +5 -2
  102. package/dist/collection/components/vega-rich-text-editor/dto/content-state.js +12 -0
  103. package/dist/collection/components/vega-rich-text-editor/dto/nodes/text-node.js +36 -10
  104. package/dist/collection/components/vega-rich-text-editor/dto/renderers/blocks/link-wrapper-renderer.js +10 -4
  105. package/dist/collection/components/vega-rich-text-editor/extensions/base-toolbar-button-renderer.js +145 -0
  106. package/dist/collection/components/vega-rich-text-editor/extensions/extension.abstract.js +97 -0
  107. package/dist/collection/components/vega-rich-text-editor/extensions/languages/language-extension.js +113 -0
  108. package/dist/collection/components/vega-rich-text-editor/extensions/languages/language-toolbar-button-renderer.js +90 -0
  109. package/dist/collection/components/vega-rich-text-editor/extensions/tokens/insert-token-node-action.js +16 -0
  110. package/dist/collection/components/vega-rich-text-editor/extensions/tokens/insert-token-node-strategy.js +20 -0
  111. package/dist/collection/components/vega-rich-text-editor/extensions/tokens/span-to-token-node-strategy.js +60 -0
  112. package/dist/collection/components/vega-rich-text-editor/extensions/tokens/token-extension.js +38 -0
  113. package/dist/collection/components/vega-rich-text-editor/extensions/tokens/token-node-renderer.js +67 -0
  114. package/dist/collection/components/vega-rich-text-editor/extensions/tokens/token-node.js +55 -0
  115. package/dist/collection/components/vega-rich-text-editor/extensions/tokens/token-toolbar-button-renderer.js +88 -0
  116. package/dist/collection/components/vega-rich-text-editor/public-api.js +38 -0
  117. package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/extension-controller.js +97 -0
  118. package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/focus-controller.js +8 -6
  119. package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/helper/element-to-dto-strategy/element-to-dto-strategy.abstract.js +12 -0
  120. package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/selection-controller.js +9 -3
  121. package/dist/collection/components/vega-rich-text-editor/slimmers/renderers/toolbar-renderer.js +43 -18
  122. package/dist/collection/components/vega-rich-text-editor/slimmers/renderers/tools/link-toolbar-button-slimmer.js +3 -1
  123. package/dist/collection/components/vega-rich-text-editor/slimmers/renderers/tools/toolbar-button-slimmer.abstract.js +6 -6
  124. package/dist/collection/components/vega-rich-text-editor/slimmers/renderers/tools/visual-mode-toolbar-button-slimmer.abstract.js +9 -9
  125. package/dist/collection/components/vega-rich-text-editor/test/dto/content-state.test.js +41 -0
  126. package/dist/collection/components/vega-rich-text-editor/vega-rich-text-editor.js +44 -11
  127. package/dist/collection/global/scripts/before-vega-load.js +9 -0
  128. package/dist/collection/helpers/code-format/test/code-formatter.test.js +1 -1
  129. package/dist/collection/helpers/public-api.js +1 -1
  130. package/dist/collection/helpers/rte-manager/dto-action-strategy-manager.js +2 -0
  131. package/dist/esm/{app-globals-ce54f0ac.js → app-globals-aaff0b25.js} +13 -5
  132. package/dist/esm/base-renderer-101f6d04.js +7 -0
  133. package/dist/esm/{child-nodes-event-prevent-slimmer-2a3115ae.js → child-nodes-event-prevent-slimmer-7fe3dc57.js} +1 -1
  134. package/dist/esm/{code-block-89a4dd13.js → code-block-68300b47.js} +67 -17
  135. package/dist/esm/{component-value-history-controller-slimmer.abstract-95b199df.js → component-value-history-controller-slimmer.abstract-ac2f1bfd.js} +13 -179
  136. package/dist/esm/{design-token-eaa7c221.js → design-token-1a36307e.js} +1 -1
  137. package/dist/esm/{dom-node-subject-factory-3c2e13f1.js → dom-node-subject-observer-factory-c7bc3035.js} +41 -1
  138. package/dist/esm/{content-state-fc47457c.js → dto-renderer-manager-af66bbd9.js} +1643 -1502
  139. package/dist/esm/{element-appender-slimmer-ce83db8a.js → element-appender-slimmer-fe68ec2d.js} +3 -4
  140. package/dist/esm/{event-emit-slimmer-4428ce26.js → event-emit-slimmer-3922d816.js} +2 -3
  141. package/dist/esm/{form-field-controller-slimmer-6e69ca4e.js → form-field-controller-slimmer-f7e8845b.js} +2 -3
  142. package/dist/esm/{image-annotation-action-53812eb7.js → image-annotation-action-f61c2693.js} +20 -76
  143. package/dist/esm/{index-1d479c88.js → index-7fe93427.js} +1 -1
  144. package/dist/esm/index.js +13 -10
  145. package/dist/esm/{icon-manager-2ee1c619.js → internal-icon-manager-f0486245.js} +51 -1
  146. package/dist/esm/{internal-vega-event-manager-a654cf8a.js → internal-vega-event-manager-cb06e987.js} +1 -1
  147. package/dist/esm/language-extension-1ada2a9d.js +204 -0
  148. package/dist/esm/loader.js +14 -12
  149. package/dist/esm/{public-rules-095284f6.js → public-rules-9f62069a.js} +5 -5
  150. package/dist/esm/range-c2eeb794.js +176 -0
  151. package/dist/esm/{responsive-format-facade-86b6de3b.js → responsive-format-facade-5711c77d.js} +4 -3
  152. package/dist/esm/{rich-text-editor-required-rule-4e8d2db8.js → rich-text-editor-required-rule-de738309.js} +1 -1
  153. package/dist/esm/{string-input-formatter-slimmer-60897659.js → string-input-formatter-slimmer-69117deb.js} +2 -2
  154. package/dist/esm/{style-formatter-a0719a8f.js → style-formatter-2479dc61.js} +1 -1
  155. package/dist/esm/{sub-state-notify-slimmer-ee730968.js → sub-state-notify-slimmer-4252a90e.js} +1 -1
  156. package/dist/esm/{sub-state-observer-slimmer-d474634d.js → sub-state-observer-slimmer-baa8853a.js} +1 -1
  157. package/dist/esm/{vega-skeleton-loader-controller-394a6026.js → token-extension-6fc5e1f5.js} +672 -4
  158. package/dist/esm/vega-accordion.entry.js +13 -14
  159. package/dist/esm/vega-app-header-button.entry.js +14 -15
  160. package/dist/esm/vega-banner.entry.js +4 -6
  161. package/dist/esm/vega-box.entry.js +13 -12
  162. package/dist/esm/vega-brand-logo.entry.js +1 -2
  163. package/dist/esm/vega-breadcrumb.entry.js +4 -5
  164. package/dist/esm/vega-button-circle.entry.js +14 -14
  165. package/dist/esm/vega-button-group_2.entry.js +6 -7
  166. package/dist/esm/vega-button-link.entry.js +5 -6
  167. package/dist/esm/vega-button.entry.js +13 -13
  168. package/dist/esm/vega-calendar_4.entry.js +7 -9
  169. package/dist/esm/vega-card.entry.js +12 -11
  170. package/dist/esm/vega-carousel.entry.js +12 -12
  171. package/dist/esm/vega-checkbox_2.entry.js +6 -7
  172. package/dist/esm/vega-chip.entry.js +14 -14
  173. package/dist/esm/vega-code-block.entry.js +8 -9
  174. package/dist/esm/vega-color-picker.entry.js +5 -6
  175. package/dist/esm/vega-combo-box.entry.js +6 -7
  176. package/dist/esm/vega-date-picker_2.entry.js +16 -17
  177. package/dist/esm/vega-dialog_2.entry.js +15 -15
  178. package/dist/esm/vega-divider.entry.js +12 -11
  179. package/dist/esm/vega-dropdown_5.entry.js +15 -15
  180. package/dist/esm/vega-env-manager-8f8dc473.js +2 -2
  181. package/dist/esm/vega-field-label.entry.js +4 -5
  182. package/dist/esm/vega-file-uploader.entry.js +6 -8
  183. package/dist/esm/vega-flag-icon.entry.js +12 -12
  184. package/dist/esm/vega-flex.entry.js +12 -11
  185. package/dist/esm/vega-font.entry.js +12 -11
  186. package/dist/esm/vega-form.entry.js +7 -8
  187. package/dist/esm/vega-grid.entry.js +12 -11
  188. package/dist/esm/vega-icon.entry.js +12 -11
  189. package/dist/esm/vega-image-uploader.entry.js +12 -12
  190. package/dist/esm/vega-input-credit-card.entry.js +7 -9
  191. package/dist/esm/vega-input-numeric.entry.js +7 -8
  192. package/dist/esm/vega-input-phone-number.entry.js +12 -13
  193. package/dist/esm/vega-input-range.entry.js +7 -8
  194. package/dist/esm/vega-input-select.entry.js +14 -15
  195. package/dist/esm/vega-input.entry.js +7 -8
  196. package/dist/esm/vega-item-toggle.entry.js +3 -4
  197. package/dist/esm/vega-left-nav_5.entry.js +14 -15
  198. package/dist/esm/vega-loader-wrapper_2.entry.js +11 -10
  199. package/dist/esm/vega-page-notification_2.entry.js +1 -2
  200. package/dist/esm/vega-pagination-page-selector-mobile.entry.js +3 -4
  201. package/dist/esm/vega-pagination-page-size-selector-mobile.entry.js +1 -2
  202. package/dist/esm/vega-pagination.entry.js +10 -10
  203. package/dist/esm/vega-popover_2.entry.js +14 -14
  204. package/dist/esm/vega-progress-tracker.entry.js +3 -4
  205. package/dist/esm/vega-radio_2.entry.js +6 -7
  206. package/dist/esm/vega-rich-text-content.entry.js +24 -19
  207. package/dist/esm/vega-rich-text-editor_4.entry.js +342 -216
  208. package/dist/esm/vega-segment-control.entry.js +4 -5
  209. package/dist/esm/vega-selection-chip_2.entry.js +15 -15
  210. package/dist/esm/vega-selection-tile_2.entry.js +7 -8
  211. package/dist/esm/vega-sidenav_3.entry.js +16 -17
  212. package/dist/esm/vega-signature-capture.entry.js +14 -15
  213. package/dist/esm/vega-stepper.entry.js +6 -7
  214. package/dist/esm/vega-tab-group_2.entry.js +4 -5
  215. package/dist/esm/vega-table_8.entry.js +12 -13
  216. package/dist/esm/vega-textarea.entry.js +6 -7
  217. package/dist/esm/vega-time-picker_2.entry.js +14 -14
  218. package/dist/esm/vega-toggle-switch.entry.js +6 -7
  219. package/dist/esm/vega-tooltip_2.entry.js +12 -12
  220. package/dist/esm/vega.js +14 -12
  221. package/dist/types/components/vega-rich-text-content/vega-rich-text-content.d.ts +8 -0
  222. package/dist/types/components/vega-rich-text-editor/constants/constant.d.ts +2 -1
  223. package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/action-handle-strategy-registry.d.ts +8 -0
  224. package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/insert-node-to-nearest-root-strategy.d.ts +18 -0
  225. package/dist/types/components/vega-rich-text-editor/dto/actions/insert-node-to-nearest-root-action.d.ts +14 -0
  226. package/dist/types/components/vega-rich-text-editor/dto/actions/modify-content-action.abstract.d.ts +2 -1
  227. package/dist/types/components/vega-rich-text-editor/dto/actions/update-cursor-position-action.d.ts +4 -2
  228. package/dist/types/components/vega-rich-text-editor/dto/blocks/block.abstract.d.ts +2 -3
  229. package/dist/types/components/vega-rich-text-editor/dto/content-state.d.ts +6 -0
  230. package/dist/types/components/vega-rich-text-editor/dto/nodes/text-node.d.ts +11 -1
  231. package/dist/types/components/vega-rich-text-editor/dto/renderers/blocks/link-wrapper-renderer.d.ts +3 -3
  232. package/dist/types/components/vega-rich-text-editor/extensions/base-toolbar-button-renderer.d.ts +95 -2
  233. package/dist/types/components/vega-rich-text-editor/extensions/extension.abstract.d.ts +82 -0
  234. package/dist/types/components/vega-rich-text-editor/extensions/languages/language-extension.d.ts +50 -0
  235. package/dist/types/components/vega-rich-text-editor/extensions/languages/language-toolbar-button-renderer.d.ts +54 -0
  236. package/dist/types/components/vega-rich-text-editor/extensions/tokens/insert-token-node-action.d.ts +16 -0
  237. package/dist/types/components/vega-rich-text-editor/extensions/tokens/insert-token-node-strategy.d.ts +12 -0
  238. package/dist/types/components/vega-rich-text-editor/extensions/tokens/span-to-token-node-strategy.d.ts +24 -0
  239. package/dist/types/components/vega-rich-text-editor/extensions/tokens/token-extension.d.ts +14 -0
  240. package/dist/types/components/vega-rich-text-editor/extensions/tokens/token-node-renderer.d.ts +38 -0
  241. package/dist/types/components/vega-rich-text-editor/extensions/tokens/token-node.d.ts +39 -0
  242. package/dist/types/components/vega-rich-text-editor/extensions/tokens/token-toolbar-button-renderer.d.ts +47 -0
  243. package/dist/types/components/vega-rich-text-editor/interface.d.ts +52 -1
  244. package/dist/types/components/vega-rich-text-editor/public-api.d.ts +29 -0
  245. package/dist/types/components/vega-rich-text-editor/slimmers/controllers/extension-controller.d.ts +44 -0
  246. package/dist/types/components/vega-rich-text-editor/slimmers/controllers/helper/element-to-dto-strategy/element-to-dto-strategy.abstract.d.ts +10 -1
  247. package/dist/types/components/vega-rich-text-editor/slimmers/renderers/toolbar-renderer.d.ts +6 -0
  248. package/dist/types/components/vega-rich-text-editor/slimmers/renderers/tools/toolbar-button-slimmer.abstract.d.ts +4 -4
  249. package/dist/types/components/vega-rich-text-editor/slimmers/renderers/tools/visual-mode-toolbar-button-slimmer.abstract.d.ts +7 -7
  250. package/dist/types/components/vega-rich-text-editor/vega-rich-text-editor.d.ts +10 -0
  251. package/dist/types/components.d.ts +21 -0
  252. package/dist/types/helpers/public-api.d.ts +1 -1
  253. package/dist/types/types/components.type.d.ts +1 -0
  254. package/dist/types/types/public-api.d.ts +11 -0
  255. package/dist/vega/index.esm.js +1 -1
  256. package/dist/vega/p-03cc47b7.entry.js +1 -0
  257. package/dist/vega/p-07836d27.entry.js +1 -0
  258. package/dist/vega/p-079f5d94.entry.js +1 -0
  259. package/dist/vega/p-09cb98f3.entry.js +1 -0
  260. package/dist/vega/{p-fb232e29.entry.js → p-0b91bb73.entry.js} +1 -1
  261. package/dist/vega/p-15a78afd.entry.js +1 -0
  262. package/dist/vega/p-16075b30.entry.js +1 -0
  263. package/dist/vega/{p-67101f43.entry.js → p-1c08077c.entry.js} +1 -1
  264. package/dist/vega/{p-c5e862aa.js → p-1da54ff3.js} +1 -1
  265. package/dist/vega/p-20a180e4.js +1 -0
  266. package/dist/vega/p-25ddb070.entry.js +1 -0
  267. package/dist/vega/p-2788afe7.entry.js +1 -0
  268. package/dist/vega/p-2a1b3108.entry.js +1 -0
  269. package/dist/vega/p-2ee4def0.js +1 -0
  270. package/dist/vega/p-2f88ba36.entry.js +1 -0
  271. package/dist/vega/p-327cd6ec.entry.js +1 -0
  272. package/dist/vega/{p-f2a1fe6a.js → p-39c185a5.js} +1 -1
  273. package/dist/vega/p-3b1bedaf.entry.js +1 -0
  274. package/dist/vega/p-3c96bbe1.entry.js +1 -0
  275. package/dist/vega/p-3cdbee7e.js +1 -0
  276. package/dist/vega/p-3d0d8a21.entry.js +1 -0
  277. package/dist/vega/p-3d53858c.entry.js +1 -0
  278. package/dist/vega/{p-927cab0c.entry.js → p-3f3bbaaa.entry.js} +2 -2
  279. package/dist/vega/p-42c364e0.entry.js +1 -0
  280. package/dist/vega/p-4f56a427.entry.js +1 -0
  281. package/dist/vega/p-4f5a2b0c.entry.js +1 -0
  282. package/dist/vega/p-51d40b0d.entry.js +1 -0
  283. package/dist/vega/p-5420c1d4.entry.js +1 -0
  284. package/dist/vega/p-589b7ea3.entry.js +1 -0
  285. package/dist/vega/p-5d3c6a06.entry.js +1 -0
  286. package/dist/vega/p-5dec47da.entry.js +1 -0
  287. package/dist/vega/p-5f377954.js +1 -1
  288. package/dist/vega/p-6244b0ad.entry.js +1 -0
  289. package/dist/vega/p-63212cc1.js +1 -0
  290. package/dist/vega/p-6585cfd5.entry.js +1 -0
  291. package/dist/vega/p-6ba27010.js +1 -0
  292. package/dist/vega/{p-129f5938.js → p-6caa6bb2.js} +1 -1
  293. package/dist/vega/p-74ac2a48.js +1 -0
  294. package/dist/vega/p-76c7538a.entry.js +1 -0
  295. package/dist/vega/p-7d8eaca9.entry.js +1 -0
  296. package/dist/vega/p-7da6e7bd.js +1 -0
  297. package/dist/vega/p-81765b4b.entry.js +1 -0
  298. package/dist/vega/p-81fbf18f.entry.js +1 -0
  299. package/dist/vega/p-8682ee0a.entry.js +1 -0
  300. package/dist/vega/p-893d5dfa.js +1 -0
  301. package/dist/vega/p-8a484812.entry.js +1 -0
  302. package/dist/vega/p-8a6b820a.entry.js +1 -0
  303. package/dist/vega/p-8c9ea6f4.js +1 -0
  304. package/dist/vega/p-8e58d6cb.entry.js +1 -0
  305. package/dist/vega/p-8e812dca.entry.js +1 -0
  306. package/dist/vega/p-8f056ac2.js +1 -0
  307. package/dist/vega/{p-e66aef91.entry.js → p-9125ba84.entry.js} +1 -1
  308. package/dist/vega/p-92469fa1.entry.js +1 -0
  309. package/dist/vega/p-9ab3bb6f.entry.js +1 -0
  310. package/dist/vega/p-9ca0bdcc.js +1 -0
  311. package/dist/vega/p-a1362aa4.entry.js +1 -0
  312. package/dist/vega/p-a61e4bba.entry.js +1 -0
  313. package/dist/vega/p-a646b66d.js +1 -0
  314. package/dist/vega/p-a7b5f497.js +1 -0
  315. package/dist/vega/p-ac5c5221.entry.js +1 -0
  316. package/dist/vega/p-b1a5ff74.entry.js +1 -0
  317. package/dist/vega/p-b32f7aac.entry.js +1 -0
  318. package/dist/vega/{p-dc6f45af.entry.js → p-baafe7d9.entry.js} +1 -1
  319. package/dist/vega/{p-3a6abcd7.entry.js → p-bb51e020.entry.js} +1 -1
  320. package/dist/vega/{p-e764acd5.js → p-bb61f015.js} +1 -1
  321. package/dist/vega/p-bc0ae89a.entry.js +1 -0
  322. package/dist/vega/p-bd39af8a.entry.js +1 -0
  323. package/dist/vega/{p-cd18f0fe.js → p-bdd9ef3b.js} +1 -1
  324. package/dist/vega/{p-5f85811c.entry.js → p-c167fa41.entry.js} +1 -1
  325. package/dist/vega/{p-7ecf65ec.js → p-c2377afa.js} +1 -1
  326. package/dist/vega/p-c671f57e.js +1 -0
  327. package/dist/vega/p-c6a354b1.js +1 -0
  328. package/dist/vega/p-c7726252.js +1 -0
  329. package/dist/vega/p-ce1766fa.js +1 -0
  330. package/dist/vega/p-cfb2af9c.entry.js +1 -0
  331. package/dist/vega/{p-3bf95faf.entry.js → p-d2790023.entry.js} +2 -2
  332. package/dist/vega/p-d3bbfb1b.js +1 -0
  333. package/dist/vega/{p-5faa7313.entry.js → p-d9617358.entry.js} +1 -1
  334. package/dist/vega/p-d982babe.entry.js +1 -0
  335. package/dist/vega/p-dcae53cf.entry.js +1 -0
  336. package/dist/vega/p-ddfad815.entry.js +1 -0
  337. package/dist/vega/p-e00ed9bd.entry.js +1 -0
  338. package/dist/vega/p-e365aba9.entry.js +1 -0
  339. package/dist/vega/p-ebfc5739.entry.js +1 -0
  340. package/dist/vega/{p-aeccc7f8.js → p-f1436035.js} +1 -1
  341. package/dist/vega/p-fe2cb3a1.entry.js +1 -0
  342. package/dist/vega/p-ff3a8907.entry.js +1 -0
  343. package/dist/vega/vega.esm.js +1 -1
  344. package/package.json +1 -1
  345. package/dist/cjs/dom-node-subject-observer-factory-15130e50.js +0 -45
  346. package/dist/cjs/internal-icon-manager-f8677abb.js +0 -55
  347. package/dist/esm/dom-node-subject-observer-factory-1e456cd4.js +0 -43
  348. package/dist/esm/internal-icon-manager-7eac52c8.js +0 -53
  349. package/dist/vega/p-0070e970.entry.js +0 -1
  350. package/dist/vega/p-0169af6b.entry.js +0 -1
  351. package/dist/vega/p-03e9cbc8.js +0 -1
  352. package/dist/vega/p-04341cd4.entry.js +0 -1
  353. package/dist/vega/p-0664ca9c.js +0 -1
  354. package/dist/vega/p-074b73f8.js +0 -1
  355. package/dist/vega/p-08fb66a4.entry.js +0 -1
  356. package/dist/vega/p-0cf35281.entry.js +0 -1
  357. package/dist/vega/p-0e75ddb2.entry.js +0 -1
  358. package/dist/vega/p-13cb5a04.entry.js +0 -1
  359. package/dist/vega/p-18223240.js +0 -1
  360. package/dist/vega/p-19ce9ae6.js +0 -1
  361. package/dist/vega/p-27f922fe.entry.js +0 -1
  362. package/dist/vega/p-2c7b7dd6.entry.js +0 -1
  363. package/dist/vega/p-310f9e76.entry.js +0 -1
  364. package/dist/vega/p-330d7ba8.js +0 -1
  365. package/dist/vega/p-34fdbe7a.js +0 -1
  366. package/dist/vega/p-3d6c302d.js +0 -1
  367. package/dist/vega/p-42563036.entry.js +0 -1
  368. package/dist/vega/p-441a681b.js +0 -1
  369. package/dist/vega/p-4a357f30.entry.js +0 -1
  370. package/dist/vega/p-4e8b6eb6.entry.js +0 -1
  371. package/dist/vega/p-50dd3cf1.js +0 -1
  372. package/dist/vega/p-518722aa.js +0 -1
  373. package/dist/vega/p-5422fdc4.entry.js +0 -1
  374. package/dist/vega/p-5c36a6cb.entry.js +0 -1
  375. package/dist/vega/p-5d095f9b.entry.js +0 -1
  376. package/dist/vega/p-68806f9c.entry.js +0 -1
  377. package/dist/vega/p-6cf490d9.entry.js +0 -1
  378. package/dist/vega/p-6def20e1.js +0 -1
  379. package/dist/vega/p-78d3f99b.entry.js +0 -1
  380. package/dist/vega/p-792715f3.js +0 -1
  381. package/dist/vega/p-7a201c6e.entry.js +0 -1
  382. package/dist/vega/p-7c22a1c3.entry.js +0 -1
  383. package/dist/vega/p-7f329473.entry.js +0 -1
  384. package/dist/vega/p-80f1b680.js +0 -1
  385. package/dist/vega/p-82beb586.entry.js +0 -1
  386. package/dist/vega/p-84eb131b.entry.js +0 -1
  387. package/dist/vega/p-8c46e116.js +0 -1
  388. package/dist/vega/p-909820dd.entry.js +0 -1
  389. package/dist/vega/p-989e141d.entry.js +0 -1
  390. package/dist/vega/p-a29e5d32.js +0 -1
  391. package/dist/vega/p-a3942d0b.entry.js +0 -1
  392. package/dist/vega/p-a66533c1.entry.js +0 -1
  393. package/dist/vega/p-a9b831d8.entry.js +0 -1
  394. package/dist/vega/p-b1d0e4cb.entry.js +0 -1
  395. package/dist/vega/p-b34f9891.entry.js +0 -1
  396. package/dist/vega/p-b820e42f.entry.js +0 -1
  397. package/dist/vega/p-c4677b0c.entry.js +0 -1
  398. package/dist/vega/p-c467fe81.entry.js +0 -1
  399. package/dist/vega/p-c7762c86.entry.js +0 -1
  400. package/dist/vega/p-c9e57cf1.entry.js +0 -1
  401. package/dist/vega/p-d0b3e319.entry.js +0 -1
  402. package/dist/vega/p-d7b4ffed.entry.js +0 -1
  403. package/dist/vega/p-e4586f13.entry.js +0 -1
  404. package/dist/vega/p-e71c4a09.entry.js +0 -1
  405. package/dist/vega/p-ea66d9f7.entry.js +0 -1
  406. package/dist/vega/p-ebbaa112.entry.js +0 -1
  407. package/dist/vega/p-ec6819fe.entry.js +0 -1
  408. package/dist/vega/p-ec9a8f81.entry.js +0 -1
  409. package/dist/vega/p-ed01328c.entry.js +0 -1
  410. package/dist/vega/p-ed798cd4.entry.js +0 -1
  411. package/dist/vega/p-edb71a72.entry.js +0 -1
  412. package/dist/vega/p-f08a4adf.js +0 -1
  413. package/dist/vega/p-f4e23c23.entry.js +0 -1
  414. package/dist/vega/p-f825e8a2.entry.js +0 -1
  415. package/dist/vega/p-f9deb43e.entry.js +0 -1
  416. package/dist/vega/p-fdd930a9.entry.js +0 -1
  417. package/dist/vega/p-fe52c370.entry.js +0 -1
@@ -1,11 +1,11 @@
1
- import { A as ActionHandleStrategy, R as RTETextBlock, a as RTETextNode, b as AppendChildrenAction, c as ActionHandleStrategyRegistry, M as ModifyContentActionType, B as BlockInsertLineBreakStrategy, d as BlockInsertLineBreakWithBlocksStrategy, e as BlockSplitWithTextNodeStrategy, f as BlockReplaceNodesStrategy, g as BlockMergeNodesStrategy, I as InsertChildrenAfterAction, h as RemoveChildrenAction, S as SyncUpSelectionAction, i as InsertChildrenBeforeAction, j as BlockAnnotation, k as BlockAnnotationTypeEnum, l as RTEBlock, C as CustomStyleAnnotation, m as CustomClassAnnotation, n as CustomAttributeAnnotation, o as RTECodeBlock, s as stateEntityRenderingRegistry, N as NodeAnnotation, p as NodeAnnotationTypeEnum, q as RTEDecoratorNode, r as NodeTypeEnum, t as CommonAnnotation, u as AnnotationAction, v as ReplaceChildNodesAction, w as ModifyContentAction, x as SplitBlockWithNodeAction, H as HorizontalAlignmentAnnotationAction, y as BlockUpdateHorizontalAlignmentStrategy, z as RTEDTOClassManager, D as BlockDeleteNodeContentStrategy, U as UpdateTextAction, E as RemoveChildrenStrategy, F as RTE_TEXT_COLORS, G as RTE_DEFAULT_TEXT_COLOR } from './code-block-89a4dd13.js';
1
+ import { c as ActionHandleStrategy, d as RTETextBlock, a as RTETextNode, e as AppendChildrenAction, A as ActionHandleStrategyRegistry, b as ModifyContentActionType, B as BlockInsertLineBreakStrategy, f as BlockInsertLineBreakWithBlocksStrategy, g as BlockSplitWithTextNodeStrategy, h as BlockReplaceNodesStrategy, i as BlockMergeNodesStrategy, I as InsertChildrenAfterAction, j as RemoveChildrenAction, S as SyncUpSelectionAction, k as InsertChildrenBeforeAction, l as BlockAnnotation, m as BlockAnnotationTypeEnum, n as RTEBlock, C as CustomStyleAnnotation, o as CustomClassAnnotation, p as CustomAttributeAnnotation, q as RTECodeBlock, r as RTE_TEXT_COLORS, t as RTE_DEFAULT_TEXT_COLOR, s as stateEntityRenderingRegistry, N as NodeAnnotation, u as NodeAnnotationTypeEnum, v as RTEDecoratorNode, w as NodeTypeEnum, x as CommonAnnotation, y as AnnotationAction, z as ReplaceChildNodesAction, M as ModifyContentAction, D as SplitBlockWithNodeAction, H as HorizontalAlignmentAnnotationAction, E as BlockUpdateHorizontalAlignmentStrategy, R as RTEDTOClassManager, F as BlockDeleteNodeContentStrategy, U as UpdateTextAction, G as RemoveChildrenStrategy } from './code-block-68300b47.js';
2
2
  import { g as generateUUID } from './create-public-api-runtime-metrics-slimmer-bedf3a1e.js';
3
3
  import { i as isNonNullable } from './type-guard-12f7654b.js';
4
- import { C as ChangeManager } from './change-manager-6a7eb88c.js';
5
- import { d as domNodeSubjectFactory } from './dom-node-subject-factory-3c2e13f1.js';
6
- import { a as VegaInternalUpdateRTECursorPosition } from './vega-internal-event-id-5a143cd2.js';
7
4
  import { d as dashCaseToCamel } from './string-a953eafc.js';
8
5
  import { r as rgbToHex, i as isHTMLElement } from './ui-c20be16d.js';
6
+ import { C as ChangeManager } from './change-manager-6a7eb88c.js';
7
+ import { d as domNodeSubjectFactory } from './dom-node-subject-observer-factory-c7bc3035.js';
8
+ import { a as VegaInternalUpdateRTECursorPosition } from './vega-internal-event-id-5a143cd2.js';
9
9
  import { c as cleanObject } from './object-66c37948.js';
10
10
 
11
11
  /**
@@ -495,2006 +495,2080 @@ class BlockTransformToCodeBlockStrategy extends ActionHandleStrategy {
495
495
  }
496
496
 
497
497
  /**
498
- * Abstract class to define strategies for processing HTML elements
498
+ * Abstract class to define handler for generate the annotations
499
499
  */
500
- class ElementToDTOStrategy {
500
+ class AnnotationGeneratorStrategyAbstract {
501
501
  }
502
- /**
503
- * Class to represent the output of a strategy applied to HTML elements
504
- */
505
- class ElementToDTOStrategyOutput {
506
- constructor(currentStrategy, currentElements) {
507
- this.childrenOutput = [];
508
- this.currentStrategy = currentStrategy;
509
- this.currentElements = currentElements;
502
+
503
+ /** Handle bold annotation */
504
+ class BoldAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
505
+ /**
506
+ * @inheritDoc
507
+ */
508
+ canHandle(targetDto) {
509
+ return targetDto.name === 'RTETextNode';
510
510
  }
511
511
  /**
512
- * Set children output.
512
+ * Handle annotation.
513
513
  *
514
- * @param {ElementToDTOStrategyOutput[]} childrenOutput - children outputs.
514
+ * @param {HTMLElement} element - Current elements.
515
+ * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
516
+ * @returns {VegaRTETextAnnotations} - Annotation.
515
517
  */
516
- setChildrenOutput(childrenOutput) {
517
- this.childrenOutput = childrenOutput;
518
+ handle(element, parentAnnotations = {}) {
519
+ return this.isBold(element) || parentAnnotations.bold ? { bold: true } : {};
518
520
  }
519
521
  /**
520
- * Transform current output and children output to DTO
522
+ * Is bold element.
521
523
  *
522
- * @param {VegaRTETransformOptions} [options] - Options for transformation.
523
- * @returns {Nullable<RTEContentBlock>} - DTO.
524
+ * @param {HTMLElement} element - current element.
525
+ * @returns {boolean} - boolean.
524
526
  */
525
- toDto(options = { autoMatchFormat: true, skipCustomAnnotations: true }) {
526
- const currentBlock = this.currentStrategy.handle(this.currentElements, options);
527
- if (this.childrenOutput.length > 0 && currentBlock) {
528
- this.currentStrategy.appendChildBlocks(currentBlock, this.childrenOutput
529
- .map((childOutput) => childOutput.toDto(options))
530
- .filter(isNonNullable));
531
- }
532
- return currentBlock;
527
+ isBold(element) {
528
+ return (element.nodeName === 'STRONG' ||
529
+ element.nodeName === 'B' ||
530
+ element.style.fontWeight === 'bold' ||
531
+ element.style.fontWeight === '700' ||
532
+ element.classList.contains('v-rte--bold'));
533
533
  }
534
534
  }
535
535
 
536
- /**
537
- * Manager for registering and retrieving strategies that convert HTML elements to DTOs.
538
- */
539
- class elementToDTOClassStrategyManager {
540
- constructor() {
541
- this.elementToBlockStrategies = [];
542
- this.elementToNodeStrategies = [];
536
+ /** Handle custom attribute annotation */
537
+ class CustomAttributeAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
538
+ /**
539
+ * Can be handle.
540
+ *
541
+ * @param {RTEDtoClassPrototype} targetDto - Target DTO.
542
+ * @param {HtmlElementToAnnotationGenerateOptions} [options] - Options for annotation generator.
543
+ * @returns {boolean} - .
544
+ */
545
+ canHandle(targetDto, options) {
546
+ return !options.skipCustomAnnotations && !!targetDto;
543
547
  }
544
548
  /**
545
- * Registers a element to block strategy for converting HTML elements to DTOs. The new strategy is added to the beginning of the list to give it higher priority.
549
+ * Handle annotation.
546
550
  *
547
- * @param {ElementToDTOStrategy} strategy - The strategy to register.
551
+ * @param {HTMLElement} element - Current elements.
552
+ * @returns {VegaRTETextAnnotations} - Annotation.
548
553
  */
549
- registerElementToBlockStrategy(strategy) {
550
- if (!this.hasDuplicateStrategy(strategy, this.elementToBlockStrategies)) {
551
- this.elementToBlockStrategies.unshift(strategy);
552
- }
554
+ handle(element) {
555
+ const attributes = this.getAttributes(element);
556
+ return Object.keys(attributes).length > 0 ? { customAttribute: attributes } : {};
553
557
  }
554
558
  /**
555
- * Registers an element to node strategy for converting HTML elements to DTOs. The new strategy is added to the beginning of the list to give it higher priority.
559
+ * Obtain the custom attributes of element, excluding 'style' and 'class'.
556
560
  *
557
- * @param {ElementToDTOStrategy} strategy - The strategy to register.
561
+ * @param {HTMLElement} element - current element.
562
+ * @returns {Record<string, string>} - Record<string, string>.
558
563
  */
559
- registerElementToNodeStrategy(strategy) {
560
- if (!this.hasDuplicateStrategy(strategy, this.elementToNodeStrategies)) {
561
- this.elementToNodeStrategies.unshift(strategy);
562
- }
564
+ getAttributes(element) {
565
+ const attributeNames = element
566
+ .getAttributeNames()
567
+ .filter((attr) => attr !== 'style' && attr !== 'class' && this.isValidAttr(attr));
568
+ return attributeNames.reduce((acc, item) => {
569
+ acc[item] = element.getAttribute(item);
570
+ return acc;
571
+ }, {});
563
572
  }
564
573
  /**
565
- * Retrieves all registered element to block strategies for converting HTML elements to DTOs.
574
+ * Check if the attribute name is valid.
566
575
  *
567
- * @returns {ElementToDTOStrategy[]} - A set of all registered element to block strategies.
576
+ * @param {string} attr - Attribute name.
577
+ * @returns {boolean} - True if valid, false otherwise.
568
578
  */
569
- getElementToBlockStrategies() {
570
- return this.elementToBlockStrategies;
579
+ isValidAttr(attr) {
580
+ return /^[a-zA-Z_][\w-]*$/.test(attr);
571
581
  }
582
+ }
583
+
584
+ /** Handle custom class annotation */
585
+ class CustomClassAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
572
586
  /**
573
- * Retrieves all registered element to node strategies for converting HTML elements to DTOs.
587
+ * Can be handle.
574
588
  *
575
- * @returns {ElementToDTOStrategy[]} - A set of all registered element to node strategies.
589
+ * @param {RTEDtoClassPrototype} targetDto - Target DTO.
590
+ * @param {HtmlElementToAnnotationGenerateOptions} [options] - Options for annotation generator.
591
+ * @returns {boolean} - .
576
592
  */
577
- getElementToNodeStrategies() {
578
- return this.elementToNodeStrategies;
593
+ canHandle(targetDto, options) {
594
+ return !options.skipCustomAnnotations && !!targetDto;
579
595
  }
580
596
  /**
581
- * Checks if a strategy is already registered in the provided strategy list.
597
+ * Handle annotation.
582
598
  *
583
- * @param {ElementToDTOStrategy} strategy - The strategy to check for duplicates.
584
- * @param {ElementToDTOStrategy[]} strategyList - The list of strategies to check against.
585
- * @returns {boolean} - True if the strategy is a duplicate, false otherwise.
599
+ * @param {HTMLElement} element - Current elements.
600
+ * @returns {VegaRTETextAnnotations} - Annotation.
586
601
  */
587
- hasDuplicateStrategy(strategy, strategyList) {
588
- return strategyList.includes(strategy);
602
+ handle(element) {
603
+ const classes = this.getCustomClass(element);
604
+ return classes.length > 0 ? { customClass: classes } : {};
605
+ }
606
+ /**
607
+ * Get the custom class
608
+ *
609
+ * @param {HTMLElement} element - current element.
610
+ * @returns {string[]} - the class after .
611
+ */
612
+ getCustomClass(element) {
613
+ return element.classList
614
+ .toString()
615
+ .split(' ')
616
+ .filter((item) => !item.includes('v-rte') && item !== '');
589
617
  }
590
618
  }
591
- const ElementToDTOClassStrategyManager = new elementToDTOClassStrategyManager();
592
619
 
593
- /** Element to DTO processor */
594
- class ElementToDtoStrategyProcessor {
620
+ /** Handle custom style annotation */
621
+ class CustomStyleAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
595
622
  /**
596
- * Transform process.
623
+ * Can be handle.
597
624
  *
598
- * @param {HTMLElement[]} elements - Current elements.
599
- * @param {VegaRTETransformOptions} [options] - Options for transformation.
600
- * @returns {ElementToDTOStrategyOutput[]} - outputs.
625
+ * @param {RTEDtoClassPrototype} targetDto - Target DTO.
626
+ * @param {HtmlElementToAnnotationGenerateOptions} [options] - Options for annotation generator.
627
+ * @returns {boolean} - .
601
628
  */
602
- process(elements, options = { autoMatchFormat: true, skipCustomAnnotations: true }) {
603
- const strategies = this.getElementToBlockStrategies();
604
- const outputs = [];
605
- for (let i = 0; i < elements.length; i++) {
606
- if (this.isInvalidElement(elements[i]))
607
- continue;
608
- let canHandledCount = 0;
609
- for (const strategy of strategies) {
610
- canHandledCount = strategy.canHandle(elements, i, options);
611
- if (canHandledCount > 0) {
612
- const handledElements = elements.slice(i, i + canHandledCount);
613
- const output = new ElementToDTOStrategyOutput(strategy, handledElements);
614
- if (canHandledCount === 1 && strategy.shouldProceedToElementChildren()) {
615
- output.setChildrenOutput(this.process(Array.from(handledElements[0].childNodes), options));
616
- }
617
- outputs.push(output);
618
- i += canHandledCount - 1;
619
- break;
620
- }
621
- }
622
- if (canHandledCount === 0 && i < elements.length) {
623
- const elementChildren = Array.from(elements[i].childNodes);
624
- const childrenOutputs = this.process(Array.from(elementChildren), options);
625
- if (childrenOutputs.length > 0) {
626
- outputs.push(...childrenOutputs);
627
- }
628
- }
629
- }
630
- return outputs;
629
+ canHandle(targetDto, options) {
630
+ return !options.skipCustomAnnotations && !!targetDto;
631
631
  }
632
632
  /**
633
- * Checks if the given element is valid to parse.
633
+ * Handle annotation.
634
634
  *
635
- * @param {HTMLElement} element - The pasted element.
636
- * @returns {boolean} Is valid
635
+ * @param {HTMLElement} element - Current elements.
636
+ * @returns {VegaRTETextAnnotations} - Annotation.
637
637
  */
638
- isInvalidElement(element) {
639
- if (element.nodeType === Node.COMMENT_NODE)
640
- return true;
641
- return ['META', 'STYLE'].includes(element.nodeName);
638
+ handle(element) {
639
+ const styles = this.generateCustomStyleAnnotations(element);
640
+ return Object.keys(styles).length > 0 ? { customStyle: styles } : {};
642
641
  }
643
642
  /**
644
- * Get the register element to block strategies.
643
+ * Obtain and format the style of element.
645
644
  *
646
- * @returns {ElementToDTOStrategy[]} - The register element to block strategies.
645
+ * @param {HTMLElement} element - current element.
646
+ * @returns {AnnotationStyle} - Record<string, string>.
647
647
  */
648
- getElementToBlockStrategies() {
649
- return ElementToDTOClassStrategyManager.getElementToBlockStrategies();
648
+ generateCustomStyleAnnotations(element) {
649
+ const customStyle = element.getAttribute('style');
650
+ if (!customStyle)
651
+ return {};
652
+ const styleValue = customStyle.split(';').filter(Boolean);
653
+ return styleValue
654
+ .filter((key) => key !== ' ')
655
+ .map((key) => {
656
+ // to remove redundant quote pairs if needed, for example: ['fontFamily: "Roboto Mono"'] will be updated to ['fontFamily: Roboto Mono']
657
+ const styleObject = key.replace(/(['"])(.*?)\1/g, '$2').split(':');
658
+ const styleKey = dashCaseToCamel(styleObject[0].trim());
659
+ return {
660
+ [styleKey]: styleObject[1].trim().replace(';', ''),
661
+ };
662
+ })
663
+ .reduce((current, obj) => (Object.assign(Object.assign({}, current), obj)), {});
650
664
  }
651
665
  }
652
- const ElementToDtoStrategyProcessor$1 = new ElementToDtoStrategyProcessor();
653
666
 
654
- /**
655
- * Update the cursor position in the editor.
656
- */
657
- class UpdateCursorPositionStrategy extends ActionHandleStrategy {
667
+ /** Handle indent annotation */
668
+ class IndentAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
658
669
  /**
659
670
  * @inheritDoc
660
671
  */
661
- handleAction(action, target) {
662
- const { offset, nextFocusNode } = action;
663
- const host = stateEntityRenderingRegistry.getDOMByEntity(target);
664
- if (host) {
665
- ChangeManager.notify(domNodeSubjectFactory.getSubject(host, VegaInternalUpdateRTECursorPosition), {
666
- node: nextFocusNode,
667
- offset,
668
- });
669
- }
672
+ canHandle(targetDto) {
673
+ return ['RTETextBlock', 'RTEListItemBlock', 'RTEListBlock'].includes(targetDto.name);
670
674
  }
671
- }
672
-
673
- /**
674
- * Append new block array or node array to block or VegaRTEContent instance strategy.
675
- */
676
- class AppendChildrenStrategy extends ActionHandleStrategy {
677
675
  /**
678
- * @inheritDoc
676
+ * Handle annotation.
677
+ *
678
+ * @param {HTMLElement} element - Current elements.
679
+ * @returns {VegaRTEBlockAnnotations} - Annotation.
679
680
  */
680
- handleAction(action, target) {
681
- const newBlocks = action.entityToBeAppended;
682
- if (target.children) {
683
- newBlocks.forEach((block) => {
684
- block.parent = target;
685
- });
686
- // This line is used to fix the typescript error `This expression is not callable`. https://github.com/microsoft/TypeScript/issues/44373
687
- const arrayFixed = target.children;
688
- target.children = arrayFixed.concat(newBlocks);
681
+ handle(element) {
682
+ const indent = this.getIndent(element);
683
+ return indent ? { indent: indent } : {};
684
+ }
685
+ /**
686
+ * Get indent of current element.
687
+ *
688
+ * @param {HTMLElement} element - current element.
689
+ * @returns {Nullable<number>} - Indent.
690
+ */
691
+ getIndent(element) {
692
+ const style = element.style;
693
+ let marginLeft;
694
+ if (style.marginLeft) {
695
+ marginLeft = style.marginLeft;
696
+ }
697
+ else if (style.margin) {
698
+ const margins = style.margin.split(' ');
699
+ switch (margins.length) {
700
+ case 4:
701
+ marginLeft = margins[3];
702
+ break;
703
+ case 2:
704
+ case 3:
705
+ marginLeft = margins[1];
706
+ break;
707
+ default:
708
+ marginLeft = margins[0];
709
+ break;
710
+ }
711
+ }
712
+ else {
713
+ return null;
689
714
  }
715
+ const marginLeftNumber = Number(marginLeft.replace('px', ''));
716
+ return marginLeftNumber && marginLeftNumber >= 0 ? Math.floor(marginLeftNumber / 16) : null;
690
717
  }
691
718
  }
692
719
 
693
- /**
694
- * Insert children at the front of the block strategy.
695
- */
696
- class InsertChildrenBeforeStrategy extends ActionHandleStrategy {
720
+ /** Handle text align annotation */
721
+ class TextAlignAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
697
722
  /**
698
- * @inheritDoc
723
+ * Can be handle.
724
+ *
725
+ * @param {RTEDtoClassPrototype} targetDto - Target DTO.
726
+ * @returns {boolean} - .
699
727
  */
700
- handleAction(action, target) {
701
- this.replaceElementWithElements(target, action.referChildren, [
702
- ...action.childrenToBeInserted,
703
- action.referChildren,
704
- ]);
728
+ canHandle(targetDto) {
729
+ return ['RTETextBlock', 'RTEListItemBlock', 'RTEListBlock'].includes(targetDto.name);
705
730
  }
706
731
  /**
707
- * Replaces a specific block or node with an array of blocks or nodes within RTEContentBlock array.
732
+ * Handle annotation.
708
733
  *
709
- * @param {RTEBlock | VegaRTEContent} target - The block or the VegaRTEContent instance.
710
- * @param {RTEBlock | RTENode} referElement - Used as a reference element to identify the element that needs to be replaced in the array.
711
- * @param {RTEBlock[] | RTENode[]} elements - An array of block or node objects that you want to replace the `referElement` with in the array.
734
+ * @param {HTMLElement} element - Current elements.
735
+ * @returns {VegaRTEBlockAnnotations} - Annotation.
712
736
  */
713
- replaceElementWithElements(target, referElement, elements) {
714
- if (target.children) {
715
- elements.forEach((block) => {
716
- block.parent = target;
717
- });
718
- const arrayFixed = target.children;
719
- target.children = arrayFixed.flatMap((block) => {
720
- if (block === referElement) {
721
- return elements;
722
- }
723
- else {
724
- return block;
725
- }
726
- });
737
+ handle(element) {
738
+ const textAlign = this.getTextAlign(element);
739
+ return textAlign ? { textAlign: textAlign } : {};
740
+ }
741
+ /**
742
+ * Get text align of current element.
743
+ *
744
+ * @param {HTMLElement} element - current element.
745
+ * @returns {Nullable<VegaRTEBlockAlignment>} - Text align.
746
+ */
747
+ getTextAlign(element) {
748
+ const classList = element.classList;
749
+ if (classList.contains(`v-rte--horizontal-alignment-left`)) {
750
+ return 'left';
751
+ }
752
+ else if (classList.contains(`v-rte--horizontal-alignment-center`)) {
753
+ return 'center';
754
+ }
755
+ else if (classList.contains(`v-rte--horizontal-alignment-right`)) {
756
+ return 'right';
757
+ }
758
+ else if (classList.contains(`v-rte--horizontal-alignment-justify`)) {
759
+ return 'justify';
760
+ }
761
+ const style = element.style;
762
+ switch (style.textAlign) {
763
+ case 'center':
764
+ return 'center';
765
+ case 'right':
766
+ return 'right';
767
+ case 'justify':
768
+ return 'justify';
769
+ case 'left':
770
+ return 'left';
771
+ default:
772
+ return null;
727
773
  }
728
774
  }
729
775
  }
730
776
 
731
- /**
732
- * Insert children at the front of the block strategy.
733
- */
734
- class InsertChildrenAfterStrategy extends InsertChildrenBeforeStrategy {
777
+ /** Handle code annotation */
778
+ class CodeAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
735
779
  /**
736
780
  * @inheritDoc
737
781
  */
738
- handleAction(action, target) {
739
- this.replaceElementWithElements(target, action.referChildren, [
740
- action.referChildren,
741
- ...action.childrenToBeInserted,
742
- ]);
743
- }
744
- }
745
-
746
- /**
747
- * Annotation for image
748
- */
749
- class ImageAnnotation extends NodeAnnotation {
750
- constructor(size, alt) {
751
- super();
752
- this.type = NodeAnnotationTypeEnum.IMAGE;
753
- this.size = size;
754
- this.alt = alt;
782
+ canHandle(targetDto) {
783
+ return targetDto.name === 'RTETextNode';
755
784
  }
756
785
  /**
757
- * Generate the map item for the annotation
786
+ * Handle annotation.
758
787
  *
759
- * @param {string} size - Image size
760
- * @param {string} alt - Image alt
761
- * @returns {[NodeAnnotationTypeEnum.IMAGE, ImageAnnotation]} Map item for the annotation
788
+ * @param {HTMLElement} element - Current elements.
789
+ * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
790
+ * @returns {VegaRTETextAnnotations} - Annotation.
762
791
  */
763
- static from(size, alt) {
764
- return [NodeAnnotationTypeEnum.IMAGE, new ImageAnnotation(size, alt)];
792
+ handle(element, parentAnnotations = {}) {
793
+ return this.isCode(element) || parentAnnotations.code ? { code: true } : {};
765
794
  }
766
795
  /**
767
- * Generate the JSON representation of the annotation
796
+ * Is code element.
768
797
  *
769
- * @returns {Nullable<Record<string, unknown>>} JSON representation of the annotation
798
+ * @param {HTMLElement} element - current element.
799
+ * @returns {boolean} - boolean.
770
800
  */
771
- toJSON() {
772
- return isNonNullable(this.alt)
773
- ? {
774
- size: this.size,
775
- alt: this.alt,
776
- }
777
- : {
778
- size: this.size,
779
- };
801
+ isCode(element) {
802
+ return (element.classList.contains('v-rte--code') ||
803
+ element.nodeName === 'CODE' ||
804
+ element.nodeName === 'PRE' ||
805
+ element.style.fontFamily === 'monospace' ||
806
+ element.style.fontFamily.replace(/["']/g, '') === 'Roboto Mono');
780
807
  }
808
+ }
809
+
810
+ /** Handle color annotation */
811
+ class ColorAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
781
812
  /**
782
813
  * @inheritDoc
783
814
  */
784
- clone() {
785
- return new ImageAnnotation(this.size, this.alt);
815
+ canHandle(targetDto) {
816
+ return targetDto.name === 'RTETextNode';
786
817
  }
787
818
  /**
788
- * @inheritDoc
819
+ * Handle annotation.
820
+ *
821
+ * @param {HTMLElement} element - Current elements.
822
+ * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
823
+ * @returns {VegaRTETextAnnotations} - Annotation.
789
824
  */
790
- renderClass(options) {
791
- if (options === null || options === void 0 ? void 0 : options.standalone)
792
- return null;
793
- return this.size ? `v-rte--image-size-${this.size}` : null;
825
+ handle(element, parentAnnotations = {}) {
826
+ const color = this.getColor(element) || parentAnnotations.textColor;
827
+ return color ? { textColor: color } : {};
794
828
  }
795
829
  /**
796
- * @inheritDoc
830
+ * Get current color of element.
831
+ *
832
+ * @param {HTMLElement} element - current element.
833
+ * @returns {Nullable<string>} - color.
797
834
  */
798
- renderStyle(options) {
799
- if (!(options === null || options === void 0 ? void 0 : options.standalone))
835
+ getColor(element) {
836
+ var _a;
837
+ const color = element.style.color;
838
+ const hexColor = (_a = rgbToHex(color)) === null || _a === void 0 ? void 0 : _a.toUpperCase();
839
+ if (hexColor) {
840
+ // We don't display default text color as inline style, because we defined it in the vega-rich-text-content.scss.
841
+ const colorSchema = RTE_TEXT_COLORS.filter((item) => item.key !== RTE_DEFAULT_TEXT_COLOR.key).find((schema) => schema.light === hexColor || schema.dark === hexColor);
842
+ if (colorSchema)
843
+ return colorSchema.key;
800
844
  return null;
801
- const baseStyle = { verticalAlign: 'bottom' };
802
- switch (this.size) {
803
- case 'sm': {
804
- return Object.assign(Object.assign({}, baseStyle), { width: '25%' });
805
- }
806
- case 'md': {
807
- return Object.assign(Object.assign({}, baseStyle), { width: '50%' });
808
- }
809
- case 'lg': {
810
- return Object.assign(Object.assign({}, baseStyle), { width: '100%' });
845
+ }
846
+ else {
847
+ for (const color of RTE_TEXT_COLORS) {
848
+ if (element.style.color.includes(color.key)) {
849
+ return color.key;
850
+ }
811
851
  }
852
+ return null;
812
853
  }
813
854
  }
814
855
  }
815
856
 
816
- /**
817
- * Update the image node annotation map strategy.
818
- */
819
- class ImageSetAnnotationMapStrategy extends ActionHandleStrategy {
857
+ /** Handle italic annotation */
858
+ class ItalicAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
820
859
  /**
821
860
  * @inheritDoc
822
861
  */
823
- handleAction(action, target) {
824
- const annotation = action.toAnnotation();
825
- target.annotationMap.set(annotation.type, annotation);
862
+ canHandle(targetDto) {
863
+ return targetDto.name === 'RTETextNode';
826
864
  }
827
- }
828
-
829
- /**
830
- * The image node update property url strategy.
831
- */
832
- class ImageUpdateUrlStrategy extends ActionHandleStrategy {
833
865
  /**
834
- * @inheritDoc
866
+ * Handle annotation.
867
+ *
868
+ * @param {HTMLElement} element - Current elements.
869
+ * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
870
+ * @returns {VegaRTETextAnnotations} - Annotation.
835
871
  */
836
- handleAction(action, target) {
837
- target.url = action.url;
838
- }
872
+ handle(element, parentAnnotations = {}) {
873
+ return this.isItalic(element) || parentAnnotations.italic ? { italic: true } : {};
874
+ }
875
+ /**
876
+ * Is italic element.
877
+ *
878
+ * @param {HTMLElement} element - current element.
879
+ * @returns {boolean} - boolean.
880
+ */
881
+ isItalic(element) {
882
+ return (element.nodeName === 'I' ||
883
+ element.style.fontStyle === 'italic' ||
884
+ element.nodeName === 'EM' ||
885
+ element.classList.contains('v-rte--italic'));
886
+ }
839
887
  }
840
888
 
841
- var __rest = (undefined && undefined.__rest) || function (s, e) {
842
- var t = {};
843
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
844
- t[p] = s[p];
845
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
846
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
847
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
848
- t[p[i]] = s[p[i]];
849
- }
850
- return t;
851
- };
852
- /**
853
- * Image node
854
- */
855
- class RTEImageNode extends RTEDecoratorNode {
856
- constructor(id, url, parentBlock, annotationMap) {
857
- super(id, annotationMap);
858
- this.type = NodeTypeEnum.IMAGE;
859
- this.url = url;
860
- this.parent = parentBlock;
889
+ /** Handle link annotation */
890
+ class LinkAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
891
+ constructor() {
892
+ super(...arguments);
893
+ this.handlers = [
894
+ new CustomAttributeAnnotationHandler(),
895
+ new CustomClassAnnotationHandler(),
896
+ new CustomStyleAnnotationHandler(),
897
+ ];
861
898
  }
862
899
  /**
863
- * Converts a VegaRTEImageNode into an RTEImageNode by mapping nodes and creating annotations.
900
+ * Can be handle.
864
901
  *
865
- * @param {VegaRTEImageNode} node - The node to be converted.
866
- * @param {RTEImageBlock} parentBlock - The parent block
867
- * @param {VegaRTETransformOptions} options - Optional transformation options.
868
- * @returns {RTEImageNode} An instance of `RTEImageBlock`
902
+ * @param {RTEDtoClassPrototype} targetDto - Target DTO.
903
+ * @returns {boolean} - .
869
904
  */
870
- static from(node, parentBlock, options = { autoMatchFormat: true }) {
871
- const imageNode = new RTEImageNode(node.id, node.url, parentBlock);
872
- const autoMatchFormat = !!options.autoMatchFormat;
873
- const _a = Object.assign({}, node.annotations), { size } = _a, otherAnnotations = __rest(_a, ["size"]);
874
- const annotations = Object.assign(Object.assign({}, otherAnnotations), { size: size !== null && size !== void 0 ? size : (autoMatchFormat ? 'md' : undefined) });
875
- imageNode.annotationMap = new Map(Object.keys(annotations)
876
- .map((type) => {
877
- if (type === 'size' || type === 'alt') {
878
- return ImageAnnotation.from(annotations.size, annotations.alt);
879
- }
880
- return this.createAnnotationEntity(type, annotations[type]);
881
- })
882
- .filter(isNonNullable));
883
- return imageNode;
905
+ canHandle(targetDto) {
906
+ return targetDto.name === 'RTETextNode';
884
907
  }
885
908
  /**
886
- * @inheritDoc
909
+ * Handle annotation.
910
+ *
911
+ * @param {HTMLElement} element - Current elements.
912
+ * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
913
+ * @returns {VegaRTETextAnnotations} - Annotation.
887
914
  */
888
- toJSON() {
889
- const annotations = Array.from(this.annotationMap.values())
890
- .filter((annotation) => annotation instanceof ImageAnnotation || annotation instanceof CommonAnnotation)
891
- .reduce((record, annotation) => {
892
- return Object.assign(Object.assign({}, record), annotation.toJSON());
893
- }, {});
894
- if (annotations.alt == '')
895
- delete annotations.alt;
896
- return Object.assign(Object.assign({ id: this.id }, (Object.keys(annotations).length > 0 ? { annotations } : {})), { type: 'image', url: this.url });
915
+ handle(element, parentAnnotations = {}) {
916
+ if (parentAnnotations.link)
917
+ return { link: parentAnnotations.link };
918
+ return element.tagName === 'A' ? { link: this.generateLinkAnnotations(element) } : {};
897
919
  }
898
920
  /**
899
- * @inheritDoc
921
+ * Generate link annotations.
922
+ *
923
+ * @param {HTMLElement} element - Current elements.
924
+ * @returns {VegaRTELink} - link annotations.
900
925
  */
901
- clone() {
902
- return new RTEImageNode(this.id, this.url, this.parent, super.cloneAnnotations());
926
+ generateLinkAnnotations(element) {
927
+ const annotations = {
928
+ href: element.getAttribute('href') || '',
929
+ groupKey: generateUUID(),
930
+ };
931
+ this.handlers.forEach((handler) => {
932
+ Object.assign(annotations, handler.handle(element));
933
+ });
934
+ return annotations;
903
935
  }
936
+ }
937
+
938
+ /** Handle strike through annotation */
939
+ class StrikeThroughAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
904
940
  /**
905
941
  * @inheritDoc
906
942
  */
907
- toHtml() {
908
- const imageAnnotation = this.getAnnotationByType(NodeAnnotationTypeEnum.IMAGE);
909
- const attrStr = super.generateAttributeString(...[
910
- imageAnnotation && imageAnnotation.alt ? `alt="${imageAnnotation.alt}"` : null,
911
- `src="${this.url}"`,
912
- imageAnnotation && imageAnnotation.size ? `data-size="${imageAnnotation.size}"` : null,
913
- ].filter(isNonNullable));
914
- return `<img${attrStr}>`;
943
+ canHandle(targetDto) {
944
+ return targetDto.name === 'RTETextNode';
915
945
  }
916
946
  /**
917
- * @inheritDoc
947
+ * Handle annotation.
948
+ *
949
+ * @param {HTMLElement} element - Current elements.
950
+ * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
951
+ * @returns {VegaRTETextAnnotations} - Annotation.
918
952
  */
919
- doAnnotationActionApply(action) {
920
- const strategy = ActionHandleStrategyRegistry.get(AnnotationAction.name, RTEImageNode.name);
921
- if (strategy) {
922
- strategy.execute(action, this);
923
- }
953
+ handle(element, parentAnnotations = {}) {
954
+ return this.isStrikethrough(element) || parentAnnotations.strikethrough
955
+ ? { strikethrough: true }
956
+ : {};
924
957
  }
925
958
  /**
926
- * @inheritDoc
959
+ * Is strikethrough element.
960
+ *
961
+ * @param {HTMLElement} element - current element.
962
+ * @returns {boolean} - boolean.
927
963
  */
928
- doModifyActionApply(action) {
929
- ActionHandleStrategyRegistry.executeTheStrategy(action, this);
964
+ isStrikethrough(element) {
965
+ return (element.style.textDecoration.includes('line-through') ||
966
+ element.nodeName === 'S' ||
967
+ element.nodeName === 'DEL' ||
968
+ element.classList.contains('v-rte--strikethrough'));
930
969
  }
931
970
  }
932
- (() => {
933
- ActionHandleStrategyRegistry.register(ModifyContentActionType.UPDATE_IMAGE_NODE_URL, RTEImageNode.name, new ImageUpdateUrlStrategy());
934
- ActionHandleStrategyRegistry.register(AnnotationAction.name, RTEImageNode.name, new ImageSetAnnotationMapStrategy());
935
- })();
936
971
 
937
- /**
938
- * Split the current image block with a special position strategy.
939
- */
940
- class BlockSplitWithImageNodeStrategy extends ActionHandleStrategy {
972
+ /** Handle underline annotation */
973
+ class UnderlineAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
941
974
  /**
942
975
  * @inheritDoc
943
976
  */
944
- handleAction(action, target) {
945
- action.newBlock = this.splitImageNodes(action.splitPointNode, action.startOffsetOfNode, target);
977
+ canHandle(targetDto) {
978
+ return targetDto.name === 'RTETextNode';
946
979
  }
947
980
  /**
948
- * The image offset should be 0 or 1
949
- * <vega-rich-text-image-editor><img /></vega-rich-text-image-editor>
981
+ * Handle annotation.
950
982
  *
951
- * @param {RTEImageNode} imageNode The split point image node.
952
- * @param {number} imageOffset The cursor point 0 | 1.
953
- * @param {RTEImageBlock} target The image block.
954
- * @returns {Nullable<RTEBlock>} The new block after split
983
+ * @param {HTMLElement} element - Current elements.
984
+ * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
985
+ * @returns {VegaRTETextAnnotations} - Annotation.
955
986
  */
956
- splitImageNodes(imageNode, imageOffset, target) {
957
- const nodesSplitIndex = target.children.indexOf(imageNode);
958
- if (nodesSplitIndex > -1) {
959
- const beforeNodes = target.children.slice(0, nodesSplitIndex + imageOffset);
960
- const afterNodes = target.children.slice(nodesSplitIndex + imageOffset);
961
- target.apply(new ReplaceChildNodesAction(beforeNodes));
962
- const newBlock = this.cloneWithNodes(afterNodes, target);
963
- target.parent.apply(new InsertChildrenAfterAction(target, newBlock));
964
- return newBlock;
965
- }
987
+ handle(element, parentAnnotations = {}) {
988
+ return this.isUnderline(element) || parentAnnotations.underline ? { underline: true } : {};
966
989
  }
967
990
  /**
968
- * Creates a new RTEImageBlock instance with the provided RTEImageNode instances appended to it.
991
+ * Is underline element.
969
992
  *
970
- * @param {RTEImageNode[]} nodes - An array of RTEImageNode objects that will be used to create a new RTEImageBlock instance.
971
- * @param {RTEImageBlock} target The image block.
972
- * @returns {RTEImageBlock} A new `RTEImageBlock` object with the provided `nodes` appended to it.
993
+ * @param {HTMLElement} element - current element.
994
+ * @returns {boolean} - boolean.
973
995
  */
974
- cloneWithNodes(nodes, target) {
975
- const block = target.createNewImageBlock();
976
- block.children = [];
977
- block.apply(new AppendChildrenAction(nodes));
978
- return block;
979
- }
980
- }
981
-
982
- /**
983
- * Break the current block after press enter, this action is similar with the SplitBlockWithNodeAction,
984
- * The SplitBlockWithNodeAction split the current block to two same type blocks, but this action will create new paragraph or list item when break at start or end.
985
- * The property `newBlock` use to store the new create block if need.
986
- *
987
- * @example currentBlock.apply(new InsertNewParagraphAction(startContainerNode, startOffset))
988
- */
989
- class InsertNewParagraphAction extends ModifyContentAction {
990
- constructor(startContainerNode, startOffset) {
991
- super();
992
- this.type = ModifyContentActionType.INSERT_NEW_PARAGRAPH;
993
- this.startContainerNode = startContainerNode;
994
- this.startOffset = startOffset;
996
+ isUnderline(element) {
997
+ return (element.style.textDecoration.includes('underline') ||
998
+ element.nodeName === 'U' ||
999
+ element.nodeName === 'INS' ||
1000
+ element.classList.contains('v-rte--underline'));
995
1001
  }
996
1002
  }
997
1003
 
998
- /**
999
- * The image block insert line break strategy.
1000
- */
1001
- class ImageInsertLineBreakStrategy extends ActionHandleStrategy {
1004
+ /** Handle text style annotation */
1005
+ class TextStyleAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1002
1006
  /**
1003
- * The image block not support insert the line break node, so invoke the insert new paragraph logic directly.
1007
+ * Can be handle.
1004
1008
  *
1005
- * @param {LineBreakSingleBlockAction} action - The action instance.
1006
- * @param {RTEImageBlock} target - The image block.
1009
+ * @param {RTEDtoClassPrototype} targetDto - Target DTO.
1010
+ * @param {HtmlElementToAnnotationGenerateOptions} options - Options for annotation generator.
1011
+ * @returns {boolean} - .
1007
1012
  */
1008
- handleAction(action, target) {
1009
- const insertNewParagraphAction = new InsertNewParagraphAction(action.startContainerNode, action.startOffset);
1010
- target.apply(insertNewParagraphAction);
1011
- const newBlock = insertNewParagraphAction.newBlock;
1012
- if (newBlock) {
1013
- action.lineBreakNode = newBlock.children[0];
1014
- }
1013
+ canHandle(targetDto, options) {
1014
+ return !!options.autoMatchFormat && targetDto.name === 'RTETextBlock';
1015
1015
  }
1016
- }
1017
-
1018
- /**
1019
- * Insert a line break node into multiple blocks selection at special position strategy.
1020
- */
1021
- class ImageInsertLineBreakWithBlocksStrategy extends ActionHandleStrategy {
1022
1016
  /**
1023
- * @inheritDoc
1017
+ * Handle annotation.
1018
+ *
1019
+ * @param {HTMLElement} element - Current elements.
1020
+ * @returns {VegaRTETextBlockAnnotations} - Annotation.
1024
1021
  */
1025
- handleAction(action, target) {
1026
- action.lineBreakNode = this.lineBreakMultipleBlocks(action.selectedBlocks, target);
1022
+ handle(element) {
1023
+ const textStyle = this.getTextStyle(element);
1024
+ return textStyle ? { textStyle: textStyle } : {};
1027
1025
  }
1028
1026
  /**
1029
- * Inserts a new paragraph block with a line break after a selected block of text in a rich text editor.
1027
+ * Get the node type of element. The element type is determined in the following
1028
+ * order: "data-type" attribute, node name, font size and class name.
1030
1029
  *
1031
- * @param {RTEBlock[]} selectedBlocks - An array of RTEBlock objects that represent the blocks that have been selected for a specific action in the Rich Text Editor.
1032
- * @param {RTEImageBlock} target - The image block.
1033
- * @returns {Nullable<RTETextNode>} Returns a Nullable RTETextNode.
1030
+ * @param {HTMLElement} element - element.
1031
+ * @returns {Nullable<VegaRTETextStyleType>} - node type.
1034
1032
  */
1035
- lineBreakMultipleBlocks(selectedBlocks, target) {
1036
- const newParagraph = RTETextBlock.from({
1037
- id: generateUUID(),
1038
- type: 'paragraph',
1039
- nodes: [{ id: generateUUID(), type: 'text', text: '\n' }],
1040
- });
1041
- target.parent.apply(new InsertChildrenAfterAction(target, newParagraph));
1042
- const afterNodes = this.concatBlocksNodes(selectedBlocks.slice(1));
1043
- if (afterNodes.length === 0 || (afterNodes[0] && afterNodes[0].text === '')) {
1044
- afterNodes.push(new RTETextNode(generateUUID(), '\n', newParagraph));
1045
- }
1046
- newParagraph.apply(new AppendChildrenAction(afterNodes));
1047
- return newParagraph['children'][0];
1033
+ getTextStyle(element) {
1034
+ const byDataType = this.getElementTypeByDataType(element);
1035
+ if (byDataType)
1036
+ return byDataType;
1037
+ const byNodeName = this.getElementTypeByNodeName(element);
1038
+ if (byNodeName)
1039
+ return byNodeName;
1040
+ const byFontSize = this.getElementTypeByFontSize(element);
1041
+ if (byFontSize)
1042
+ return byFontSize;
1043
+ const byClassName = this.getElementTypeByClassName(element);
1044
+ if (byClassName)
1045
+ return byClassName;
1046
+ return null;
1048
1047
  }
1049
1048
  /**
1050
- * Concat the child nodes of multiple RTEBlocks if both are not images.
1049
+ * Get the element type by data-type attribute.
1051
1050
  *
1052
- * @param {RTEBlock[]} blocks - multiple block of content in a rich text editor, such as a paragraph, heading, image, etc.
1053
- * @returns {RTENode[]} Array of connected block nodes
1051
+ * @param {HTMLElement} element - element.
1052
+ * @returns {Nullable<VegaRTETextStyleType>} - element type or null if not found.
1054
1053
  */
1055
- concatBlocksNodes(blocks) {
1056
- const nodes = [];
1057
- blocks.map((block) => {
1058
- if (block.type !== 'image') {
1059
- nodes.push(...block.children);
1060
- block.parent.apply(new RemoveChildrenAction(block));
1061
- }
1062
- });
1063
- return nodes;
1054
+ getElementTypeByDataType(element) {
1055
+ if (element.nodeType !== Node.TEXT_NODE && element.hasAttribute('data-type')) {
1056
+ return element.getAttribute('data-type');
1057
+ }
1058
+ return null;
1064
1059
  }
1065
- }
1066
-
1067
- /**
1068
- * Insert a image node at the special position of image block.
1069
- */
1070
- class ImageBlockInsertImageStrategy extends ActionHandleStrategy {
1071
1060
  /**
1072
- * @inheritDoc
1061
+ * Get the element type by font size.
1062
+ *
1063
+ * @param {HTMLElement} element - element.
1064
+ * @returns {Nullable<VegaRTETextStyleType>} - element type or null if not found.
1073
1065
  */
1074
- handleAction(action, target) {
1075
- const splitNode = action.splitPointNode;
1076
- const startOffsetOfNode = action.startOffsetOfNode;
1077
- const newImageBlock = action.imageBlockToBeInserted;
1078
- const newImageNodes = newImageBlock.children;
1079
- if (target.children.length < 1) {
1080
- target.apply(new AppendChildrenAction(newImageNodes));
1081
- }
1082
- else if (this.isCaretPositionAtBlockEnd(target, splitNode, startOffsetOfNode)) {
1083
- target.parent.apply(new InsertChildrenAfterAction(target, newImageBlock));
1084
- }
1085
- else if (this.isCaretPositionAtBlockStart(target, splitNode, startOffsetOfNode)) {
1086
- target.parent.apply(new InsertChildrenBeforeAction(target, newImageBlock));
1087
- }
1088
- else {
1089
- target.apply(new SplitBlockWithNodeAction(splitNode, startOffsetOfNode));
1090
- target.parent.apply(new InsertChildrenAfterAction(target, newImageBlock));
1066
+ getElementTypeByFontSize(element) {
1067
+ var _a;
1068
+ switch ((_a = element.style) === null || _a === void 0 ? void 0 : _a.fontSize) {
1069
+ case '36px':
1070
+ return 'title';
1071
+ case '28px':
1072
+ return 'subtitle';
1073
+ case '22px':
1074
+ return 'heading-1';
1075
+ case '20px':
1076
+ return 'heading-2';
1077
+ case '18px':
1078
+ return 'heading-3';
1079
+ default:
1080
+ return null;
1091
1081
  }
1092
1082
  }
1093
- }
1094
-
1095
- /**
1096
- * Image block
1097
- */
1098
- class RTEImageBlock extends RTEBlock {
1099
- constructor(id) {
1100
- super(id);
1101
- this.type = 'image';
1102
- this.children = [];
1103
- }
1104
1083
  /**
1105
- * Converts a VegaRTEImageBlock object into an RTEImageBlock object by mapping nodes and creating annotations.
1084
+ * Get the element type by node name.
1106
1085
  *
1107
- * @param {VegaRTEImageBlock} block - The block object to be converted.
1108
- * @param {VegaRTETransformOptions} options - Optional transformation options.
1109
- * @returns {RTEImageBlock} An instance of `RTEImageBlock`
1086
+ * @param {HTMLElement} element - element.
1087
+ * @returns {Nullable<VegaRTETextStyleType>} - element type or null if not found.
1110
1088
  */
1111
- static from(block, options = { autoMatchFormat: true }) {
1112
- const imageBlock = new RTEImageBlock(block.id);
1113
- const { annotations } = block;
1114
- imageBlock.children = block.nodes.map((image) => RTEImageNode.from(image, imageBlock, options));
1115
- if (annotations) {
1116
- super.convertAnnotationsToMap(imageBlock.annotationMap, annotations);
1089
+ getElementTypeByNodeName(element) {
1090
+ switch (element.nodeName) {
1091
+ case 'H1':
1092
+ return 'heading-1';
1093
+ case 'H2':
1094
+ return 'heading-2';
1095
+ case 'H3':
1096
+ return 'heading-3';
1097
+ case 'H4':
1098
+ return 'heading-4';
1099
+ case 'H5':
1100
+ return 'heading-5';
1101
+ case 'H6':
1102
+ return 'heading-6';
1103
+ default:
1104
+ return null;
1117
1105
  }
1118
- return imageBlock;
1119
1106
  }
1120
1107
  /**
1121
- * @inheritDoc
1108
+ * Get the element type by class name.
1109
+ *
1110
+ * @param {HTMLElement} element - element.
1111
+ * @returns {Nullable<VegaRTETextStyleType>} - element type or null if not found.
1122
1112
  */
1123
- toJSON() {
1124
- return Object.assign(Object.assign({}, super.toJSON()), { type: 'image', nodes: this.children.map((node) => node.toJSON()) });
1113
+ getElementTypeByClassName(element) {
1114
+ if (element.className) {
1115
+ const match = /\bv-rte--text-style-(title|subtitle|heading-1|heading-2|heading-3|paragraph)\b/.exec(element.className);
1116
+ if (match) {
1117
+ return match[1];
1118
+ }
1119
+ }
1120
+ return null;
1125
1121
  }
1122
+ }
1123
+
1124
+ /** Handle image size annotation */
1125
+ class ImageSizeAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1126
1126
  /**
1127
1127
  * @inheritDoc
1128
1128
  */
1129
- toHtml() {
1130
- const attrStr = super.generateAttributeString();
1131
- const children = this.children.map((node) => node.toHtml()).join('');
1132
- return super.shouldRenderAsInternalWrapper()
1133
- ? children
1134
- : [`<div${attrStr}>`, children, `</div>`].join('');
1129
+ canHandle(targetDto) {
1130
+ return targetDto.name === 'RTEImageNode';
1135
1131
  }
1136
1132
  /**
1137
- * @inheritDoc
1133
+ * Handle annotation.
1134
+ *
1135
+ * @param {HTMLElement} element - Current elements.
1136
+ * @returns {VegaRTEImageAnnotations} - Annotation.
1138
1137
  */
1139
- isNotEmpty() {
1140
- return this.children.length > 0 && this.children.some((node) => node.url.length > 0);
1138
+ handle(element) {
1139
+ const size = this.getImageSize(element);
1140
+ return size ? { size: size } : {};
1141
1141
  }
1142
1142
  /**
1143
- * @inheritDoc
1143
+ * Determine the image display size based on the width of the current element.
1144
+ *
1145
+ * @param {HTMLElement} element - current element.
1146
+ * @returns {Nullable<VegaRichTextImageEditorSizeType>} -Image size, default 'md'.
1144
1147
  */
1145
- getLastNode() {
1146
- return this.children[this.children.length - 1];
1148
+ getImageSize(element) {
1149
+ if (element.getAttribute('data-size')) {
1150
+ return element.getAttribute('data-size');
1151
+ }
1152
+ return null;
1147
1153
  }
1154
+ }
1155
+
1156
+ /** Handle image alt annotation */
1157
+ class ImageAltAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1148
1158
  /**
1149
- * Create a new image block.
1150
- *
1151
- * @returns {RTEImageBlock} - The empty image block.
1159
+ * @inheritDoc
1152
1160
  */
1153
- createNewImageBlock() {
1154
- return new RTEImageBlock(generateUUID());
1161
+ canHandle(targetDto) {
1162
+ return targetDto.name === 'RTEImageNode';
1155
1163
  }
1156
1164
  /**
1157
- * @inheritDoc
1165
+ * Handle annotation.
1166
+ *
1167
+ * @param {HTMLElement} element - Current elements.
1168
+ * @returns {VegaRTEImageAnnotations} - Annotation.
1158
1169
  */
1159
- clone() {
1160
- const clonedBlock = new RTEImageBlock(this.id);
1161
- clonedBlock.children = this.children.map((node) => {
1162
- const clonedNode = node.clone();
1163
- clonedNode.parent = clonedBlock;
1164
- return clonedNode;
1165
- });
1166
- clonedBlock.annotationMap = super.cloneAnnotations();
1167
- clonedBlock.parent = this.parent;
1168
- return clonedBlock;
1170
+ handle(element) {
1171
+ return element.hasAttribute('alt') ? { alt: element.getAttribute('alt') } : {};
1169
1172
  }
1170
1173
  }
1171
- (() => {
1172
- ActionHandleStrategyRegistry.register(ModifyContentActionType.MERGE_TWO_BLOCKS_NODES, RTEImageBlock.name, new BlockMergeNodesStrategy());
1173
- ActionHandleStrategyRegistry.register(ModifyContentActionType.REPLACE_CHILD_NODES, RTEImageBlock.name, new BlockReplaceNodesStrategy());
1174
- ActionHandleStrategyRegistry.register(ModifyContentActionType.SPLIT_BLOCK_WITH_NODE, RTEImageBlock.name, new BlockSplitWithImageNodeStrategy());
1175
- ActionHandleStrategyRegistry.register(ModifyContentActionType.LINE_BREAK_SINGLE_BLOCK, RTEImageBlock.name, new ImageInsertLineBreakStrategy());
1176
- ActionHandleStrategyRegistry.register(ModifyContentActionType.LINE_BREAK_MULTIPLE_BLOCKS, RTEImageBlock.name, new ImageInsertLineBreakWithBlocksStrategy());
1177
- ActionHandleStrategyRegistry.register(ModifyContentActionType.INSERT_IMAGE_TO_BLOCK, RTEImageBlock.name, new ImageBlockInsertImageStrategy());
1178
- ActionHandleStrategyRegistry.register(HorizontalAlignmentAnnotationAction.name, RTEImageBlock.name, new BlockUpdateHorizontalAlignmentStrategy());
1179
- })();
1180
1174
 
1181
1175
  /**
1182
- * HTML Block
1176
+ * Handle inline html annotation
1183
1177
  */
1184
- class RTEHtmlBlock extends RTEBlock {
1185
- constructor(id, htmlTag) {
1186
- super(id);
1187
- this.type = 'html-block';
1188
- this.children = [];
1189
- this.htmlTag = htmlTag;
1178
+ class InlineHtmlAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1179
+ constructor() {
1180
+ super(...arguments);
1181
+ this.customAttributeHandler = new CustomAttributeAnnotationHandler();
1182
+ this.customStyleAnnotationHandler = new CustomStyleAnnotationHandler();
1183
+ this.customClassAnnotationHandler = new CustomClassAnnotationHandler();
1190
1184
  }
1191
1185
  /**
1192
- * Converts a VegaRTEHtmlBlock to an RTEHtmlBlock.
1193
- *
1194
- * @param {VegaRTEHtmlBlock} block - The VegaRTEHtmlBlock to convert.
1195
- * @param {VegaRTETransformOptions} [options] - Optional transformation options.
1196
- * @returns {RTEHtmlBlock} The converted RTEHtmlBlock.
1186
+ * @inheritDoc
1197
1187
  */
1198
- static from(block, options) {
1199
- const htmlBlock = new RTEHtmlBlock(block.id, block.htmlTag);
1200
- const { annotations } = block;
1201
- if (annotations) {
1202
- super.convertAnnotationsToMap(htmlBlock.annotationMap, annotations);
1203
- }
1204
- htmlBlock.children = block.children
1205
- .map((child) => {
1206
- const BlockClass = RTEDTOClassManager.getRTEBlockClass(child.type);
1207
- if (BlockClass) {
1208
- const block = BlockClass.from(child, options);
1209
- block.parent = htmlBlock;
1210
- return block;
1211
- }
1212
- })
1213
- .filter(isNonNullable);
1214
- return htmlBlock;
1188
+ canHandle(targetDto, options) {
1189
+ return targetDto.name === 'RTETextNode' && options.autoMatchFormat === false;
1215
1190
  }
1216
1191
  /**
1217
1192
  * @inheritDoc
1218
1193
  */
1219
- clone() {
1220
- const clonedBlock = new RTEHtmlBlock(this.id, this.htmlTag);
1221
- clonedBlock.children = this.children.map((child) => child.clone());
1222
- clonedBlock.annotationMap = super.cloneAnnotations();
1223
- return clonedBlock;
1194
+ handle(element, parentAnnotations) {
1195
+ const canHandle = InlineHtmlAnnotationHandler.canHandleTags.includes(element.nodeName);
1196
+ if (canHandle) {
1197
+ const inlineHtml = this.generateInlineHtmlAnnotation(element, Object.assign({}, parentAnnotations));
1198
+ if (inlineHtml) {
1199
+ return { inlineHtml: inlineHtml };
1200
+ }
1201
+ }
1202
+ return {};
1224
1203
  }
1225
1204
  /**
1226
- * @inheritDoc
1205
+ * Generate inline html annotation.
1206
+ *
1207
+ * @param {HTMLElement} child - Current element.
1208
+ * @param {VegaRTETextAnnotations} annotations - Current annotations.
1209
+ * @returns {Nullable<VegaInlineHtmlSchema>} - Inline html annotation.
1227
1210
  */
1228
- getLastNode() {
1229
- return this.children[this.children.length - 1].getLastNode();
1211
+ generateInlineHtmlAnnotation(child, annotations) {
1212
+ let { inlineHtml } = annotations;
1213
+ if (!RTETextNode.supportsHtmlTag(child.nodeName.toLowerCase()) ||
1214
+ (child.childNodes.length === 1 && child.childNodes[0].nodeType !== Node.TEXT_NODE)) {
1215
+ const childInlineHtmlNode = {
1216
+ htmlTag: child.nodeName.toLowerCase(),
1217
+ customAttribute: this.customAttributeHandler.handle(child).customAttribute,
1218
+ customStyle: this.customStyleAnnotationHandler.handle(child).customStyle,
1219
+ customClass: this.customClassAnnotationHandler.handle(child).customClass,
1220
+ };
1221
+ if (!inlineHtml) {
1222
+ inlineHtml = childInlineHtmlNode;
1223
+ }
1224
+ else {
1225
+ let lastChild = inlineHtml;
1226
+ while (lastChild.child &&
1227
+ child.parentNode &&
1228
+ lastChild.child.htmlTag === child.parentNode.nodeName.toLowerCase()) {
1229
+ lastChild = lastChild.child;
1230
+ }
1231
+ lastChild.child = childInlineHtmlNode;
1232
+ }
1233
+ }
1234
+ return inlineHtml ? Object.assign({}, inlineHtml) : null;
1230
1235
  }
1231
- /**
1232
- * @inheritDoc
1233
- */
1234
- isNotEmpty() {
1235
- return this.children.length > 0;
1236
+ }
1237
+ InlineHtmlAnnotationHandler.canHandleTags = [
1238
+ 'A',
1239
+ 'ABBR',
1240
+ 'AUDIO',
1241
+ 'B',
1242
+ 'BDI',
1243
+ 'BDO',
1244
+ 'CITE',
1245
+ 'CODE',
1246
+ 'DEL',
1247
+ 'DFN',
1248
+ 'EMBED',
1249
+ 'EM',
1250
+ 'I',
1251
+ 'INS',
1252
+ 'KBD',
1253
+ 'MARK',
1254
+ 'METER',
1255
+ 'OUTPUT',
1256
+ 'PROGRESS',
1257
+ 'Q',
1258
+ 'S',
1259
+ 'SMALL',
1260
+ 'SPAN',
1261
+ 'STRONG',
1262
+ 'SUB',
1263
+ 'SUP',
1264
+ 'TIME',
1265
+ 'U',
1266
+ 'VAR',
1267
+ 'VIDEO',
1268
+ ];
1269
+
1270
+ /** Html element to annotations generator */
1271
+ class HtmlElementToAnnotationGenerator {
1272
+ constructor() {
1273
+ this.handlers = [
1274
+ new TextAlignAnnotationHandler(),
1275
+ new IndentAnnotationHandler(),
1276
+ new BoldAnnotationHandler(),
1277
+ new ItalicAnnotationHandler(),
1278
+ new UnderlineAnnotationHandler(),
1279
+ new StrikeThroughAnnotationHandler(),
1280
+ new ColorAnnotationHandler(),
1281
+ new LinkAnnotationHandler(),
1282
+ new CodeAnnotationHandler(),
1283
+ new ImageSizeAnnotationHandler(),
1284
+ new ImageAltAnnotationHandler(),
1285
+ new CustomAttributeAnnotationHandler(),
1286
+ new CustomClassAnnotationHandler(),
1287
+ new CustomStyleAnnotationHandler(),
1288
+ new LinkAnnotationHandler(),
1289
+ new TextStyleAnnotationHandler(),
1290
+ new InlineHtmlAnnotationHandler(),
1291
+ ];
1236
1292
  }
1237
1293
  /**
1238
- * @inheritDoc
1294
+ * The function generates annotations for a given target DTO and HTML element based on a set of
1295
+ * strategies.
1296
+ *
1297
+ * @typedef T class name of target DTO
1298
+ * @typedef V generated annotations type
1299
+ * @param {T} targetDto - Which DTO is the generated annotations to set.
1300
+ * @param {HTMLElement} element - Current html element.
1301
+ * @param {HtmlElementToAnnotationGenerateOptions} [options] - Options
1302
+ * @returns {V} Generated annotations.
1239
1303
  */
1240
- toHtml() {
1241
- const BlockTag = this.htmlTag;
1242
- const attrStr = super.generateAttributeString();
1243
- return [
1244
- `<${BlockTag}${attrStr}>`,
1245
- this.children.map((block) => block.toHtml()).join(''),
1246
- `</${BlockTag}>`,
1247
- ].join('');
1304
+ generate(targetDto, element, options = { autoMatchFormat: true }) {
1305
+ const isLinkElement = element.tagName === 'A';
1306
+ return this.handlers
1307
+ .filter((handler) => !options.autoMatchFormat && isLinkElement ? handler instanceof LinkAnnotationHandler : true)
1308
+ .filter((handler) => element.nodeType !== Node.TEXT_NODE &&
1309
+ handler.canHandle(targetDto, {
1310
+ skipCustomAnnotations: options.skipCustomAnnotations || isLinkElement,
1311
+ autoMatchFormat: options.autoMatchFormat,
1312
+ }))
1313
+ .reduce((annotations, handler) => {
1314
+ const result = handler.handle(element, options.parentAnnotations);
1315
+ return Object.assign(Object.assign({}, annotations), result);
1316
+ }, {});
1248
1317
  }
1318
+ }
1319
+ const htmlElementToAnnotationGenerator = new HtmlElementToAnnotationGenerator();
1320
+
1321
+ /**
1322
+ * Abstract class to define strategies for processing HTML elements
1323
+ */
1324
+ class ElementToDTOStrategy {
1249
1325
  /**
1250
- * @inheritDoc
1326
+ * Convert element style attributes to text annotations.
1327
+ *
1328
+ * @param {HTMLElement} element - Current html element.
1329
+ * @param {HtmlElementToAnnotationGenerateOptions} options - Options for generating annotations.
1330
+ * @returns {VegaRTEAnnotations} - Generated annotations.
1251
1331
  */
1252
- toJSON() {
1253
- return Object.assign(Object.assign({}, super.toJSON()), { id: this.id, type: this.type, htmlTag: this.htmlTag, children: this.children.map((child) => child.toJSON()) });
1332
+ generateTextStyleAnnotations(element, options) {
1333
+ return htmlElementToAnnotationGenerator.generate(RTETextNode, element, options);
1254
1334
  }
1255
1335
  }
1256
-
1257
1336
  /**
1258
- * Merge the two blocks node into first block if the two blocks nodes type is same(text node or image node)
1259
- *
1260
- * @example firstBlock.apply(new MergeTwoBlocksNodesAction(secondBlock))
1337
+ * Class to represent the output of a strategy applied to HTML elements
1261
1338
  */
1262
- class MergeTwoBlocksNodesAction extends ModifyContentAction {
1263
- constructor(blockNeedToBeMerged) {
1264
- super();
1265
- this.type = ModifyContentActionType.MERGE_TWO_BLOCKS_NODES;
1266
- this.blockNeedToBeMerged = blockNeedToBeMerged;
1339
+ class ElementToDTOStrategyOutput {
1340
+ constructor(currentStrategy, currentElements) {
1341
+ this.childrenOutput = [];
1342
+ this.currentStrategy = currentStrategy;
1343
+ this.currentElements = currentElements;
1344
+ }
1345
+ /**
1346
+ * Set children output.
1347
+ *
1348
+ * @param {ElementToDTOStrategyOutput[]} childrenOutput - children outputs.
1349
+ */
1350
+ setChildrenOutput(childrenOutput) {
1351
+ this.childrenOutput = childrenOutput;
1352
+ }
1353
+ /**
1354
+ * Transform current output and children output to DTO
1355
+ *
1356
+ * @param {VegaRTETransformOptions} [options] - Options for transformation.
1357
+ * @returns {Nullable<RTEContentBlock>} - DTO.
1358
+ */
1359
+ toDto(options = { autoMatchFormat: true, skipCustomAnnotations: true }) {
1360
+ const currentBlock = this.currentStrategy.handle(this.currentElements, options);
1361
+ if (this.childrenOutput.length > 0 && currentBlock) {
1362
+ this.currentStrategy.appendChildBlocks(currentBlock, this.childrenOutput
1363
+ .map((childOutput) => childOutput.toDto(options))
1364
+ .filter(isNonNullable));
1365
+ }
1366
+ return currentBlock;
1267
1367
  }
1268
1368
  }
1269
1369
 
1270
1370
  /**
1271
- * Block delete text or decorator node strategy.
1371
+ * Manager for registering and retrieving strategies that convert HTML elements to DTOs.
1272
1372
  */
1273
- class BlockDeleteTextOrDecoratorNodeStrategy extends BlockDeleteNodeContentStrategy {
1373
+ class elementToDTOClassStrategyManager {
1374
+ constructor() {
1375
+ this.elementToBlockStrategies = [];
1376
+ this.elementToNodeStrategies = [];
1377
+ }
1274
1378
  /**
1275
- * @inheritDoc
1379
+ * Registers a element to block strategy for converting HTML elements to DTOs. The new strategy is added to the beginning of the list to give it higher priority.
1380
+ *
1381
+ * @param {ElementToDTOStrategy} strategy - The strategy to register.
1276
1382
  */
1277
- handleAction(action, target) {
1278
- const { startContainerNode } = action;
1279
- if (!startContainerNode.isContentEditable()) {
1280
- this.deleteDecoratorNodeContent(action, target);
1281
- }
1282
- else if (startContainerNode.isTextNode()) {
1283
- this.deleteTextNodeContent(action, target);
1284
- }
1285
- const parent = target.parent;
1286
- if (parent && target.isListItemBlock() && parent.children.length === 0) {
1287
- parent.parent.apply(new RemoveChildrenAction(parent));
1383
+ registerElementToBlockStrategy(strategy) {
1384
+ if (!this.hasDuplicateStrategy(strategy, this.elementToBlockStrategies)) {
1385
+ this.elementToBlockStrategies.unshift(strategy);
1288
1386
  }
1289
1387
  }
1290
1388
  /**
1291
- * Handle the delete text logic when press delete key.
1389
+ * Registers an element to node strategy for converting HTML elements to DTOs. The new strategy is added to the beginning of the list to give it higher priority.
1292
1390
  *
1293
- * @param {DeleteBlockContentAction} action - ModifyContentAction
1294
- * @param {RTETextBlock} target - Current text block
1391
+ * @param {ElementToDTOStrategy} strategy - The strategy to register.
1295
1392
  */
1296
- deleteTextNodeContent(action, target) {
1297
- const startContainerNode = action.startContainerNode;
1298
- const startOffset = action.startOffset;
1299
- if (startOffset !== 0 && !startContainerNode.isEmpty()) {
1300
- const newText = startContainerNode.text.slice(0, startOffset - 1) +
1301
- startContainerNode.text.slice(startOffset);
1302
- startContainerNode.apply(new UpdateTextAction(newText));
1303
- if (newText) {
1304
- action.previousNode = startContainerNode;
1305
- return;
1306
- }
1307
- else {
1308
- const previousNode = this.getPreviousNode(startContainerNode);
1309
- // Remove the last character will not delete paragraph, the paragraph will removed after press delete again
1310
- if ((previousNode && previousNode.parent === target && previousNode['text'] === '\n') ||
1311
- target.children.length === 1) {
1312
- action.previousNode = startContainerNode;
1313
- return;
1314
- }
1315
- else {
1316
- target.apply(new RemoveChildrenAction(startContainerNode));
1317
- action.previousNode = previousNode;
1318
- return;
1319
- }
1320
- }
1321
- }
1322
- else {
1323
- let previousNode = this.getPreviousNode(startContainerNode);
1324
- let nextNode = null;
1325
- if (target.children.length && previousNode && previousNode.parent !== target) {
1326
- if (startContainerNode.isEmpty()) {
1327
- target.apply(new RemoveChildrenAction(startContainerNode));
1328
- }
1329
- if (target.type === previousNode.parent.type) {
1330
- previousNode.parent.apply(new MergeTwoBlocksNodesAction(target));
1331
- }
1332
- }
1333
- else {
1334
- if (this.isContentFirstNode(startContainerNode) && startContainerNode.isEmpty()) {
1335
- nextNode = this.getNextNode(startContainerNode);
1336
- }
1337
- /**
1338
- * Remove line break
1339
- *
1340
- * @example caret at the first line
1341
- * \n
1342
- * test
1343
- */
1344
- if (startContainerNode.isEmpty()) {
1345
- target.apply(new RemoveChildrenAction(startContainerNode));
1346
- }
1347
- /**
1348
- * Remove line break
1349
- *
1350
- * @example caret at the begin of second line
1351
- * \n
1352
- * test
1353
- */
1354
- if (previousNode && previousNode.isTextNode() && previousNode.isEmpty()) {
1355
- const shouldRemoveNode = previousNode;
1356
- previousNode = this.getPreviousNode(previousNode);
1357
- shouldRemoveNode.parent.apply(new RemoveChildrenAction(shouldRemoveNode));
1358
- if (!previousNode) {
1359
- nextNode = startContainerNode;
1360
- }
1361
- }
1362
- }
1363
- //Remove the paragraph block if the content is empty
1364
- if (target.children.length === 0) {
1365
- target.parent.apply(new RemoveChildrenAction(target));
1366
- }
1367
- if (previousNode) {
1368
- action.previousNode = previousNode;
1369
- }
1370
- else if (nextNode) {
1371
- action.nextNode = nextNode;
1372
- }
1393
+ registerElementToNodeStrategy(strategy) {
1394
+ if (!this.hasDuplicateStrategy(strategy, this.elementToNodeStrategies)) {
1395
+ this.elementToNodeStrategies.unshift(strategy);
1373
1396
  }
1374
1397
  }
1375
1398
  /**
1376
- * Delete decorator node content
1399
+ * Retrieves all registered element to block strategies for converting HTML elements to DTOs.
1377
1400
  *
1378
- * @param {DeleteBlockContentAction} action - The delete block content action
1379
- * @param {RTEBlock} target - The target block
1401
+ * @returns {ElementToDTOStrategy[]} - A set of all registered element to block strategies.
1380
1402
  */
1381
- deleteDecoratorNodeContent(action, target) {
1382
- const startContainerNode = action.startContainerNode, startOffset = action.startOffset;
1383
- let previousNode = this.getPreviousNode(startContainerNode);
1384
- let nextNode = null;
1385
- if (startOffset !== 0) {
1386
- const parentBlock = target;
1387
- if (this.isContentFirstNode(startContainerNode)) {
1388
- nextNode = this.getNextNode(startContainerNode);
1389
- }
1390
- if (parentBlock.children.length === 1) {
1391
- parentBlock.parent.apply(new RemoveChildrenAction(parentBlock));
1392
- }
1393
- else {
1394
- parentBlock.apply(new RemoveChildrenAction(startContainerNode));
1395
- }
1396
- }
1397
- else {
1398
- const shouldRemoveNode = previousNode;
1399
- if (shouldRemoveNode && !shouldRemoveNode.isContentEditable()) {
1400
- previousNode = this.getPreviousNode(shouldRemoveNode);
1401
- shouldRemoveNode.parent.apply(new RemoveChildrenAction(shouldRemoveNode));
1402
- if (!previousNode) {
1403
- action.nextNode = startContainerNode;
1404
- }
1405
- }
1406
- }
1407
- if (previousNode) {
1408
- action.previousNode = previousNode;
1409
- }
1410
- else if (nextNode) {
1411
- action.nextNode = nextNode;
1412
- }
1403
+ getElementToBlockStrategies() {
1404
+ return this.elementToBlockStrategies;
1413
1405
  }
1414
- }
1415
-
1416
- /**
1417
- * Insert new paragraph into current block at special position.
1418
- */
1419
- class BlockInsertNewParagraphStrategy extends ActionHandleStrategy {
1420
1406
  /**
1421
- * @inheritDoc
1407
+ * Retrieves all registered element to node strategies for converting HTML elements to DTOs.
1408
+ *
1409
+ * @returns {ElementToDTOStrategy[]} - A set of all registered element to node strategies.
1422
1410
  */
1423
- handleAction(action, target) {
1424
- const { startContainerNode } = action;
1425
- action.newBlock = this.breakSingleBlock(startContainerNode, action.startOffset, target);
1411
+ getElementToNodeStrategies() {
1412
+ return this.elementToNodeStrategies;
1426
1413
  }
1427
1414
  /**
1428
- * breakSingleTextBlock
1415
+ * Checks if a strategy is already registered in the provided strategy list.
1429
1416
  *
1430
- * @param {RTETextNode} splitNode -
1431
- * @param {number} startOffsetOfNode -
1432
- * @param {RTEBlock} target -
1433
- * @returns {Nullable<RTEBlock>} Nullable<RTEBlock>
1417
+ * @param {ElementToDTOStrategy} strategy - The strategy to check for duplicates.
1418
+ * @param {ElementToDTOStrategy[]} strategyList - The list of strategies to check against.
1419
+ * @returns {boolean} - True if the strategy is a duplicate, false otherwise.
1434
1420
  */
1435
- breakSingleBlock(splitNode, startOffsetOfNode, target) {
1436
- const newParagraph = this.getNewParagraph(splitNode);
1437
- if (newParagraph) {
1438
- if (this.isCaretPositionAtBlockEnd(target, splitNode, startOffsetOfNode)) {
1439
- target.parent.apply(new InsertChildrenAfterAction(target, newParagraph));
1440
- }
1441
- else if (this.isCaretPositionAtBlockStart(target, splitNode, startOffsetOfNode)) {
1442
- target.parent.apply(new InsertChildrenBeforeAction(target, newParagraph));
1421
+ hasDuplicateStrategy(strategy, strategyList) {
1422
+ return strategyList.includes(strategy);
1423
+ }
1424
+ }
1425
+ const ElementToDTOClassStrategyManager = new elementToDTOClassStrategyManager();
1426
+
1427
+ /** Element to DTO processor */
1428
+ class ElementToDtoStrategyProcessor {
1429
+ /**
1430
+ * Transform process.
1431
+ *
1432
+ * @param {HTMLElement[]} elements - Current elements.
1433
+ * @param {VegaRTETransformOptions} [options] - Options for transformation.
1434
+ * @returns {ElementToDTOStrategyOutput[]} - outputs.
1435
+ */
1436
+ process(elements, options = { autoMatchFormat: true, skipCustomAnnotations: true }) {
1437
+ const strategies = this.getElementToBlockStrategies();
1438
+ const outputs = [];
1439
+ for (let i = 0; i < elements.length; i++) {
1440
+ if (this.isInvalidElement(elements[i]))
1441
+ continue;
1442
+ let canHandledCount = 0;
1443
+ for (const strategy of strategies) {
1444
+ canHandledCount = strategy.canHandle(elements, i, options);
1445
+ if (canHandledCount > 0) {
1446
+ const handledElements = elements.slice(i, i + canHandledCount);
1447
+ const output = new ElementToDTOStrategyOutput(strategy, handledElements);
1448
+ if (canHandledCount === 1 && strategy.shouldProceedToElementChildren()) {
1449
+ output.setChildrenOutput(this.process(Array.from(handledElements[0].childNodes), options));
1450
+ }
1451
+ outputs.push(output);
1452
+ i += canHandledCount - 1;
1453
+ break;
1454
+ }
1443
1455
  }
1444
- else {
1445
- const splitBlockAction = new SplitBlockWithNodeAction(splitNode, startOffsetOfNode);
1446
- target.apply(splitBlockAction);
1447
- return splitBlockAction.newBlock;
1456
+ if (canHandledCount === 0 && i < elements.length) {
1457
+ const elementChildren = Array.from(elements[i].childNodes);
1458
+ const childrenOutputs = this.process(Array.from(elementChildren), options);
1459
+ if (childrenOutputs.length > 0) {
1460
+ outputs.push(...childrenOutputs);
1461
+ }
1448
1462
  }
1449
- return newParagraph;
1450
1463
  }
1464
+ return outputs;
1451
1465
  }
1452
1466
  /**
1453
- * Create new Paragraph
1467
+ * Checks if the given element is valid to parse.
1454
1468
  *
1455
- * @param {RTENode} splitNode - The split node of the block.
1456
- * @returns {Nullable<RTETextBlock>} - The new text block.
1469
+ * @param {HTMLElement} element - The pasted element.
1470
+ * @returns {boolean} Is valid
1457
1471
  */
1458
- getNewParagraph(splitNode) {
1459
- const newParagraph = this.createNewParagraph('');
1460
- if (newParagraph) {
1461
- let textNode = newParagraph.children[0];
1462
- if (splitNode.isTextNode() && splitNode.isContentEditable()) {
1463
- newParagraph.children = [];
1464
- textNode = splitNode.cloneWithText('');
1465
- // The link annotation don't need inherited
1466
- textNode.annotationMap.delete(NodeAnnotationTypeEnum.LINK);
1467
- newParagraph.apply(new AppendChildrenAction([textNode]));
1468
- }
1469
- return newParagraph;
1470
- }
1472
+ isInvalidElement(element) {
1473
+ if (element.nodeType === Node.COMMENT_NODE)
1474
+ return true;
1475
+ return ['META', 'STYLE'].includes(element.nodeName);
1476
+ }
1477
+ /**
1478
+ * Get the register element to block strategies.
1479
+ *
1480
+ * @returns {ElementToDTOStrategy[]} - The register element to block strategies.
1481
+ */
1482
+ getElementToBlockStrategies() {
1483
+ return ElementToDTOClassStrategyManager.getElementToBlockStrategies();
1471
1484
  }
1472
1485
  }
1486
+ const ElementToDtoStrategyProcessor$1 = new ElementToDtoStrategyProcessor();
1473
1487
 
1474
1488
  /**
1475
1489
  * Update the cursor position in the editor.
1476
- *
1477
- * @example richEditorRef.value.apply(new UpdateCursorPositionAction(nextFocusNode, [offset]))
1478
1490
  */
1479
- class UpdateCursorPositionAction extends ModifyContentAction {
1491
+ class UpdateCursorPositionStrategy extends ActionHandleStrategy {
1480
1492
  /**
1481
- * Set the cursor position at end of the current node.
1482
- *
1483
- * @param {RTENode} nextFocusNode - The rich text editor needs focus node.
1484
- * @param {number} offset - The cursor offset position.
1493
+ * @inheritDoc
1485
1494
  */
1486
- constructor(nextFocusNode, offset) {
1487
- super();
1488
- this.type = ModifyContentActionType.UPDATE_CURSOR_POSITION;
1489
- this.nextFocusNode = nextFocusNode;
1490
- this.offset = offset;
1495
+ handleAction(action, target) {
1496
+ const { offset, nextFocusNode, immediatelyRun } = action;
1497
+ const host = stateEntityRenderingRegistry.getDOMByEntity(target);
1498
+ if (host) {
1499
+ ChangeManager.notify(domNodeSubjectFactory.getSubject(host, VegaInternalUpdateRTECursorPosition), {
1500
+ node: nextFocusNode,
1501
+ offset,
1502
+ updateDirectly: immediatelyRun,
1503
+ });
1504
+ }
1505
+ }
1506
+ }
1507
+
1508
+ /**
1509
+ * Append new block array or node array to block or VegaRTEContent instance strategy.
1510
+ */
1511
+ class AppendChildrenStrategy extends ActionHandleStrategy {
1512
+ /**
1513
+ * @inheritDoc
1514
+ */
1515
+ handleAction(action, target) {
1516
+ const newBlocks = action.entityToBeAppended;
1517
+ if (target.children) {
1518
+ newBlocks.forEach((block) => {
1519
+ block.parent = target;
1520
+ });
1521
+ // This line is used to fix the typescript error `This expression is not callable`. https://github.com/microsoft/TypeScript/issues/44373
1522
+ const arrayFixed = target.children;
1523
+ target.children = arrayFixed.concat(newBlocks);
1524
+ }
1491
1525
  }
1492
1526
  }
1493
1527
 
1494
1528
  /**
1495
- * Strategy for inserting text into a decorator node. The decorator can not edit, so we insert the text as a new child.
1529
+ * Insert children at the front of the block strategy.
1496
1530
  */
1497
- class InsertTextToDecoratorNodeStrategy extends ActionHandleStrategy {
1531
+ class InsertChildrenBeforeStrategy extends ActionHandleStrategy {
1498
1532
  /**
1499
1533
  * @inheritDoc
1500
1534
  */
1501
1535
  handleAction(action, target) {
1502
- const { text, offset, decoratorNode } = action;
1503
- const paragraph = this.createNewParagraph(text);
1504
- if (paragraph) {
1505
- const newTextNode = paragraph.children[0];
1506
- if (offset !== 0) {
1507
- target.apply(new InsertChildrenAfterAction(decoratorNode, newTextNode));
1508
- }
1509
- else {
1510
- target.apply(new InsertChildrenBeforeAction(decoratorNode, newTextNode));
1511
- }
1512
- this.setTheCursorPosition(newTextNode);
1513
- }
1536
+ this.replaceElementWithElements(target, action.referChildren, [
1537
+ ...action.childrenToBeInserted,
1538
+ action.referChildren,
1539
+ ]);
1514
1540
  }
1515
1541
  /**
1516
- * Set the cursor position to the new text node.
1542
+ * Replaces a specific block or node with an array of blocks or nodes within RTEContentBlock array.
1517
1543
  *
1518
- * @param {RTENode} focusNode - The new text node to focus on.
1544
+ * @param {RTEBlock | VegaRTEContent} target - The block or the VegaRTEContent instance.
1545
+ * @param {RTEBlock | RTENode} referElement - Used as a reference element to identify the element that needs to be replaced in the array.
1546
+ * @param {RTEBlock[] | RTENode[]} elements - An array of block or node objects that you want to replace the `referElement` with in the array.
1519
1547
  */
1520
- setTheCursorPosition(focusNode) {
1521
- const rootContent = this.getRootContent(focusNode.parent);
1522
- if (rootContent) {
1523
- rootContent.apply(new UpdateCursorPositionAction(focusNode));
1548
+ replaceElementWithElements(target, referElement, elements) {
1549
+ if (target.children) {
1550
+ elements.forEach((block) => {
1551
+ block.parent = target;
1552
+ });
1553
+ const arrayFixed = target.children;
1554
+ target.children = arrayFixed.flatMap((block) => {
1555
+ if (block === referElement) {
1556
+ return elements;
1557
+ }
1558
+ else {
1559
+ return block;
1560
+ }
1561
+ });
1524
1562
  }
1525
1563
  }
1526
1564
  }
1527
1565
 
1528
1566
  /**
1529
- * Insert new paragraph into current list item block at special position.
1567
+ * Insert children at the front of the block strategy.
1530
1568
  */
1531
- class ListItemInsertNewParagraphStrategy extends ActionHandleStrategy {
1569
+ class InsertChildrenAfterStrategy extends InsertChildrenBeforeStrategy {
1532
1570
  /**
1533
1571
  * @inheritDoc
1534
1572
  */
1535
1573
  handleAction(action, target) {
1536
- action.newBlock = this.breakSingleListItemBlock(action.startContainerNode, action.startOffset, target);
1574
+ this.replaceElementWithElements(target, action.referChildren, [
1575
+ action.referChildren,
1576
+ ...action.childrenToBeInserted,
1577
+ ]);
1578
+ }
1579
+ }
1580
+
1581
+ /**
1582
+ * Annotation for image
1583
+ */
1584
+ class ImageAnnotation extends NodeAnnotation {
1585
+ constructor(size, alt) {
1586
+ super();
1587
+ this.type = NodeAnnotationTypeEnum.IMAGE;
1588
+ this.size = size;
1589
+ this.alt = alt;
1537
1590
  }
1538
1591
  /**
1539
- * Breaks a single list item block at a specific position.
1592
+ * Generate the map item for the annotation
1540
1593
  *
1541
- * @param {RTETextNode} splitNode - The node that needs to be split within a list item block.
1542
- * @param {number} startOffsetOfNode - The index within the `splitNode` where the break operation should occur.
1543
- * @param {RTEListItemBlock} target - The list item block.
1544
- * @returns {Nullable<RTEBlock>} Returns either a new `RTEListItemBlock` if the caret
1545
- * position is at the end of the `splitNode`, or it returns the result of splitting the block at the
1546
- * caret position if it is neither at the start nor at the end.
1594
+ * @param {string} size - Image size
1595
+ * @param {string} alt - Image alt
1596
+ * @returns {[NodeAnnotationTypeEnum.IMAGE, ImageAnnotation]} Map item for the annotation
1547
1597
  */
1548
- breakSingleListItemBlock(splitNode, startOffsetOfNode, target) {
1549
- const newListItem = target.createNewListItem();
1550
- const newBreakNode = this.copyInlineStyleToNewNode(splitNode);
1551
- newListItem.apply(new AppendChildrenAction([newBreakNode]));
1552
- if (this.isCaretPositionAtBlockEnd(target, splitNode, startOffsetOfNode)) {
1553
- return this.breakListItemAtEnd(newListItem, target);
1554
- }
1555
- else if (this.isCaretPositionAtBlockStart(target, splitNode, startOffsetOfNode)) {
1556
- target.parent.apply(new InsertChildrenBeforeAction(target, newListItem));
1557
- }
1558
- else {
1559
- const splitBlockAction = new SplitBlockWithNodeAction(splitNode, startOffsetOfNode);
1560
- target.apply(splitBlockAction);
1561
- return splitBlockAction.newBlock;
1562
- }
1563
- return newListItem;
1598
+ static from(size, alt) {
1599
+ return [NodeAnnotationTypeEnum.IMAGE, new ImageAnnotation(size, alt)];
1564
1600
  }
1565
1601
  /**
1566
- * Breaks a list item at the end and handles the insertion of a new list item or paragraph accordingly.
1602
+ * Generate the JSON representation of the annotation
1567
1603
  *
1568
- * @param {RTEListItemBlock} newListItem - Item that represents a new list item to be added to the existing list.
1569
- * @param {RTEListItemBlock} target - The list item block.
1570
- * @returns {RTEBlock} Returns a `RTEBlock`.
1604
+ * @returns {Nullable<Record<string, unknown>>} JSON representation of the annotation
1571
1605
  */
1572
- breakListItemAtEnd(newListItem, target) {
1573
- const lastItem = target.parent.children[target.parent.children.length - 1];
1574
- const currentItemIsEmpty = target.children.length === 1 && target.children[0].isEmpty();
1575
- if (target === lastItem && currentItemIsEmpty) {
1576
- const parentParent = target.parent.parent;
1577
- if (parentParent['type'] !== 'list-item') {
1578
- const newParagraph = RTETextBlock.from({
1579
- id: generateUUID(),
1580
- type: 'paragraph',
1581
- nodes: [],
1582
- });
1583
- newParagraph.apply(new AppendChildrenAction(newListItem.children));
1584
- parentParent.apply(new InsertChildrenAfterAction(target.parent, newParagraph));
1585
- target.parent.apply(new RemoveChildrenAction(target));
1586
- return newParagraph;
1587
- }
1588
- else {
1589
- parentParent.parent.apply(new InsertChildrenAfterAction(parentParent, newListItem));
1590
- target.parent.apply(new RemoveChildrenAction(target));
1606
+ toJSON() {
1607
+ return isNonNullable(this.alt)
1608
+ ? {
1609
+ size: this.size,
1610
+ alt: this.alt,
1591
1611
  }
1592
- }
1593
- else {
1594
- target.parent.apply(new InsertChildrenAfterAction(target, newListItem));
1595
- }
1596
- return newListItem;
1612
+ : {
1613
+ size: this.size,
1614
+ };
1597
1615
  }
1598
1616
  /**
1599
- * Copy the inline style to new node
1600
- *
1601
- * @param {RTETextNode} needCopedNode - The node that needed to be copied to
1602
- * @returns {RTETextNode} Returns a `RTETextNode`.
1617
+ * @inheritDoc
1603
1618
  */
1604
- copyInlineStyleToNewNode(needCopedNode) {
1605
- const textNode = needCopedNode.cloneWithText('');
1606
- // The link annotation doesn't need to inherit
1607
- textNode.annotationMap.delete(NodeAnnotationTypeEnum.LINK);
1608
- return textNode;
1619
+ clone() {
1620
+ return new ImageAnnotation(this.size, this.alt);
1609
1621
  }
1610
- }
1611
-
1612
- /**
1613
- * Delete the nest list block action
1614
- *
1615
- * @example needRemovedNestList.parent.apply(new RemoveNestListAction(needRemovedNestList))
1616
- */
1617
- class RemoveNestListAction extends ModifyContentAction {
1618
- constructor(childList) {
1619
- super();
1620
- this.type = ModifyContentActionType.DELETE_NEST_LIST;
1621
- this.nestListBlockToBeRemoved = childList;
1622
+ /**
1623
+ * @inheritDoc
1624
+ */
1625
+ renderClass(options) {
1626
+ if (options === null || options === void 0 ? void 0 : options.standalone)
1627
+ return null;
1628
+ return this.size ? `v-rte--image-size-${this.size}` : null;
1622
1629
  }
1623
- }
1624
-
1625
- /**
1626
- * List remove list item strategy.
1627
- */
1628
- class ListRemoveListItemStrategy extends RemoveChildrenStrategy {
1629
1630
  /**
1630
- * Remove the list item, check the list item and remove self if the list item is empty.
1631
- *
1632
- * @param {RemoveChildrenAction} action - The remove action instance.
1633
- * @param {RTEListBlock} target - The list block.
1631
+ * @inheritDoc
1634
1632
  */
1635
- handleAction(action, target) {
1636
- super.handleAction(action, target);
1637
- const parent = target.parent;
1638
- if (target.children.length === 0 && parent) {
1639
- // The parent is a list item mean the current block is a nest list, so we need to use RemoveNestListAction to remove the item
1640
- if (parent['type'] === 'list-item') {
1641
- parent.apply(new RemoveNestListAction(target));
1633
+ renderStyle(options) {
1634
+ if (!(options === null || options === void 0 ? void 0 : options.standalone))
1635
+ return null;
1636
+ const baseStyle = { verticalAlign: 'bottom' };
1637
+ switch (this.size) {
1638
+ case 'sm': {
1639
+ return Object.assign(Object.assign({}, baseStyle), { width: '25%' });
1642
1640
  }
1643
- else {
1644
- parent.apply(new RemoveChildrenAction(target));
1641
+ case 'md': {
1642
+ return Object.assign(Object.assign({}, baseStyle), { width: '50%' });
1643
+ }
1644
+ case 'lg': {
1645
+ return Object.assign(Object.assign({}, baseStyle), { width: '100%' });
1645
1646
  }
1646
1647
  }
1647
1648
  }
1648
1649
  }
1649
1650
 
1650
1651
  /**
1651
- * Manager class for registering DTO action strategies.
1652
+ * Update the image node annotation map strategy.
1652
1653
  */
1653
- class RTEDTOActionStrategyManager {
1654
+ class ImageSetAnnotationMapStrategy extends ActionHandleStrategy {
1654
1655
  /**
1655
- * Registers basic strategies for a given DTO class.
1656
- *
1657
- * @param {string} dtoClassName - The name of the RTE block class name.
1656
+ * @inheritDoc
1658
1657
  */
1659
- registerBlockBasicStrategies(dtoClassName) {
1660
- ActionHandleStrategyRegistry.register(ModifyContentActionType.DELETE_CHILDREN, dtoClassName, dtoClassName === RTEListBlock.name
1661
- ? new ListRemoveListItemStrategy()
1662
- : new RemoveChildrenStrategy());
1663
- ActionHandleStrategyRegistry.register(ModifyContentActionType.APPEND_CHILDREN, dtoClassName, new AppendChildrenStrategy());
1664
- ActionHandleStrategyRegistry.register(ModifyContentActionType.INSERT_CHILDREN_BEFORE, dtoClassName, new InsertChildrenBeforeStrategy());
1665
- ActionHandleStrategyRegistry.register(ModifyContentActionType.INSERT_CHILDREN_AFTER, dtoClassName, new InsertChildrenAfterStrategy());
1666
- ActionHandleStrategyRegistry.register(ModifyContentActionType.DELETE_BLOCK_CONTENT, dtoClassName, new BlockDeleteTextOrDecoratorNodeStrategy());
1667
- ActionHandleStrategyRegistry.register(ModifyContentActionType.INSERT_NEW_PARAGRAPH, dtoClassName, dtoClassName === RTEListItemBlock.name
1668
- ? new ListItemInsertNewParagraphStrategy()
1669
- : new BlockInsertNewParagraphStrategy());
1670
- ActionHandleStrategyRegistry.register(ModifyContentActionType.INSERT_TEXT_TO_DECORATOR_NODE, dtoClassName, new InsertTextToDecoratorNodeStrategy());
1658
+ handleAction(action, target) {
1659
+ const annotation = action.toAnnotation();
1660
+ target.annotationMap.set(annotation.type, annotation);
1671
1661
  }
1672
1662
  }
1673
- const RTEDTOActionStrategyManager$1 = new RTEDTOActionStrategyManager();
1674
1663
 
1675
1664
  /**
1676
- * Abstract class to define handler for generate the annotations
1665
+ * The image node update property url strategy.
1677
1666
  */
1678
- class AnnotationGeneratorStrategyAbstract {
1679
- }
1680
-
1681
- /** Handle bold annotation */
1682
- class BoldAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1667
+ class ImageUpdateUrlStrategy extends ActionHandleStrategy {
1683
1668
  /**
1684
1669
  * @inheritDoc
1685
1670
  */
1686
- canHandle(targetDto) {
1687
- return targetDto.name === 'RTETextNode';
1671
+ handleAction(action, target) {
1672
+ target.url = action.url;
1673
+ }
1674
+ }
1675
+
1676
+ var __rest = (undefined && undefined.__rest) || function (s, e) {
1677
+ var t = {};
1678
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
1679
+ t[p] = s[p];
1680
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
1681
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
1682
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
1683
+ t[p[i]] = s[p[i]];
1684
+ }
1685
+ return t;
1686
+ };
1687
+ /**
1688
+ * Image node
1689
+ */
1690
+ class RTEImageNode extends RTEDecoratorNode {
1691
+ constructor(id, url, parentBlock, annotationMap) {
1692
+ super(id, annotationMap);
1693
+ this.type = NodeTypeEnum.IMAGE;
1694
+ this.url = url;
1695
+ this.parent = parentBlock;
1688
1696
  }
1689
1697
  /**
1690
- * Handle annotation.
1698
+ * Converts a VegaRTEImageNode into an RTEImageNode by mapping nodes and creating annotations.
1691
1699
  *
1692
- * @param {HTMLElement} element - Current elements.
1693
- * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
1694
- * @returns {VegaRTETextAnnotations} - Annotation.
1700
+ * @param {VegaRTEImageNode} node - The node to be converted.
1701
+ * @param {RTEImageBlock} parentBlock - The parent block
1702
+ * @param {VegaRTETransformOptions} options - Optional transformation options.
1703
+ * @returns {RTEImageNode} An instance of `RTEImageBlock`
1695
1704
  */
1696
- handle(element, parentAnnotations = {}) {
1697
- return this.isBold(element) || parentAnnotations.bold ? { bold: true } : {};
1705
+ static from(node, parentBlock, options = { autoMatchFormat: true }) {
1706
+ const imageNode = new RTEImageNode(node.id, node.url, parentBlock);
1707
+ const autoMatchFormat = !!options.autoMatchFormat;
1708
+ const _a = Object.assign({}, node.annotations), { size } = _a, otherAnnotations = __rest(_a, ["size"]);
1709
+ const annotations = Object.assign(Object.assign({}, otherAnnotations), { size: size !== null && size !== void 0 ? size : (autoMatchFormat ? 'md' : undefined) });
1710
+ imageNode.annotationMap = new Map(Object.keys(annotations)
1711
+ .map((type) => {
1712
+ if (type === 'size' || type === 'alt') {
1713
+ return ImageAnnotation.from(annotations.size, annotations.alt);
1714
+ }
1715
+ return this.createAnnotationEntity(type, annotations[type]);
1716
+ })
1717
+ .filter(isNonNullable));
1718
+ return imageNode;
1698
1719
  }
1699
1720
  /**
1700
- * Is bold element.
1701
- *
1702
- * @param {HTMLElement} element - current element.
1703
- * @returns {boolean} - boolean.
1721
+ * @inheritDoc
1704
1722
  */
1705
- isBold(element) {
1706
- return (element.nodeName === 'STRONG' ||
1707
- element.nodeName === 'B' ||
1708
- element.style.fontWeight === 'bold' ||
1709
- element.style.fontWeight === '700' ||
1710
- element.classList.contains('v-rte--bold'));
1723
+ toJSON() {
1724
+ const annotations = Array.from(this.annotationMap.values())
1725
+ .filter((annotation) => annotation instanceof ImageAnnotation || annotation instanceof CommonAnnotation)
1726
+ .reduce((record, annotation) => {
1727
+ return Object.assign(Object.assign({}, record), annotation.toJSON());
1728
+ }, {});
1729
+ if (annotations.alt == '')
1730
+ delete annotations.alt;
1731
+ return Object.assign(Object.assign({ id: this.id }, (Object.keys(annotations).length > 0 ? { annotations } : {})), { type: 'image', url: this.url });
1711
1732
  }
1712
- }
1713
-
1714
- /** Handle custom attribute annotation */
1715
- class CustomAttributeAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1716
1733
  /**
1717
- * Can be handle.
1718
- *
1719
- * @param {RTEDtoClassPrototype} targetDto - Target DTO.
1720
- * @param {HtmlElementToAnnotationGenerateOptions} [options] - Options for annotation generator.
1721
- * @returns {boolean} - .
1734
+ * @inheritDoc
1722
1735
  */
1723
- canHandle(targetDto, options) {
1724
- return !options.skipCustomAnnotations && !!targetDto;
1736
+ clone() {
1737
+ return new RTEImageNode(this.id, this.url, this.parent, super.cloneAnnotations());
1725
1738
  }
1726
1739
  /**
1727
- * Handle annotation.
1728
- *
1729
- * @param {HTMLElement} element - Current elements.
1730
- * @returns {VegaRTETextAnnotations} - Annotation.
1740
+ * @inheritDoc
1731
1741
  */
1732
- handle(element) {
1733
- const attributes = this.getAttributes(element);
1734
- return Object.keys(attributes).length > 0 ? { customAttribute: attributes } : {};
1742
+ toHtml() {
1743
+ const imageAnnotation = this.getAnnotationByType(NodeAnnotationTypeEnum.IMAGE);
1744
+ const attrStr = super.generateAttributeString(...[
1745
+ imageAnnotation && imageAnnotation.alt ? `alt="${imageAnnotation.alt}"` : null,
1746
+ `src="${this.url}"`,
1747
+ imageAnnotation && imageAnnotation.size ? `data-size="${imageAnnotation.size}"` : null,
1748
+ ].filter(isNonNullable));
1749
+ return `<img${attrStr}>`;
1735
1750
  }
1736
1751
  /**
1737
- * Obtain the custom attributes of element, excluding 'style' and 'class'.
1738
- *
1739
- * @param {HTMLElement} element - current element.
1740
- * @returns {Record<string, string>} - Record<string, string>.
1752
+ * @inheritDoc
1741
1753
  */
1742
- getAttributes(element) {
1743
- const attributeNames = element
1744
- .getAttributeNames()
1745
- .filter((attr) => attr !== 'style' && attr !== 'class' && this.isValidAttr(attr));
1746
- return attributeNames.reduce((acc, item) => {
1747
- acc[item] = element.getAttribute(item);
1748
- return acc;
1749
- }, {});
1754
+ doAnnotationActionApply(action) {
1755
+ const strategy = ActionHandleStrategyRegistry.get(AnnotationAction.name, RTEImageNode.name);
1756
+ if (strategy) {
1757
+ strategy.execute(action, this);
1758
+ }
1750
1759
  }
1751
1760
  /**
1752
- * Check if the attribute name is valid.
1753
- *
1754
- * @param {string} attr - Attribute name.
1755
- * @returns {boolean} - True if valid, false otherwise.
1761
+ * @inheritDoc
1756
1762
  */
1757
- isValidAttr(attr) {
1758
- return /^[a-zA-Z_][\w-]*$/.test(attr);
1763
+ doModifyActionApply(action) {
1764
+ ActionHandleStrategyRegistry.executeTheStrategy(action, this);
1759
1765
  }
1760
1766
  }
1767
+ (() => {
1768
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.UPDATE_IMAGE_NODE_URL, RTEImageNode.name, new ImageUpdateUrlStrategy());
1769
+ ActionHandleStrategyRegistry.register(AnnotationAction.name, RTEImageNode.name, new ImageSetAnnotationMapStrategy());
1770
+ })();
1761
1771
 
1762
- /** Handle custom class annotation */
1763
- class CustomClassAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1772
+ /**
1773
+ * Split the current image block with a special position strategy.
1774
+ */
1775
+ class BlockSplitWithImageNodeStrategy extends ActionHandleStrategy {
1764
1776
  /**
1765
- * Can be handle.
1766
- *
1767
- * @param {RTEDtoClassPrototype} targetDto - Target DTO.
1768
- * @param {HtmlElementToAnnotationGenerateOptions} [options] - Options for annotation generator.
1769
- * @returns {boolean} - .
1777
+ * @inheritDoc
1770
1778
  */
1771
- canHandle(targetDto, options) {
1772
- return !options.skipCustomAnnotations && !!targetDto;
1779
+ handleAction(action, target) {
1780
+ action.newBlock = this.splitImageNodes(action.splitPointNode, action.startOffsetOfNode, target);
1773
1781
  }
1774
1782
  /**
1775
- * Handle annotation.
1783
+ * The image offset should be 0 or 1
1784
+ * <vega-rich-text-image-editor><img /></vega-rich-text-image-editor>
1776
1785
  *
1777
- * @param {HTMLElement} element - Current elements.
1778
- * @returns {VegaRTETextAnnotations} - Annotation.
1786
+ * @param {RTEImageNode} imageNode The split point image node.
1787
+ * @param {number} imageOffset The cursor point 0 | 1.
1788
+ * @param {RTEImageBlock} target The image block.
1789
+ * @returns {Nullable<RTEBlock>} The new block after split
1779
1790
  */
1780
- handle(element) {
1781
- const classes = this.getCustomClass(element);
1782
- return classes.length > 0 ? { customClass: classes } : {};
1791
+ splitImageNodes(imageNode, imageOffset, target) {
1792
+ const nodesSplitIndex = target.children.indexOf(imageNode);
1793
+ if (nodesSplitIndex > -1) {
1794
+ const beforeNodes = target.children.slice(0, nodesSplitIndex + imageOffset);
1795
+ const afterNodes = target.children.slice(nodesSplitIndex + imageOffset);
1796
+ target.apply(new ReplaceChildNodesAction(beforeNodes));
1797
+ const newBlock = this.cloneWithNodes(afterNodes, target);
1798
+ target.parent.apply(new InsertChildrenAfterAction(target, newBlock));
1799
+ return newBlock;
1800
+ }
1783
1801
  }
1784
1802
  /**
1785
- * Get the custom class
1803
+ * Creates a new RTEImageBlock instance with the provided RTEImageNode instances appended to it.
1786
1804
  *
1787
- * @param {HTMLElement} element - current element.
1788
- * @returns {string[]} - the class after .
1805
+ * @param {RTEImageNode[]} nodes - An array of RTEImageNode objects that will be used to create a new RTEImageBlock instance.
1806
+ * @param {RTEImageBlock} target The image block.
1807
+ * @returns {RTEImageBlock} A new `RTEImageBlock` object with the provided `nodes` appended to it.
1789
1808
  */
1790
- getCustomClass(element) {
1791
- return element.classList
1792
- .toString()
1793
- .split(' ')
1794
- .filter((item) => !item.includes('v-rte') && item !== '');
1809
+ cloneWithNodes(nodes, target) {
1810
+ const block = target.createNewImageBlock();
1811
+ block.children = [];
1812
+ block.apply(new AppendChildrenAction(nodes));
1813
+ return block;
1795
1814
  }
1796
1815
  }
1797
1816
 
1798
- /** Handle custom style annotation */
1799
- class CustomStyleAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1800
- /**
1801
- * Can be handle.
1802
- *
1803
- * @param {RTEDtoClassPrototype} targetDto - Target DTO.
1804
- * @param {HtmlElementToAnnotationGenerateOptions} [options] - Options for annotation generator.
1805
- * @returns {boolean} - .
1806
- */
1807
- canHandle(targetDto, options) {
1808
- return !options.skipCustomAnnotations && !!targetDto;
1809
- }
1810
- /**
1811
- * Handle annotation.
1812
- *
1813
- * @param {HTMLElement} element - Current elements.
1814
- * @returns {VegaRTETextAnnotations} - Annotation.
1815
- */
1816
- handle(element) {
1817
- const styles = this.generateCustomStyleAnnotations(element);
1818
- return Object.keys(styles).length > 0 ? { customStyle: styles } : {};
1817
+ /**
1818
+ * Break the current block after press enter, this action is similar with the SplitBlockWithNodeAction,
1819
+ * The SplitBlockWithNodeAction split the current block to two same type blocks, but this action will create new paragraph or list item when break at start or end.
1820
+ * The property `newBlock` use to store the new create block if need.
1821
+ *
1822
+ * @example currentBlock.apply(new InsertNewParagraphAction(startContainerNode, startOffset))
1823
+ */
1824
+ class InsertNewParagraphAction extends ModifyContentAction {
1825
+ constructor(startContainerNode, startOffset) {
1826
+ super();
1827
+ this.type = ModifyContentActionType.INSERT_NEW_PARAGRAPH;
1828
+ this.startContainerNode = startContainerNode;
1829
+ this.startOffset = startOffset;
1819
1830
  }
1831
+ }
1832
+
1833
+ /**
1834
+ * The image block insert line break strategy.
1835
+ */
1836
+ class ImageInsertLineBreakStrategy extends ActionHandleStrategy {
1820
1837
  /**
1821
- * Obtain and format the style of element.
1838
+ * The image block not support insert the line break node, so invoke the insert new paragraph logic directly.
1822
1839
  *
1823
- * @param {HTMLElement} element - current element.
1824
- * @returns {AnnotationStyle} - Record<string, string>.
1840
+ * @param {LineBreakSingleBlockAction} action - The action instance.
1841
+ * @param {RTEImageBlock} target - The image block.
1825
1842
  */
1826
- generateCustomStyleAnnotations(element) {
1827
- const customStyle = element.getAttribute('style');
1828
- if (!customStyle)
1829
- return {};
1830
- const styleValue = customStyle.split(';').filter(Boolean);
1831
- return styleValue
1832
- .filter((key) => key !== ' ')
1833
- .map((key) => {
1834
- // to remove redundant quote pairs if needed, for example: ['fontFamily: "Roboto Mono"'] will be updated to ['fontFamily: Roboto Mono']
1835
- const styleObject = key.replace(/(['"])(.*?)\1/g, '$2').split(':');
1836
- const styleKey = dashCaseToCamel(styleObject[0].trim());
1837
- return {
1838
- [styleKey]: styleObject[1].trim().replace(';', ''),
1839
- };
1840
- })
1841
- .reduce((current, obj) => (Object.assign(Object.assign({}, current), obj)), {});
1843
+ handleAction(action, target) {
1844
+ const insertNewParagraphAction = new InsertNewParagraphAction(action.startContainerNode, action.startOffset);
1845
+ target.apply(insertNewParagraphAction);
1846
+ const newBlock = insertNewParagraphAction.newBlock;
1847
+ if (newBlock) {
1848
+ action.lineBreakNode = newBlock.children[0];
1849
+ }
1842
1850
  }
1843
1851
  }
1844
1852
 
1845
- /** Handle indent annotation */
1846
- class IndentAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1853
+ /**
1854
+ * Insert a line break node into multiple blocks selection at special position strategy.
1855
+ */
1856
+ class ImageInsertLineBreakWithBlocksStrategy extends ActionHandleStrategy {
1847
1857
  /**
1848
1858
  * @inheritDoc
1849
1859
  */
1850
- canHandle(targetDto) {
1851
- return ['RTETextBlock', 'RTEListItemBlock', 'RTEListBlock'].includes(targetDto.name);
1860
+ handleAction(action, target) {
1861
+ action.lineBreakNode = this.lineBreakMultipleBlocks(action.selectedBlocks, target);
1862
+ }
1863
+ /**
1864
+ * Inserts a new paragraph block with a line break after a selected block of text in a rich text editor.
1865
+ *
1866
+ * @param {RTEBlock[]} selectedBlocks - An array of RTEBlock objects that represent the blocks that have been selected for a specific action in the Rich Text Editor.
1867
+ * @param {RTEImageBlock} target - The image block.
1868
+ * @returns {Nullable<RTETextNode>} Returns a Nullable RTETextNode.
1869
+ */
1870
+ lineBreakMultipleBlocks(selectedBlocks, target) {
1871
+ const newParagraph = RTETextBlock.from({
1872
+ id: generateUUID(),
1873
+ type: 'paragraph',
1874
+ nodes: [{ id: generateUUID(), type: 'text', text: '\n' }],
1875
+ });
1876
+ target.parent.apply(new InsertChildrenAfterAction(target, newParagraph));
1877
+ const afterNodes = this.concatBlocksNodes(selectedBlocks.slice(1));
1878
+ if (afterNodes.length === 0 || (afterNodes[0] && afterNodes[0].text === '')) {
1879
+ afterNodes.push(new RTETextNode(generateUUID(), '\n', newParagraph));
1880
+ }
1881
+ newParagraph.apply(new AppendChildrenAction(afterNodes));
1882
+ return newParagraph['children'][0];
1852
1883
  }
1853
1884
  /**
1854
- * Handle annotation.
1885
+ * Concat the child nodes of multiple RTEBlocks if both are not images.
1855
1886
  *
1856
- * @param {HTMLElement} element - Current elements.
1857
- * @returns {VegaRTEBlockAnnotations} - Annotation.
1887
+ * @param {RTEBlock[]} blocks - multiple block of content in a rich text editor, such as a paragraph, heading, image, etc.
1888
+ * @returns {RTENode[]} Array of connected block nodes
1858
1889
  */
1859
- handle(element) {
1860
- const indent = this.getIndent(element);
1861
- return indent ? { indent: indent } : {};
1890
+ concatBlocksNodes(blocks) {
1891
+ const nodes = [];
1892
+ blocks.map((block) => {
1893
+ if (block.type !== 'image') {
1894
+ nodes.push(...block.children);
1895
+ block.parent.apply(new RemoveChildrenAction(block));
1896
+ }
1897
+ });
1898
+ return nodes;
1862
1899
  }
1900
+ }
1901
+
1902
+ /**
1903
+ * Insert a image node at the special position of image block.
1904
+ */
1905
+ class ImageBlockInsertImageStrategy extends ActionHandleStrategy {
1863
1906
  /**
1864
- * Get indent of current element.
1865
- *
1866
- * @param {HTMLElement} element - current element.
1867
- * @returns {Nullable<number>} - Indent.
1907
+ * @inheritDoc
1868
1908
  */
1869
- getIndent(element) {
1870
- const style = element.style;
1871
- let marginLeft;
1872
- if (style.marginLeft) {
1873
- marginLeft = style.marginLeft;
1909
+ handleAction(action, target) {
1910
+ const splitNode = action.splitPointNode;
1911
+ const startOffsetOfNode = action.startOffsetOfNode;
1912
+ const newImageBlock = action.imageBlockToBeInserted;
1913
+ const newImageNodes = newImageBlock.children;
1914
+ if (target.children.length < 1) {
1915
+ target.apply(new AppendChildrenAction(newImageNodes));
1874
1916
  }
1875
- else if (style.margin) {
1876
- const margins = style.margin.split(' ');
1877
- switch (margins.length) {
1878
- case 4:
1879
- marginLeft = margins[3];
1880
- break;
1881
- case 2:
1882
- case 3:
1883
- marginLeft = margins[1];
1884
- break;
1885
- default:
1886
- marginLeft = margins[0];
1887
- break;
1888
- }
1917
+ else if (this.isCaretPositionAtBlockEnd(target, splitNode, startOffsetOfNode)) {
1918
+ target.parent.apply(new InsertChildrenAfterAction(target, newImageBlock));
1919
+ }
1920
+ else if (this.isCaretPositionAtBlockStart(target, splitNode, startOffsetOfNode)) {
1921
+ target.parent.apply(new InsertChildrenBeforeAction(target, newImageBlock));
1889
1922
  }
1890
1923
  else {
1891
- return null;
1924
+ target.apply(new SplitBlockWithNodeAction(splitNode, startOffsetOfNode));
1925
+ target.parent.apply(new InsertChildrenAfterAction(target, newImageBlock));
1892
1926
  }
1893
- const marginLeftNumber = Number(marginLeft.replace('px', ''));
1894
- return marginLeftNumber && marginLeftNumber >= 0 ? Math.floor(marginLeftNumber / 16) : null;
1895
1927
  }
1896
1928
  }
1897
1929
 
1898
- /** Handle text align annotation */
1899
- class TextAlignAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1930
+ /**
1931
+ * Image block
1932
+ */
1933
+ class RTEImageBlock extends RTEBlock {
1934
+ constructor(id) {
1935
+ super(id);
1936
+ this.type = 'image';
1937
+ this.children = [];
1938
+ }
1900
1939
  /**
1901
- * Can be handle.
1940
+ * Converts a VegaRTEImageBlock object into an RTEImageBlock object by mapping nodes and creating annotations.
1902
1941
  *
1903
- * @param {RTEDtoClassPrototype} targetDto - Target DTO.
1904
- * @returns {boolean} - .
1942
+ * @param {VegaRTEImageBlock} block - The block object to be converted.
1943
+ * @param {VegaRTETransformOptions} options - Optional transformation options.
1944
+ * @returns {RTEImageBlock} An instance of `RTEImageBlock`
1905
1945
  */
1906
- canHandle(targetDto) {
1907
- return ['RTETextBlock', 'RTEListItemBlock', 'RTEListBlock'].includes(targetDto.name);
1946
+ static from(block, options = { autoMatchFormat: true }) {
1947
+ const imageBlock = new RTEImageBlock(block.id);
1948
+ const { annotations } = block;
1949
+ imageBlock.children = block.nodes.map((image) => RTEImageNode.from(image, imageBlock, options));
1950
+ if (annotations) {
1951
+ super.convertAnnotationsToMap(imageBlock.annotationMap, annotations);
1952
+ }
1953
+ return imageBlock;
1908
1954
  }
1909
1955
  /**
1910
- * Handle annotation.
1911
- *
1912
- * @param {HTMLElement} element - Current elements.
1913
- * @returns {VegaRTEBlockAnnotations} - Annotation.
1956
+ * @inheritDoc
1914
1957
  */
1915
- handle(element) {
1916
- const textAlign = this.getTextAlign(element);
1917
- return textAlign ? { textAlign: textAlign } : {};
1958
+ toJSON() {
1959
+ return Object.assign(Object.assign({}, super.toJSON()), { type: 'image', nodes: this.children.map((node) => node.toJSON()) });
1918
1960
  }
1919
1961
  /**
1920
- * Get text align of current element.
1921
- *
1922
- * @param {HTMLElement} element - current element.
1923
- * @returns {Nullable<VegaRTEBlockAlignment>} - Text align.
1962
+ * @inheritDoc
1924
1963
  */
1925
- getTextAlign(element) {
1926
- const classList = element.classList;
1927
- if (classList.contains(`v-rte--horizontal-alignment-left`)) {
1928
- return 'left';
1929
- }
1930
- else if (classList.contains(`v-rte--horizontal-alignment-center`)) {
1931
- return 'center';
1932
- }
1933
- else if (classList.contains(`v-rte--horizontal-alignment-right`)) {
1934
- return 'right';
1935
- }
1936
- else if (classList.contains(`v-rte--horizontal-alignment-justify`)) {
1937
- return 'justify';
1938
- }
1939
- const style = element.style;
1940
- switch (style.textAlign) {
1941
- case 'center':
1942
- return 'center';
1943
- case 'right':
1944
- return 'right';
1945
- case 'justify':
1946
- return 'justify';
1947
- case 'left':
1948
- return 'left';
1949
- default:
1950
- return null;
1951
- }
1964
+ toHtml() {
1965
+ const attrStr = super.generateAttributeString();
1966
+ const children = this.children.map((node) => node.toHtml()).join('');
1967
+ return super.shouldRenderAsInternalWrapper()
1968
+ ? children
1969
+ : [`<div${attrStr}>`, children, `</div>`].join('');
1952
1970
  }
1953
- }
1954
-
1955
- /** Handle code annotation */
1956
- class CodeAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1957
1971
  /**
1958
1972
  * @inheritDoc
1959
1973
  */
1960
- canHandle(targetDto) {
1961
- return targetDto.name === 'RTETextNode';
1974
+ isNotEmpty() {
1975
+ return this.children.length > 0 && this.children.some((node) => node.url.length > 0);
1962
1976
  }
1963
1977
  /**
1964
- * Handle annotation.
1965
- *
1966
- * @param {HTMLElement} element - Current elements.
1967
- * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
1968
- * @returns {VegaRTETextAnnotations} - Annotation.
1978
+ * @inheritDoc
1969
1979
  */
1970
- handle(element, parentAnnotations = {}) {
1971
- return this.isCode(element) || parentAnnotations.code ? { code: true } : {};
1980
+ getLastNode() {
1981
+ return this.children[this.children.length - 1];
1972
1982
  }
1973
1983
  /**
1974
- * Is code element.
1984
+ * Create a new image block.
1975
1985
  *
1976
- * @param {HTMLElement} element - current element.
1977
- * @returns {boolean} - boolean.
1986
+ * @returns {RTEImageBlock} - The empty image block.
1978
1987
  */
1979
- isCode(element) {
1980
- return (element.classList.contains('v-rte--code') ||
1981
- element.nodeName === 'CODE' ||
1982
- element.nodeName === 'PRE' ||
1983
- element.style.fontFamily === 'monospace' ||
1984
- element.style.fontFamily.replace(/["']/g, '') === 'Roboto Mono');
1988
+ createNewImageBlock() {
1989
+ return new RTEImageBlock(generateUUID());
1985
1990
  }
1986
- }
1987
-
1988
- /** Handle color annotation */
1989
- class ColorAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
1990
1991
  /**
1991
1992
  * @inheritDoc
1992
1993
  */
1993
- canHandle(targetDto) {
1994
- return targetDto.name === 'RTETextNode';
1994
+ clone() {
1995
+ const clonedBlock = new RTEImageBlock(this.id);
1996
+ clonedBlock.children = this.children.map((node) => {
1997
+ const clonedNode = node.clone();
1998
+ clonedNode.parent = clonedBlock;
1999
+ return clonedNode;
2000
+ });
2001
+ clonedBlock.annotationMap = super.cloneAnnotations();
2002
+ clonedBlock.parent = this.parent;
2003
+ return clonedBlock;
1995
2004
  }
1996
- /**
1997
- * Handle annotation.
1998
- *
1999
- * @param {HTMLElement} element - Current elements.
2000
- * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
2001
- * @returns {VegaRTETextAnnotations} - Annotation.
2002
- */
2003
- handle(element, parentAnnotations = {}) {
2004
- const color = this.getColor(element) || parentAnnotations.textColor;
2005
- return color ? { textColor: color } : {};
2005
+ }
2006
+ (() => {
2007
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.MERGE_TWO_BLOCKS_NODES, RTEImageBlock.name, new BlockMergeNodesStrategy());
2008
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.REPLACE_CHILD_NODES, RTEImageBlock.name, new BlockReplaceNodesStrategy());
2009
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.SPLIT_BLOCK_WITH_NODE, RTEImageBlock.name, new BlockSplitWithImageNodeStrategy());
2010
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.LINE_BREAK_SINGLE_BLOCK, RTEImageBlock.name, new ImageInsertLineBreakStrategy());
2011
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.LINE_BREAK_MULTIPLE_BLOCKS, RTEImageBlock.name, new ImageInsertLineBreakWithBlocksStrategy());
2012
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.INSERT_IMAGE_TO_BLOCK, RTEImageBlock.name, new ImageBlockInsertImageStrategy());
2013
+ ActionHandleStrategyRegistry.register(HorizontalAlignmentAnnotationAction.name, RTEImageBlock.name, new BlockUpdateHorizontalAlignmentStrategy());
2014
+ })();
2015
+
2016
+ /**
2017
+ * HTML Block
2018
+ */
2019
+ class RTEHtmlBlock extends RTEBlock {
2020
+ constructor(id, htmlTag) {
2021
+ super(id);
2022
+ this.type = 'html-block';
2023
+ this.children = [];
2024
+ this.htmlTag = htmlTag;
2006
2025
  }
2007
2026
  /**
2008
- * Get current color of element.
2027
+ * Converts a VegaRTEHtmlBlock to an RTEHtmlBlock.
2009
2028
  *
2010
- * @param {HTMLElement} element - current element.
2011
- * @returns {Nullable<string>} - color.
2029
+ * @param {VegaRTEHtmlBlock} block - The VegaRTEHtmlBlock to convert.
2030
+ * @param {VegaRTETransformOptions} [options] - Optional transformation options.
2031
+ * @returns {RTEHtmlBlock} The converted RTEHtmlBlock.
2012
2032
  */
2013
- getColor(element) {
2014
- var _a;
2015
- const color = element.style.color;
2016
- const hexColor = (_a = rgbToHex(color)) === null || _a === void 0 ? void 0 : _a.toUpperCase();
2017
- if (hexColor) {
2018
- // We don't display default text color as inline style, because we defined it in the vega-rich-text-content.scss.
2019
- const colorSchema = RTE_TEXT_COLORS.filter((item) => item.key !== RTE_DEFAULT_TEXT_COLOR.key).find((schema) => schema.light === hexColor || schema.dark === hexColor);
2020
- if (colorSchema)
2021
- return colorSchema.key;
2022
- return null;
2023
- }
2024
- else {
2025
- for (const color of RTE_TEXT_COLORS) {
2026
- if (element.style.color.includes(color.key)) {
2027
- return color.key;
2028
- }
2029
- }
2030
- return null;
2033
+ static from(block, options) {
2034
+ const htmlBlock = new RTEHtmlBlock(block.id, block.htmlTag);
2035
+ const { annotations } = block;
2036
+ if (annotations) {
2037
+ super.convertAnnotationsToMap(htmlBlock.annotationMap, annotations);
2031
2038
  }
2039
+ htmlBlock.children = block.children
2040
+ .map((child) => {
2041
+ const BlockClass = RTEDTOClassManager.getRTEBlockClass(child.type);
2042
+ if (BlockClass) {
2043
+ const block = BlockClass.from(child, options);
2044
+ block.parent = htmlBlock;
2045
+ return block;
2046
+ }
2047
+ })
2048
+ .filter(isNonNullable);
2049
+ return htmlBlock;
2032
2050
  }
2033
- }
2034
-
2035
- /** Handle italic annotation */
2036
- class ItalicAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
2037
2051
  /**
2038
2052
  * @inheritDoc
2039
2053
  */
2040
- canHandle(targetDto) {
2041
- return targetDto.name === 'RTETextNode';
2054
+ clone() {
2055
+ const clonedBlock = new RTEHtmlBlock(this.id, this.htmlTag);
2056
+ clonedBlock.children = this.children.map((child) => child.clone());
2057
+ clonedBlock.annotationMap = super.cloneAnnotations();
2058
+ return clonedBlock;
2042
2059
  }
2043
2060
  /**
2044
- * Handle annotation.
2045
- *
2046
- * @param {HTMLElement} element - Current elements.
2047
- * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
2048
- * @returns {VegaRTETextAnnotations} - Annotation.
2061
+ * @inheritDoc
2049
2062
  */
2050
- handle(element, parentAnnotations = {}) {
2051
- return this.isItalic(element) || parentAnnotations.italic ? { italic: true } : {};
2063
+ getLastNode() {
2064
+ return this.children[this.children.length - 1].getLastNode();
2052
2065
  }
2053
2066
  /**
2054
- * Is italic element.
2055
- *
2056
- * @param {HTMLElement} element - current element.
2057
- * @returns {boolean} - boolean.
2067
+ * @inheritDoc
2058
2068
  */
2059
- isItalic(element) {
2060
- return (element.nodeName === 'I' ||
2061
- element.style.fontStyle === 'italic' ||
2062
- element.nodeName === 'EM' ||
2063
- element.classList.contains('v-rte--italic'));
2064
- }
2065
- }
2066
-
2067
- /** Handle link annotation */
2068
- class LinkAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
2069
- constructor() {
2070
- super(...arguments);
2071
- this.handlers = [
2072
- new CustomAttributeAnnotationHandler(),
2073
- new CustomClassAnnotationHandler(),
2074
- new CustomStyleAnnotationHandler(),
2075
- ];
2069
+ isNotEmpty() {
2070
+ return this.children.length > 0;
2076
2071
  }
2077
2072
  /**
2078
- * Can be handle.
2079
- *
2080
- * @param {RTEDtoClassPrototype} targetDto - Target DTO.
2081
- * @returns {boolean} - .
2073
+ * @inheritDoc
2082
2074
  */
2083
- canHandle(targetDto) {
2084
- return targetDto.name === 'RTETextNode';
2075
+ toHtml() {
2076
+ const BlockTag = this.htmlTag;
2077
+ const attrStr = super.generateAttributeString();
2078
+ return [
2079
+ `<${BlockTag}${attrStr}>`,
2080
+ this.children.map((block) => block.toHtml()).join(''),
2081
+ `</${BlockTag}>`,
2082
+ ].join('');
2085
2083
  }
2086
2084
  /**
2087
- * Handle annotation.
2088
- *
2089
- * @param {HTMLElement} element - Current elements.
2090
- * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
2091
- * @returns {VegaRTETextAnnotations} - Annotation.
2085
+ * @inheritDoc
2092
2086
  */
2093
- handle(element, parentAnnotations = {}) {
2094
- if (parentAnnotations.link)
2095
- return { link: parentAnnotations.link };
2096
- return element.tagName === 'A' ? { link: this.generateLinkAnnotations(element) } : {};
2087
+ toJSON() {
2088
+ return Object.assign(Object.assign({}, super.toJSON()), { id: this.id, type: this.type, htmlTag: this.htmlTag, children: this.children.map((child) => child.toJSON()) });
2097
2089
  }
2098
- /**
2099
- * Generate link annotations.
2100
- *
2101
- * @param {HTMLElement} element - Current elements.
2102
- * @returns {VegaRTELink} - link annotations.
2103
- */
2104
- generateLinkAnnotations(element) {
2105
- const annotations = {
2106
- href: element.getAttribute('href') || '',
2107
- groupKey: generateUUID(),
2108
- };
2109
- this.handlers.forEach((handler) => {
2110
- Object.assign(annotations, handler.handle(element));
2111
- });
2112
- return annotations;
2090
+ }
2091
+
2092
+ /**
2093
+ * Merge the two blocks node into first block if the two blocks nodes type is same(text node or image node)
2094
+ *
2095
+ * @example firstBlock.apply(new MergeTwoBlocksNodesAction(secondBlock))
2096
+ */
2097
+ class MergeTwoBlocksNodesAction extends ModifyContentAction {
2098
+ constructor(blockNeedToBeMerged) {
2099
+ super();
2100
+ this.type = ModifyContentActionType.MERGE_TWO_BLOCKS_NODES;
2101
+ this.blockNeedToBeMerged = blockNeedToBeMerged;
2113
2102
  }
2114
2103
  }
2115
2104
 
2116
- /** Handle strike through annotation */
2117
- class StrikeThroughAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
2105
+ /**
2106
+ * Block delete text or decorator node strategy.
2107
+ */
2108
+ class BlockDeleteTextOrDecoratorNodeStrategy extends BlockDeleteNodeContentStrategy {
2118
2109
  /**
2119
2110
  * @inheritDoc
2120
2111
  */
2121
- canHandle(targetDto) {
2122
- return targetDto.name === 'RTETextNode';
2112
+ handleAction(action, target) {
2113
+ const { startContainerNode } = action;
2114
+ if (!startContainerNode.isContentEditable()) {
2115
+ this.deleteDecoratorNodeContent(action, target);
2116
+ }
2117
+ else if (startContainerNode.isTextNode()) {
2118
+ this.deleteTextNodeContent(action, target);
2119
+ }
2120
+ const parent = target.parent;
2121
+ if (parent && target.isListItemBlock() && parent.children.length === 0) {
2122
+ parent.parent.apply(new RemoveChildrenAction(parent));
2123
+ }
2123
2124
  }
2124
2125
  /**
2125
- * Handle annotation.
2126
+ * Handle the delete text logic when press delete key.
2126
2127
  *
2127
- * @param {HTMLElement} element - Current elements.
2128
- * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
2129
- * @returns {VegaRTETextAnnotations} - Annotation.
2128
+ * @param {DeleteBlockContentAction} action - ModifyContentAction
2129
+ * @param {RTETextBlock} target - Current text block
2130
2130
  */
2131
- handle(element, parentAnnotations = {}) {
2132
- return this.isStrikethrough(element) || parentAnnotations.strikethrough
2133
- ? { strikethrough: true }
2134
- : {};
2131
+ deleteTextNodeContent(action, target) {
2132
+ const startContainerNode = action.startContainerNode;
2133
+ const startOffset = action.startOffset;
2134
+ if (startOffset !== 0 && !startContainerNode.isEmpty()) {
2135
+ const newText = startContainerNode.text.slice(0, startOffset - 1) +
2136
+ startContainerNode.text.slice(startOffset);
2137
+ startContainerNode.apply(new UpdateTextAction(newText));
2138
+ if (newText) {
2139
+ action.previousNode = startContainerNode;
2140
+ return;
2141
+ }
2142
+ else {
2143
+ const previousNode = this.getPreviousNode(startContainerNode);
2144
+ // Remove the last character will not delete paragraph, the paragraph will removed after press delete again
2145
+ if ((previousNode && previousNode.parent === target && previousNode['text'] === '\n') ||
2146
+ target.children.length === 1) {
2147
+ action.previousNode = startContainerNode;
2148
+ return;
2149
+ }
2150
+ else {
2151
+ target.apply(new RemoveChildrenAction(startContainerNode));
2152
+ action.previousNode = previousNode;
2153
+ return;
2154
+ }
2155
+ }
2156
+ }
2157
+ else {
2158
+ let previousNode = this.getPreviousNode(startContainerNode);
2159
+ let nextNode = null;
2160
+ const isCurrentNodeEmpty = startContainerNode.isEmpty();
2161
+ if (target.children.length && previousNode && previousNode.parent !== target) {
2162
+ if (isCurrentNodeEmpty) {
2163
+ target.apply(new RemoveChildrenAction(startContainerNode));
2164
+ }
2165
+ if (target.type === previousNode.parent.type) {
2166
+ previousNode.parent.apply(new MergeTwoBlocksNodesAction(target));
2167
+ }
2168
+ }
2169
+ else {
2170
+ if (this.isContentFirstNode(startContainerNode) && isCurrentNodeEmpty) {
2171
+ nextNode = this.getNextNode(startContainerNode);
2172
+ }
2173
+ /**
2174
+ * Remove line break
2175
+ *
2176
+ * @example caret at the first line
2177
+ * \n
2178
+ * test
2179
+ */
2180
+ if (isCurrentNodeEmpty) {
2181
+ target.apply(new RemoveChildrenAction(startContainerNode));
2182
+ }
2183
+ /**
2184
+ * Remove line break or non-editable node
2185
+ *
2186
+ * @example caret at the begin of second line
2187
+ * \n
2188
+ * test
2189
+ * @example caret at the end of non-editable node and start of the text node
2190
+ * <img/><span>test</span>
2191
+ */
2192
+ if (previousNode &&
2193
+ previousNode.isTextNode() &&
2194
+ (previousNode.isEmpty() ||
2195
+ (!previousNode.isContentEditable() && previousNode.parent === target))) {
2196
+ const shouldRemoveNode = previousNode;
2197
+ previousNode = this.getPreviousNode(previousNode);
2198
+ shouldRemoveNode.parent.apply(new RemoveChildrenAction(shouldRemoveNode));
2199
+ if (!previousNode && !isCurrentNodeEmpty) {
2200
+ nextNode = startContainerNode;
2201
+ }
2202
+ }
2203
+ }
2204
+ //Remove the paragraph block if the content is empty
2205
+ if (target.children.length === 0) {
2206
+ target.parent.apply(new RemoveChildrenAction(target));
2207
+ }
2208
+ if (previousNode) {
2209
+ action.previousNode = previousNode;
2210
+ }
2211
+ else if (nextNode) {
2212
+ action.nextNode = nextNode;
2213
+ }
2214
+ }
2135
2215
  }
2136
2216
  /**
2137
- * Is strikethrough element.
2217
+ * Delete decorator node content
2138
2218
  *
2139
- * @param {HTMLElement} element - current element.
2140
- * @returns {boolean} - boolean.
2219
+ * @param {DeleteBlockContentAction} action - The delete block content action
2220
+ * @param {RTEBlock} target - The target block
2141
2221
  */
2142
- isStrikethrough(element) {
2143
- return (element.style.textDecoration.includes('line-through') ||
2144
- element.nodeName === 'S' ||
2145
- element.nodeName === 'DEL' ||
2146
- element.classList.contains('v-rte--strikethrough'));
2222
+ deleteDecoratorNodeContent(action, target) {
2223
+ const startContainerNode = action.startContainerNode, startOffset = action.startOffset;
2224
+ let previousNode = this.getPreviousNode(startContainerNode);
2225
+ let nextNode = null;
2226
+ if (startOffset !== 0) {
2227
+ const parentBlock = target;
2228
+ if (this.isContentFirstNode(startContainerNode)) {
2229
+ nextNode = this.getNextNode(startContainerNode);
2230
+ }
2231
+ if (parentBlock.children.length === 1) {
2232
+ parentBlock.parent.apply(new RemoveChildrenAction(parentBlock));
2233
+ }
2234
+ else {
2235
+ parentBlock.apply(new RemoveChildrenAction(startContainerNode));
2236
+ }
2237
+ }
2238
+ else {
2239
+ const shouldRemoveNode = previousNode;
2240
+ if (shouldRemoveNode && !shouldRemoveNode.isContentEditable()) {
2241
+ previousNode = this.getPreviousNode(shouldRemoveNode);
2242
+ shouldRemoveNode.parent.apply(new RemoveChildrenAction(shouldRemoveNode));
2243
+ if (!previousNode) {
2244
+ action.nextNode = startContainerNode;
2245
+ }
2246
+ }
2247
+ }
2248
+ if (previousNode) {
2249
+ action.previousNode = previousNode;
2250
+ }
2251
+ else if (nextNode) {
2252
+ action.nextNode = nextNode;
2253
+ }
2147
2254
  }
2148
2255
  }
2149
2256
 
2150
- /** Handle underline annotation */
2151
- class UnderlineAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
2257
+ /**
2258
+ * Insert new paragraph into current block at special position.
2259
+ */
2260
+ class BlockInsertNewParagraphStrategy extends ActionHandleStrategy {
2152
2261
  /**
2153
2262
  * @inheritDoc
2154
2263
  */
2155
- canHandle(targetDto) {
2156
- return targetDto.name === 'RTETextNode';
2264
+ handleAction(action, target) {
2265
+ const { startContainerNode } = action;
2266
+ action.newBlock = this.breakSingleBlock(startContainerNode, action.startOffset, target);
2157
2267
  }
2158
2268
  /**
2159
- * Handle annotation.
2269
+ * breakSingleTextBlock
2160
2270
  *
2161
- * @param {HTMLElement} element - Current elements.
2162
- * @param {VegaRTETextAnnotations} parentAnnotations - Parent annotations.
2163
- * @returns {VegaRTETextAnnotations} - Annotation.
2271
+ * @param {RTETextNode} splitNode -
2272
+ * @param {number} startOffsetOfNode -
2273
+ * @param {RTEBlock} target -
2274
+ * @returns {Nullable<RTEBlock>} Nullable<RTEBlock>
2164
2275
  */
2165
- handle(element, parentAnnotations = {}) {
2166
- return this.isUnderline(element) || parentAnnotations.underline ? { underline: true } : {};
2276
+ breakSingleBlock(splitNode, startOffsetOfNode, target) {
2277
+ const newParagraph = this.getNewParagraph(splitNode);
2278
+ if (newParagraph) {
2279
+ if (this.isCaretPositionAtBlockEnd(target, splitNode, startOffsetOfNode)) {
2280
+ target.parent.apply(new InsertChildrenAfterAction(target, newParagraph));
2281
+ }
2282
+ else if (this.isCaretPositionAtBlockStart(target, splitNode, startOffsetOfNode)) {
2283
+ target.parent.apply(new InsertChildrenBeforeAction(target, newParagraph));
2284
+ }
2285
+ else {
2286
+ const splitBlockAction = new SplitBlockWithNodeAction(splitNode, startOffsetOfNode);
2287
+ target.apply(splitBlockAction);
2288
+ return splitBlockAction.newBlock;
2289
+ }
2290
+ return newParagraph;
2291
+ }
2167
2292
  }
2168
2293
  /**
2169
- * Is underline element.
2294
+ * Create new Paragraph
2170
2295
  *
2171
- * @param {HTMLElement} element - current element.
2172
- * @returns {boolean} - boolean.
2296
+ * @param {RTENode} splitNode - The split node of the block.
2297
+ * @returns {Nullable<RTETextBlock>} - The new text block.
2173
2298
  */
2174
- isUnderline(element) {
2175
- return (element.style.textDecoration.includes('underline') ||
2176
- element.nodeName === 'U' ||
2177
- element.nodeName === 'INS' ||
2178
- element.classList.contains('v-rte--underline'));
2299
+ getNewParagraph(splitNode) {
2300
+ const newParagraph = this.createNewParagraph('');
2301
+ if (newParagraph) {
2302
+ let textNode = newParagraph.children[0];
2303
+ if (splitNode.isTextNode() && splitNode.isContentEditable()) {
2304
+ newParagraph.children = [];
2305
+ textNode = splitNode.cloneWithText('');
2306
+ // The link annotation don't need inherited
2307
+ textNode.annotationMap.delete(NodeAnnotationTypeEnum.LINK);
2308
+ newParagraph.apply(new AppendChildrenAction([textNode]));
2309
+ }
2310
+ return newParagraph;
2311
+ }
2179
2312
  }
2180
2313
  }
2181
2314
 
2182
- /** Handle text style annotation */
2183
- class TextStyleAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
2184
- /**
2185
- * Can be handle.
2186
- *
2187
- * @param {RTEDtoClassPrototype} targetDto - Target DTO.
2188
- * @param {HtmlElementToAnnotationGenerateOptions} options - Options for annotation generator.
2189
- * @returns {boolean} - .
2190
- */
2191
- canHandle(targetDto, options) {
2192
- return !!options.autoMatchFormat && targetDto.name === 'RTETextBlock';
2193
- }
2194
- /**
2195
- * Handle annotation.
2196
- *
2197
- * @param {HTMLElement} element - Current elements.
2198
- * @returns {VegaRTETextBlockAnnotations} - Annotation.
2199
- */
2200
- handle(element) {
2201
- const textStyle = this.getTextStyle(element);
2202
- return textStyle ? { textStyle: textStyle } : {};
2203
- }
2315
+ /**
2316
+ * Update the cursor position in the editor.
2317
+ *
2318
+ * @example richEditorRef.value.apply(new UpdateCursorPositionAction(nextFocusNode, [offset], [immediatelyRun]))
2319
+ */
2320
+ class UpdateCursorPositionAction extends ModifyContentAction {
2204
2321
  /**
2205
- * Get the node type of element. The element type is determined in the following
2206
- * order: "data-type" attribute, node name, font size and class name.
2322
+ * Set the cursor position at end of the current node.
2207
2323
  *
2208
- * @param {HTMLElement} element - element.
2209
- * @returns {Nullable<VegaRTETextStyleType>} - node type.
2324
+ * @param {RTENode} nextFocusNode - The rich text editor needs focus node.
2325
+ * @param {number} offset - The cursor offset position.
2326
+ * @param {boolean} immediatelyRun - Whether to immediately set the cursor position after applying it. Usually the set action will trigger after the UI renders.
2210
2327
  */
2211
- getTextStyle(element) {
2212
- const byDataType = this.getElementTypeByDataType(element);
2213
- if (byDataType)
2214
- return byDataType;
2215
- const byNodeName = this.getElementTypeByNodeName(element);
2216
- if (byNodeName)
2217
- return byNodeName;
2218
- const byFontSize = this.getElementTypeByFontSize(element);
2219
- if (byFontSize)
2220
- return byFontSize;
2221
- const byClassName = this.getElementTypeByClassName(element);
2222
- if (byClassName)
2223
- return byClassName;
2224
- return null;
2328
+ constructor(nextFocusNode, offset, immediatelyRun = false) {
2329
+ super();
2330
+ this.type = ModifyContentActionType.UPDATE_CURSOR_POSITION;
2331
+ this.immediatelyRun = false;
2332
+ this.nextFocusNode = nextFocusNode;
2333
+ this.offset = offset;
2334
+ this.immediatelyRun = immediatelyRun;
2225
2335
  }
2336
+ }
2337
+
2338
+ /**
2339
+ * Insert a new node in nearest position of parent block strategy.
2340
+ */
2341
+ class InsertNodeToNearestRootStrategy extends ActionHandleStrategy {
2226
2342
  /**
2227
- * Get the element type by data-type attribute.
2228
- *
2229
- * @param {HTMLElement} element - element.
2230
- * @returns {Nullable<VegaRTETextStyleType>} - element type or null if not found.
2343
+ * @inheritDoc
2231
2344
  */
2232
- getElementTypeByDataType(element) {
2233
- if (element.nodeType !== Node.TEXT_NODE && element.hasAttribute('data-type')) {
2234
- return element.getAttribute('data-type');
2345
+ handleAction(action, target) {
2346
+ const { rteRange, nodeToBeInserted } = action;
2347
+ const { startNode, startOffset } = rteRange;
2348
+ if (startNode) {
2349
+ const parent = target;
2350
+ if (startNode.isContentEditable() && startNode.isTextNode()) {
2351
+ if (startNode.text === '\n' || !startNode.text || startOffset === 0) {
2352
+ parent.apply(new InsertChildrenBeforeAction(startNode, nodeToBeInserted));
2353
+ }
2354
+ else {
2355
+ const startText = startNode.text.substring(0, startOffset);
2356
+ const endText = startNode.text.substring(startOffset);
2357
+ const startTextNode = startNode.cloneWithText(startText);
2358
+ const endTextNode = startNode.cloneWithText(endText);
2359
+ const insertNodes = [startTextNode, nodeToBeInserted];
2360
+ if (endText) {
2361
+ insertNodes.push(endTextNode);
2362
+ }
2363
+ parent.apply(new InsertChildrenBeforeAction(startNode, ...insertNodes));
2364
+ parent.apply(new RemoveChildrenAction(startNode));
2365
+ }
2366
+ }
2367
+ else {
2368
+ if (startOffset !== 0) {
2369
+ parent.apply(new InsertChildrenAfterAction(startNode, nodeToBeInserted));
2370
+ }
2371
+ else {
2372
+ parent.apply(new InsertChildrenBeforeAction(startNode, nodeToBeInserted));
2373
+ }
2374
+ }
2375
+ this.updateCursorPosition(nodeToBeInserted);
2235
2376
  }
2236
- return null;
2237
2377
  }
2238
2378
  /**
2239
- * Get the element type by font size.
2379
+ * Update the cursor position to end of the inserted node.
2240
2380
  *
2241
- * @param {HTMLElement} element - element.
2242
- * @returns {Nullable<VegaRTETextStyleType>} - element type or null if not found.
2381
+ * @param {RTENode} node - node to find root content
2243
2382
  */
2244
- getElementTypeByFontSize(element) {
2245
- var _a;
2246
- switch ((_a = element.style) === null || _a === void 0 ? void 0 : _a.fontSize) {
2247
- case '36px':
2248
- return 'title';
2249
- case '28px':
2250
- return 'subtitle';
2251
- case '22px':
2252
- return 'heading-1';
2253
- case '20px':
2254
- return 'heading-2';
2255
- case '18px':
2256
- return 'heading-3';
2257
- default:
2258
- return null;
2383
+ updateCursorPosition(node) {
2384
+ const root = this.getRootContent(node.parent);
2385
+ if (root) {
2386
+ root.apply(new UpdateCursorPositionAction(node));
2259
2387
  }
2260
2388
  }
2389
+ }
2390
+
2391
+ /**
2392
+ * Strategy for inserting text into a decorator node. The decorator can not edit, so we insert the text as a new child.
2393
+ */
2394
+ class InsertTextToDecoratorNodeStrategy extends ActionHandleStrategy {
2261
2395
  /**
2262
- * Get the element type by node name.
2263
- *
2264
- * @param {HTMLElement} element - element.
2265
- * @returns {Nullable<VegaRTETextStyleType>} - element type or null if not found.
2396
+ * @inheritDoc
2266
2397
  */
2267
- getElementTypeByNodeName(element) {
2268
- switch (element.nodeName) {
2269
- case 'H1':
2270
- return 'heading-1';
2271
- case 'H2':
2272
- return 'heading-2';
2273
- case 'H3':
2274
- return 'heading-3';
2275
- case 'H4':
2276
- return 'heading-4';
2277
- case 'H5':
2278
- return 'heading-5';
2279
- case 'H6':
2280
- return 'heading-6';
2281
- default:
2282
- return null;
2398
+ handleAction(action, target) {
2399
+ const { text, offset, decoratorNode } = action;
2400
+ const paragraph = this.createNewParagraph(text);
2401
+ if (paragraph) {
2402
+ const newTextNode = paragraph.children[0];
2403
+ if (offset !== 0) {
2404
+ target.apply(new InsertChildrenAfterAction(decoratorNode, newTextNode));
2405
+ }
2406
+ else {
2407
+ target.apply(new InsertChildrenBeforeAction(decoratorNode, newTextNode));
2408
+ }
2409
+ this.setTheCursorPosition(newTextNode);
2283
2410
  }
2284
2411
  }
2285
2412
  /**
2286
- * Get the element type by class name.
2413
+ * Set the cursor position to the new text node.
2287
2414
  *
2288
- * @param {HTMLElement} element - element.
2289
- * @returns {Nullable<VegaRTETextStyleType>} - element type or null if not found.
2415
+ * @param {RTENode} focusNode - The new text node to focus on.
2290
2416
  */
2291
- getElementTypeByClassName(element) {
2292
- if (element.className) {
2293
- const match = /\bv-rte--text-style-(title|subtitle|heading-1|heading-2|heading-3|paragraph)\b/.exec(element.className);
2294
- if (match) {
2295
- return match[1];
2296
- }
2417
+ setTheCursorPosition(focusNode) {
2418
+ const rootContent = this.getRootContent(focusNode.parent);
2419
+ if (rootContent) {
2420
+ rootContent.apply(new UpdateCursorPositionAction(focusNode));
2297
2421
  }
2298
- return null;
2299
2422
  }
2300
2423
  }
2301
2424
 
2302
- /** Handle image size annotation */
2303
- class ImageSizeAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
2425
+ /**
2426
+ * Insert new paragraph into current list item block at special position.
2427
+ */
2428
+ class ListItemInsertNewParagraphStrategy extends ActionHandleStrategy {
2304
2429
  /**
2305
2430
  * @inheritDoc
2306
2431
  */
2307
- canHandle(targetDto) {
2308
- return targetDto.name === 'RTEImageNode';
2309
- }
2310
- /**
2311
- * Handle annotation.
2312
- *
2313
- * @param {HTMLElement} element - Current elements.
2314
- * @returns {VegaRTEImageAnnotations} - Annotation.
2315
- */
2316
- handle(element) {
2317
- const size = this.getImageSize(element);
2318
- return size ? { size: size } : {};
2432
+ handleAction(action, target) {
2433
+ action.newBlock = this.breakSingleListItemBlock(action.startContainerNode, action.startOffset, target);
2319
2434
  }
2320
2435
  /**
2321
- * Determine the image display size based on the width of the current element.
2436
+ * Breaks a single list item block at a specific position.
2322
2437
  *
2323
- * @param {HTMLElement} element - current element.
2324
- * @returns {Nullable<VegaRichTextImageEditorSizeType>} -Image size, default 'md'.
2438
+ * @param {RTETextNode} splitNode - The node that needs to be split within a list item block.
2439
+ * @param {number} startOffsetOfNode - The index within the `splitNode` where the break operation should occur.
2440
+ * @param {RTEListItemBlock} target - The list item block.
2441
+ * @returns {Nullable<RTEBlock>} Returns either a new `RTEListItemBlock` if the caret
2442
+ * position is at the end of the `splitNode`, or it returns the result of splitting the block at the
2443
+ * caret position if it is neither at the start nor at the end.
2325
2444
  */
2326
- getImageSize(element) {
2327
- if (element.getAttribute('data-size')) {
2328
- return element.getAttribute('data-size');
2445
+ breakSingleListItemBlock(splitNode, startOffsetOfNode, target) {
2446
+ const newListItem = target.createNewListItem();
2447
+ const newBreakNode = this.copyInlineStyleToNewNode(splitNode);
2448
+ newListItem.apply(new AppendChildrenAction([newBreakNode]));
2449
+ if (this.isCaretPositionAtBlockEnd(target, splitNode, startOffsetOfNode)) {
2450
+ return this.breakListItemAtEnd(newListItem, target);
2451
+ }
2452
+ else if (this.isCaretPositionAtBlockStart(target, splitNode, startOffsetOfNode)) {
2453
+ target.parent.apply(new InsertChildrenBeforeAction(target, newListItem));
2454
+ }
2455
+ else {
2456
+ const splitBlockAction = new SplitBlockWithNodeAction(splitNode, startOffsetOfNode);
2457
+ target.apply(splitBlockAction);
2458
+ return splitBlockAction.newBlock;
2329
2459
  }
2330
- return null;
2460
+ return newListItem;
2331
2461
  }
2332
- }
2333
-
2334
- /** Handle image alt annotation */
2335
- class ImageAltAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
2336
2462
  /**
2337
- * @inheritDoc
2463
+ * Breaks a list item at the end and handles the insertion of a new list item or paragraph accordingly.
2464
+ *
2465
+ * @param {RTEListItemBlock} newListItem - Item that represents a new list item to be added to the existing list.
2466
+ * @param {RTEListItemBlock} target - The list item block.
2467
+ * @returns {RTEBlock} Returns a `RTEBlock`.
2338
2468
  */
2339
- canHandle(targetDto) {
2340
- return targetDto.name === 'RTEImageNode';
2469
+ breakListItemAtEnd(newListItem, target) {
2470
+ const lastItem = target.parent.children[target.parent.children.length - 1];
2471
+ const currentItemIsEmpty = target.children.length === 1 && target.children[0].isEmpty();
2472
+ if (target === lastItem && currentItemIsEmpty) {
2473
+ const parentParent = target.parent.parent;
2474
+ if (parentParent['type'] !== 'list-item') {
2475
+ const newParagraph = RTETextBlock.from({
2476
+ id: generateUUID(),
2477
+ type: 'paragraph',
2478
+ nodes: [],
2479
+ });
2480
+ newParagraph.apply(new AppendChildrenAction(newListItem.children));
2481
+ parentParent.apply(new InsertChildrenAfterAction(target.parent, newParagraph));
2482
+ target.parent.apply(new RemoveChildrenAction(target));
2483
+ return newParagraph;
2484
+ }
2485
+ else {
2486
+ parentParent.parent.apply(new InsertChildrenAfterAction(parentParent, newListItem));
2487
+ target.parent.apply(new RemoveChildrenAction(target));
2488
+ }
2489
+ }
2490
+ else {
2491
+ target.parent.apply(new InsertChildrenAfterAction(target, newListItem));
2492
+ }
2493
+ return newListItem;
2341
2494
  }
2342
2495
  /**
2343
- * Handle annotation.
2496
+ * Copy the inline style to new node
2344
2497
  *
2345
- * @param {HTMLElement} element - Current elements.
2346
- * @returns {VegaRTEImageAnnotations} - Annotation.
2498
+ * @param {RTETextNode} needCopedNode - The node that needed to be copied to
2499
+ * @returns {RTETextNode} Returns a `RTETextNode`.
2347
2500
  */
2348
- handle(element) {
2349
- return element.hasAttribute('alt') ? { alt: element.getAttribute('alt') } : {};
2501
+ copyInlineStyleToNewNode(needCopedNode) {
2502
+ const textNode = needCopedNode.cloneWithText('');
2503
+ // The link annotation doesn't need to inherit
2504
+ textNode.annotationMap.delete(NodeAnnotationTypeEnum.LINK);
2505
+ return textNode;
2350
2506
  }
2351
2507
  }
2352
2508
 
2353
2509
  /**
2354
- * Handle inline html annotation
2510
+ * Delete the nest list block action
2511
+ *
2512
+ * @example needRemovedNestList.parent.apply(new RemoveNestListAction(needRemovedNestList))
2355
2513
  */
2356
- class InlineHtmlAnnotationHandler extends AnnotationGeneratorStrategyAbstract {
2357
- constructor() {
2358
- super(...arguments);
2359
- this.customAttributeHandler = new CustomAttributeAnnotationHandler();
2360
- this.customStyleAnnotationHandler = new CustomStyleAnnotationHandler();
2361
- this.customClassAnnotationHandler = new CustomClassAnnotationHandler();
2362
- }
2363
- /**
2364
- * @inheritDoc
2365
- */
2366
- canHandle(targetDto, options) {
2367
- return targetDto.name === 'RTETextNode' && options.autoMatchFormat === false;
2368
- }
2369
- /**
2370
- * @inheritDoc
2371
- */
2372
- handle(element, parentAnnotations) {
2373
- const canHandle = InlineHtmlAnnotationHandler.canHandleTags.includes(element.nodeName);
2374
- if (canHandle) {
2375
- const inlineHtml = this.generateInlineHtmlAnnotation(element, Object.assign({}, parentAnnotations));
2376
- if (inlineHtml) {
2377
- return { inlineHtml: inlineHtml };
2378
- }
2379
- }
2380
- return {};
2514
+ class RemoveNestListAction extends ModifyContentAction {
2515
+ constructor(childList) {
2516
+ super();
2517
+ this.type = ModifyContentActionType.DELETE_NEST_LIST;
2518
+ this.nestListBlockToBeRemoved = childList;
2381
2519
  }
2520
+ }
2521
+
2522
+ /**
2523
+ * List remove list item strategy.
2524
+ */
2525
+ class ListRemoveListItemStrategy extends RemoveChildrenStrategy {
2382
2526
  /**
2383
- * Generate inline html annotation.
2527
+ * Remove the list item, check the list item and remove self if the list item is empty.
2384
2528
  *
2385
- * @param {HTMLElement} child - Current element.
2386
- * @param {VegaRTETextAnnotations} annotations - Current annotations.
2387
- * @returns {Nullable<VegaInlineHtmlSchema>} - Inline html annotation.
2529
+ * @param {RemoveChildrenAction} action - The remove action instance.
2530
+ * @param {RTEListBlock} target - The list block.
2388
2531
  */
2389
- generateInlineHtmlAnnotation(child, annotations) {
2390
- let { inlineHtml } = annotations;
2391
- if (!RTETextNode.supportsHtmlTag(child.nodeName.toLowerCase()) ||
2392
- (child.childNodes.length === 1 && child.childNodes[0].nodeType !== Node.TEXT_NODE)) {
2393
- const childInlineHtmlNode = {
2394
- htmlTag: child.nodeName.toLowerCase(),
2395
- customAttribute: this.customAttributeHandler.handle(child).customAttribute,
2396
- customStyle: this.customStyleAnnotationHandler.handle(child).customStyle,
2397
- customClass: this.customClassAnnotationHandler.handle(child).customClass,
2398
- };
2399
- if (!inlineHtml) {
2400
- inlineHtml = childInlineHtmlNode;
2532
+ handleAction(action, target) {
2533
+ super.handleAction(action, target);
2534
+ const parent = target.parent;
2535
+ if (target.children.length === 0 && parent) {
2536
+ // The parent is a list item mean the current block is a nest list, so we need to use RemoveNestListAction to remove the item
2537
+ if (parent['type'] === 'list-item') {
2538
+ parent.apply(new RemoveNestListAction(target));
2401
2539
  }
2402
2540
  else {
2403
- let lastChild = inlineHtml;
2404
- while (lastChild.child &&
2405
- child.parentNode &&
2406
- lastChild.child.htmlTag === child.parentNode.nodeName.toLowerCase()) {
2407
- lastChild = lastChild.child;
2408
- }
2409
- lastChild.child = childInlineHtmlNode;
2541
+ parent.apply(new RemoveChildrenAction(target));
2410
2542
  }
2411
2543
  }
2412
- return inlineHtml ? Object.assign({}, inlineHtml) : null;
2413
2544
  }
2414
2545
  }
2415
- InlineHtmlAnnotationHandler.canHandleTags = [
2416
- 'A',
2417
- 'ABBR',
2418
- 'AUDIO',
2419
- 'B',
2420
- 'BDI',
2421
- 'BDO',
2422
- 'CITE',
2423
- 'CODE',
2424
- 'DEL',
2425
- 'DFN',
2426
- 'EMBED',
2427
- 'EM',
2428
- 'I',
2429
- 'INS',
2430
- 'KBD',
2431
- 'MARK',
2432
- 'METER',
2433
- 'OUTPUT',
2434
- 'PROGRESS',
2435
- 'Q',
2436
- 'S',
2437
- 'SMALL',
2438
- 'SPAN',
2439
- 'STRONG',
2440
- 'SUB',
2441
- 'SUP',
2442
- 'TIME',
2443
- 'U',
2444
- 'VAR',
2445
- 'VIDEO',
2446
- ];
2447
2546
 
2448
- /** Html element to annotations generator */
2449
- class HtmlElementToAnnotationGenerator {
2450
- constructor() {
2451
- this.handlers = [
2452
- new TextAlignAnnotationHandler(),
2453
- new IndentAnnotationHandler(),
2454
- new BoldAnnotationHandler(),
2455
- new ItalicAnnotationHandler(),
2456
- new UnderlineAnnotationHandler(),
2457
- new StrikeThroughAnnotationHandler(),
2458
- new ColorAnnotationHandler(),
2459
- new LinkAnnotationHandler(),
2460
- new CodeAnnotationHandler(),
2461
- new ImageSizeAnnotationHandler(),
2462
- new ImageAltAnnotationHandler(),
2463
- new CustomAttributeAnnotationHandler(),
2464
- new CustomClassAnnotationHandler(),
2465
- new CustomStyleAnnotationHandler(),
2466
- new LinkAnnotationHandler(),
2467
- new TextStyleAnnotationHandler(),
2468
- new InlineHtmlAnnotationHandler(),
2469
- ];
2470
- }
2547
+ /**
2548
+ * Manager class for registering DTO action strategies.
2549
+ */
2550
+ class RTEDTOActionStrategyManager {
2471
2551
  /**
2472
- * The function generates annotations for a given target DTO and HTML element based on a set of
2473
- * strategies.
2552
+ * Registers basic strategies for a given DTO class.
2474
2553
  *
2475
- * @typedef T class name of target DTO
2476
- * @typedef V generated annotations type
2477
- * @param {T} targetDto - Which DTO is the generated annotations to set.
2478
- * @param {HTMLElement} element - Current html element.
2479
- * @param {HtmlElementToAnnotationGenerateOptions} [options] - Options
2480
- * @returns {V} Generated annotations.
2554
+ * @param {string} dtoClassName - The name of the RTE block class name.
2481
2555
  */
2482
- generate(targetDto, element, options = { autoMatchFormat: true }) {
2483
- const isLinkElement = element.tagName === 'A';
2484
- return this.handlers
2485
- .filter((handler) => !options.autoMatchFormat && isLinkElement ? handler instanceof LinkAnnotationHandler : true)
2486
- .filter((handler) => element.nodeType !== Node.TEXT_NODE &&
2487
- handler.canHandle(targetDto, {
2488
- skipCustomAnnotations: options.skipCustomAnnotations || isLinkElement,
2489
- autoMatchFormat: options.autoMatchFormat,
2490
- }))
2491
- .reduce((annotations, handler) => {
2492
- const result = handler.handle(element, options.parentAnnotations);
2493
- return Object.assign(Object.assign({}, annotations), result);
2494
- }, {});
2556
+ registerBlockBasicStrategies(dtoClassName) {
2557
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.DELETE_CHILDREN, dtoClassName, dtoClassName === RTEListBlock.name
2558
+ ? new ListRemoveListItemStrategy()
2559
+ : new RemoveChildrenStrategy());
2560
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.APPEND_CHILDREN, dtoClassName, new AppendChildrenStrategy());
2561
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.INSERT_CHILDREN_BEFORE, dtoClassName, new InsertChildrenBeforeStrategy());
2562
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.INSERT_CHILDREN_AFTER, dtoClassName, new InsertChildrenAfterStrategy());
2563
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.DELETE_BLOCK_CONTENT, dtoClassName, new BlockDeleteTextOrDecoratorNodeStrategy());
2564
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.INSERT_NEW_PARAGRAPH, dtoClassName, dtoClassName === RTEListItemBlock.name
2565
+ ? new ListItemInsertNewParagraphStrategy()
2566
+ : new BlockInsertNewParagraphStrategy());
2567
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.INSERT_TEXT_TO_DECORATOR_NODE, dtoClassName, new InsertTextToDecoratorNodeStrategy());
2568
+ ActionHandleStrategyRegistry.register(ModifyContentActionType.INSERT_NODE_TO_NEAREST_ROOT, dtoClassName, new InsertNodeToNearestRootStrategy());
2495
2569
  }
2496
2570
  }
2497
- const htmlElementToAnnotationGenerator = new HtmlElementToAnnotationGenerator();
2571
+ const RTEDTOActionStrategyManager$1 = new RTEDTOActionStrategyManager();
2498
2572
 
2499
2573
  /** Abstract class for block html element to RTE block dto */
2500
2574
  class BlockToRTEBlockStrategyAbstract extends ElementToDTOStrategy {
@@ -3605,6 +3679,18 @@ class VegaRTEContent {
3605
3679
  apply(action) {
3606
3680
  ActionHandleStrategyRegistry.executeTheStrategy(action, this);
3607
3681
  }
3682
+ /**
3683
+ * Get the last node in the content.
3684
+ *
3685
+ * @returns {Nullable<RTENode>} The last node in the content or null if there are no nodes.
3686
+ */
3687
+ getLastNode() {
3688
+ if (this.children.length === 0) {
3689
+ return null;
3690
+ }
3691
+ const lastBlock = this.children[this.children.length - 1];
3692
+ return lastBlock.getLastNode();
3693
+ }
3608
3694
  /**
3609
3695
  * Convert text to list.
3610
3696
  *
@@ -3679,4 +3765,59 @@ class VegaRTEContent {
3679
3765
  ActionHandleStrategyRegistry.register(ModifyContentActionType.UPDATE_CURSOR_POSITION, VegaRTEContent.name, new UpdateCursorPositionStrategy());
3680
3766
  })();
3681
3767
 
3682
- export { ElementToDtoStrategyProcessor$1 as E, ImageAnnotation as I, MergeTwoBlocksNodesAction as M, RTEImageBlock as R, VegaRTEContent as V, RTEListItemBlock as a, RTEListBlock as b, RTEImageNode as c, InsertNewParagraphAction as d };
3768
+ /**
3769
+ * RTEDTORendererManager is a singleton class that manages the registration and retrieval of RTE DTO renderers.
3770
+ */
3771
+ class RTEDTORendererManager {
3772
+ constructor() {
3773
+ // Register RTE DTO renderers, mapping type strings to their respective renderer instances.
3774
+ this.RTE_DTO_RENDERER_MAP = new Map();
3775
+ // Register RTE Toolbar Button Renderers, mapping type strings to their respective renderer instances.
3776
+ this.RTE_TOOLBAR_BUTTON_RENDERER_MAP = new Map();
3777
+ }
3778
+ /**
3779
+ * Registers a new RTE DTO renderer.
3780
+ *
3781
+ * @param {string} type - The type identifier for the RTE DTO renderer.
3782
+ * @param {VegaRTEBaseRenderer} RTEDTORenderer - The renderer instance for the RTE DTO.
3783
+ */
3784
+ registerRTEDTORenderer(type, RTEDTORenderer) {
3785
+ const existRenderer = this.RTE_DTO_RENDERER_MAP.get(type);
3786
+ if (RTEDTORenderer &&
3787
+ existRenderer &&
3788
+ existRenderer.constructor.name !== RTEDTORenderer.constructor.name) {
3789
+ throw new Error(`Renderer for type ${type} is already registered with a different class(${existRenderer.constructor.name}).`);
3790
+ }
3791
+ this.RTE_DTO_RENDERER_MAP.set(type, RTEDTORenderer);
3792
+ }
3793
+ /**
3794
+ * Registers a new RTE Toolbar Button Renderer.
3795
+ *
3796
+ * @param {string} type - The type identifier for the RTE Toolbar Button Renderer.
3797
+ * @param {VegaRTEToolbarButtonRenderer} RTEToolbarButtonRenderer - The renderer instance for the RTE Toolbar Button.
3798
+ */
3799
+ registerRTEToolbarButtonRenderer(type, RTEToolbarButtonRenderer) {
3800
+ this.RTE_TOOLBAR_BUTTON_RENDERER_MAP.set(type, RTEToolbarButtonRenderer);
3801
+ }
3802
+ /**
3803
+ * Retrieves the RTE renderer for a given type.
3804
+ *
3805
+ * @param {string} type - The type identifier for the RTE block.
3806
+ * @returns {Nullable<BaseRenderer>} - The renderer instance for the RTE block, or null if not found.
3807
+ */
3808
+ getRTERenderer(type) {
3809
+ return this.RTE_DTO_RENDERER_MAP.get(type);
3810
+ }
3811
+ /**
3812
+ * Retrieves the RTE Toolbar Button Renderer for a given type.
3813
+ *
3814
+ * @param {string} type - The type identifier for the RTE Toolbar Button Renderer.
3815
+ * @returns {Nullable<VegaRTEToolbarButtonRenderer>} - The renderer instance for the RTE Toolbar Button, or null if not found.
3816
+ */
3817
+ getRTEToolbarButtonRenderer(type) {
3818
+ return this.RTE_TOOLBAR_BUTTON_RENDERER_MAP.get(type);
3819
+ }
3820
+ }
3821
+ const RTEDTORendererManager$1 = new RTEDTORendererManager();
3822
+
3823
+ export { ElementToDTOClassStrategyManager as E, ImageAnnotation as I, MergeTwoBlocksNodesAction as M, RTEDTORendererManager$1 as R, UpdateCursorPositionAction as U, VegaRTEContent as V, RTEDTOActionStrategyManager$1 as a, ElementToDTOStrategy as b, RTEListItemBlock as c, RTEImageBlock as d, RTEListBlock as e, RTEImageNode as f, InsertNewParagraphAction as g, ElementToDtoStrategyProcessor$1 as h };