@globalpayments/vega 2.37.2 → 2.39.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.
- package/dist/cjs/{app-globals-7087f121.js → app-globals-dd3e7925.js} +2 -3
- package/dist/cjs/content-state-c5b47ca1.js +6644 -0
- package/dist/cjs/{image-annotation-action-7d82f7e1.js → image-annotation-action-75b9c0d3.js} +5 -6
- package/dist/cjs/index.cjs.js +13 -14
- package/dist/cjs/loader.cjs.js +8 -9
- package/dist/cjs/vega-date-picker_2.cjs.entry.js +1 -1
- package/dist/cjs/vega-env-manager-23b8b23c.js +2 -2
- package/dist/cjs/vega-input-phone-number.cjs.entry.js +31 -7
- package/dist/cjs/vega-popover_2.cjs.entry.js +14 -0
- package/dist/cjs/vega-rich-text-content.cjs.entry.js +18 -19
- package/dist/cjs/vega-rich-text-editor_4.cjs.entry.js +75 -79
- package/dist/cjs/vega.cjs.js +8 -9
- package/dist/collection/components/vega-input-phone-number/slimmers/controllers/vega-input-phone-number-value-controller.js +18 -2
- package/dist/collection/components/vega-input-phone-number/vega-input-phone-number.js +7 -4
- package/dist/collection/components/vega-popover/slimmers/controllers/vega-popover-appender-controller.js +4 -0
- package/dist/collection/components/vega-popover/vega-popover.js +37 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/action-handle-strategy-registry.js +52 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/action-handle-strategy.abstract.js +63 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/apply-annotation-strategies/block-update-link-group-strategy.js +21 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/apply-annotation-strategies/block-update-text-style-strategy.js +32 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/apply-annotation-strategies/image-set-annotation-map-strategy.js +13 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/apply-annotation-strategies/node-split-text-strategy.js +134 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/apply-annotation-strategies/node-update-annotation-map-strategy.js +47 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-append-blocks-strategy.js +19 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-append-nodes-strategy.js +21 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-delete-image-strategy.js +54 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-delete-node-content-strategy.js +152 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-delete-text-content-strategy.js +99 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-blocks-after-strategy.js +15 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-blocks-before-strategy.js +38 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-image-into-text-strategy.js +31 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-line-break-strategy.js +57 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-line-break-with-blocks-strategy.js +60 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-new-paragraph-strategy.js +55 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-nodes-after-node-strategy.js +14 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-nodes-before-node-strategy.js +14 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-merge-nodes-strategy.js +25 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-remove-child-block-strategy.js +15 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-remove-node-strategy.js +21 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-replace-node-with-nodes-strategy.js +28 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-replace-nodes-strategy.js +17 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-split-with-image-node-strategy.js +48 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-split-with-text-node-strategy.js +43 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-transform-to-list-strategy.js +26 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/image-block-insert-image-strategy.js +32 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/image-insert-line-break-strategy.js +21 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/image-insert-line-break-with-blocks-strategy.js +55 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/image-insert-new-paragraph-strategy.js +44 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/image-update-url-strategy.js +12 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-insert-image-strategy.js +22 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-delete-text-content-strategy.js +20 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-insert-image-strategy.js +15 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-insert-new-paragraph-strategy.js +92 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-remove-nest-list-strategy.js +22 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-remove-node-strategy.js +19 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-replace-nest-list-strategy.js +15 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-remove-list-item-strategy.js +27 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-transform-to-list-strategy.js +36 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-transform-to-paragraph-strategy.js +63 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/node-replace-selected-text-strategy.js +46 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/node-update-text-strategy.js +20 -0
- package/dist/collection/components/vega-rich-text-editor/dto/actions/image-update-url-action.js +13 -0
- package/dist/collection/components/vega-rich-text-editor/dto/actions/modify-content-action.abstract.js +1 -1
- package/dist/collection/components/vega-rich-text-editor/dto/blocks/block.abstract.js +3 -215
- package/dist/collection/components/vega-rich-text-editor/dto/blocks/image-block.js +31 -244
- package/dist/collection/components/vega-rich-text-editor/dto/blocks/list-block.js +17 -155
- package/dist/collection/components/vega-rich-text-editor/dto/blocks/list-item-block.js +33 -184
- package/dist/collection/components/vega-rich-text-editor/dto/blocks/text-block.js +40 -352
- package/dist/collection/components/vega-rich-text-editor/dto/content-state.js +13 -23
- package/dist/collection/components/vega-rich-text-editor/dto/nodes/image-node.js +14 -6
- package/dist/collection/components/vega-rich-text-editor/dto/nodes/text-node.js +23 -182
- package/dist/collection/components/vega-rich-text-editor/slimmers/renderers/tools/image-toolbar-button-slimmer.js +2 -1
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/action-handle-strategy-registry.test.js +41 -0
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/block-insert-line-break-with-blocks-strategy.test.js +24 -0
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/content-state-strategy-registry.test.js +14 -0
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/image-block-strategy-register.test.js +30 -0
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/image-set-annotation-map-strategy.test.js +11 -0
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/image-update-url-strategy.test.js +16 -0
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/list-block-strategy-register.test.js +20 -0
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/list-item-strategy-register.test.js +31 -0
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/node-split-text-strategy.test.js +31 -0
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/node-update-annotation-map-strategy.test.js +17 -0
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/text-block-strategy-register.test.js +55 -0
- package/dist/collection/components/vega-rich-text-editor/test/dto/action-handle-strategies/update-selected-text-strategy.test.js +23 -0
- package/dist/collection/components/vega-rich-text-editor/vega-rich-text-editor.js +2 -2
- package/dist/collection/helpers/validator/rules/valid-phone-number-rule.js +7 -2
- package/dist/collection/helpers/validator/test/rules/valid-phone-number-rule.test.js +8 -0
- package/dist/esm/{app-globals-4cca4a96.js → app-globals-c954167a.js} +2 -3
- package/dist/esm/content-state-2edba4ec.js +6600 -0
- package/dist/esm/{form-field-controller-slimmer-3535e76a.js → form-field-controller-slimmer-7a9f2b2e.js} +1 -1
- package/dist/esm/{image-annotation-action-3da42221.js → image-annotation-action-b6668f48.js} +1 -2
- package/dist/esm/{index-6e05b241.js → index-d172bafa.js} +1 -1
- package/dist/esm/index.js +5 -6
- package/dist/esm/loader.js +9 -10
- package/dist/esm/{string-input-formatter-slimmer-d4132497.js → string-input-formatter-slimmer-418b54f0.js} +2 -2
- package/dist/esm/{sub-state-notify-slimmer-51151fc3.js → sub-state-notify-slimmer-b36fd081.js} +1 -1
- package/dist/esm/{sub-state-observer-slimmer-d77a1c46.js → sub-state-observer-slimmer-09452523.js} +1 -1
- package/dist/esm/vega-button-group_2.entry.js +3 -3
- package/dist/esm/vega-calendar_3.entry.js +3 -3
- package/dist/esm/vega-checkbox_2.entry.js +2 -2
- package/dist/esm/vega-color-picker.entry.js +2 -2
- package/dist/esm/vega-combo-box.entry.js +2 -2
- package/dist/esm/vega-date-picker_2.entry.js +5 -5
- package/dist/esm/vega-dropdown_5.entry.js +3 -3
- package/dist/esm/vega-env-manager-8f8dc473.js +2 -2
- package/dist/esm/vega-file-uploader.entry.js +2 -2
- package/dist/esm/vega-form.entry.js +2 -2
- package/dist/esm/vega-image-uploader.entry.js +2 -2
- package/dist/esm/vega-input-credit-card.entry.js +2 -2
- package/dist/esm/vega-input-numeric.entry.js +3 -3
- package/dist/esm/vega-input-phone-number.entry.js +33 -9
- package/dist/esm/vega-input-range.entry.js +2 -2
- package/dist/esm/vega-input-select.entry.js +2 -2
- package/dist/esm/vega-input.entry.js +5 -5
- package/dist/esm/{vega-internal-event-id-d0690d0d.js → vega-internal-event-id-f269c42f.js} +1 -1
- package/dist/esm/vega-left-nav_5.entry.js +3 -3
- package/dist/esm/vega-popover_2.entry.js +15 -1
- package/dist/esm/vega-radio_2.entry.js +2 -2
- package/dist/esm/vega-rich-text-content.entry.js +6 -7
- package/dist/esm/vega-rich-text-editor_4.entry.js +21 -25
- package/dist/esm/vega-selection-chip_2.entry.js +4 -4
- package/dist/esm/vega-selection-tile_2.entry.js +4 -4
- package/dist/esm/vega-sidenav_3.entry.js +3 -3
- package/dist/esm/vega-signature-capture.entry.js +2 -2
- package/dist/esm/vega-stepper.entry.js +2 -2
- package/dist/esm/vega-table_8.entry.js +3 -3
- package/dist/esm/vega-textarea.entry.js +2 -2
- package/dist/esm/vega-time-picker_2.entry.js +2 -2
- package/dist/esm/vega-toggle-switch.entry.js +2 -2
- package/dist/esm/vega.js +9 -10
- package/dist/types/components/vega-input-phone-number/slimmers/controllers/vega-input-phone-number-value-controller.d.ts +7 -0
- package/dist/types/components/vega-popover/slimmers/controllers/vega-popover-appender-controller.d.ts +1 -0
- package/dist/types/components/vega-popover/vega-popover.d.ts +10 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/action-handle-strategy-registry.d.ts +37 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/action-handle-strategy.abstract.d.ts +66 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/apply-annotation-strategies/block-update-link-group-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/apply-annotation-strategies/block-update-text-style-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/apply-annotation-strategies/image-set-annotation-map-strategy.d.ts +13 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/apply-annotation-strategies/node-split-text-strategy.d.ts +47 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/apply-annotation-strategies/node-update-annotation-map-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-append-blocks-strategy.d.ts +13 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-append-nodes-strategy.d.ts +16 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-delete-image-strategy.d.ts +19 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-delete-node-content-strategy.d.ts +61 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-delete-text-content-strategy.d.ts +19 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-blocks-after-strategy.d.ts +13 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-blocks-before-strategy.d.ts +23 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-image-into-text-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-line-break-strategy.d.ts +30 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-line-break-with-blocks-strategy.d.ts +36 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-new-paragraph-strategy.d.ts +29 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-nodes-after-node-strategy.d.ts +13 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-insert-nodes-before-node-strategy.d.ts +13 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-merge-nodes-strategy.d.ts +16 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-remove-child-block-strategy.d.ts +13 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-remove-node-strategy.d.ts +17 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-replace-node-with-nodes-strategy.d.ts +20 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-replace-nodes-strategy.d.ts +16 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-split-with-image-node-strategy.d.ts +30 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-split-with-text-node-strategy.d.ts +24 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-transform-to-list-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/image-block-insert-image-strategy.d.ts +12 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/image-insert-line-break-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/image-insert-line-break-with-blocks-strategy.d.ts +27 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/image-insert-new-paragraph-strategy.d.ts +21 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/image-update-url-strategy.d.ts +12 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-insert-image-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-delete-text-content-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-insert-image-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-insert-new-paragraph-strategy.d.ts +38 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-remove-nest-list-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-remove-node-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-replace-nest-list-strategy.d.ts +12 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-remove-list-item-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-transform-to-list-strategy.d.ts +12 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-transform-to-paragraph-strategy.d.ts +19 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/node-replace-selected-text-strategy.d.ts +20 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/node-update-text-strategy.d.ts +15 -0
- package/dist/types/components/vega-rich-text-editor/dto/actions/image-update-url-action.d.ts +11 -0
- package/dist/types/components/vega-rich-text-editor/dto/actions/modify-content-action.abstract.d.ts +2 -2
- package/dist/types/components/vega-rich-text-editor/dto/blocks/block.abstract.d.ts +1 -79
- package/dist/types/components/vega-rich-text-editor/dto/blocks/image-block.d.ts +3 -77
- package/dist/types/components/vega-rich-text-editor/dto/blocks/list-block.d.ts +0 -38
- package/dist/types/components/vega-rich-text-editor/dto/blocks/list-item-block.d.ts +3 -58
- package/dist/types/components/vega-rich-text-editor/dto/blocks/text-block.d.ts +5 -93
- package/dist/types/components/vega-rich-text-editor/dto/content-state.d.ts +1 -2
- package/dist/types/components/vega-rich-text-editor/dto/nodes/text-node.d.ts +0 -43
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/action-handle-strategy-registry.test.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/block-insert-line-break-with-blocks-strategy.test.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/content-state-strategy-registry.test.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/image-block-strategy-register.test.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/image-set-annotation-map-strategy.test.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/image-update-url-strategy.test.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/list-block-strategy-register.test.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/list-item-strategy-register.test.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/node-split-text-strategy.test.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/node-update-annotation-map-strategy.test.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/text-block-strategy-register.test.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/test/dto/action-handle-strategies/update-selected-text-strategy.test.d.ts +1 -0
- package/dist/types/components.d.ts +14 -0
- package/dist/types/helpers/validator/rules/valid-phone-number-rule.d.ts +3 -1
- package/dist/vega/index.esm.js +1 -1
- package/dist/vega/{p-ba077ca8.entry.js → p-073beb31.entry.js} +1 -1
- package/dist/vega/{p-6419e13e.entry.js → p-0b697841.entry.js} +1 -1
- package/dist/vega/p-0cc1ad76.js +1 -0
- package/dist/vega/{p-29d6ec6c.js → p-239bae84.js} +1 -1
- package/dist/vega/{p-7198d675.entry.js → p-24ac5151.entry.js} +1 -1
- package/dist/vega/{p-cb4fd6e1.entry.js → p-257b1bc2.entry.js} +1 -1
- package/dist/vega/{p-ba2833c0.entry.js → p-3c85a11b.entry.js} +1 -1
- package/dist/vega/{p-b517ed15.js → p-49bf2b3a.js} +1 -1
- package/dist/vega/p-4a8db510.entry.js +1 -0
- package/dist/vega/p-4b19706c.entry.js +1 -0
- package/dist/vega/{p-bf4996d5.entry.js → p-4e436842.entry.js} +1 -1
- package/dist/vega/{p-12fe63c1.entry.js → p-59834ea4.entry.js} +1 -1
- package/dist/vega/{p-50eabdca.entry.js → p-59cfed37.entry.js} +1 -1
- package/dist/vega/p-5f377954.js +1 -1
- package/dist/vega/p-60e1ebe1.entry.js +1 -0
- package/dist/vega/{p-23fd9401.entry.js → p-629bd266.entry.js} +1 -1
- package/dist/vega/p-6408d3dc.entry.js +1 -0
- package/dist/vega/{p-3e8f9fcf.entry.js → p-64e0c944.entry.js} +1 -1
- package/dist/vega/{p-b9a0f136.entry.js → p-64e49394.entry.js} +1 -1
- package/dist/vega/p-6e5db02b.js +1 -0
- package/dist/vega/{p-9689ad99.entry.js → p-74ff73d6.entry.js} +1 -1
- package/dist/vega/{p-b809f3d7.entry.js → p-8120e7a1.entry.js} +1 -1
- package/dist/vega/p-894c067a.entry.js +1 -0
- package/dist/vega/{p-e9785742.entry.js → p-989b36a2.entry.js} +1 -1
- package/dist/vega/{p-a2a34239.entry.js → p-9ee23f34.entry.js} +1 -1
- package/dist/vega/{p-34bd9204.js → p-a9e1123a.js} +1 -1
- package/dist/vega/{p-267cde46.entry.js → p-b071be5c.entry.js} +1 -1
- package/dist/vega/{p-1b67c443.entry.js → p-b6bffdf3.entry.js} +1 -1
- package/dist/vega/{p-20326c64.js → p-bd0116f9.js} +1 -1
- package/dist/vega/{p-a7e078ac.entry.js → p-bf6d3c00.entry.js} +1 -1
- package/dist/vega/{p-ecaf4cfa.entry.js → p-c00fde35.entry.js} +1 -1
- package/dist/vega/{p-7baa4fae.entry.js → p-c2e96537.entry.js} +1 -1
- package/dist/vega/{p-3cb90bdf.entry.js → p-ce94a9c5.entry.js} +1 -1
- package/dist/vega/{p-904b489a.entry.js → p-d03945cb.entry.js} +1 -1
- package/dist/vega/p-d2e6090a.js +1 -0
- package/dist/vega/{p-348e95ba.js → p-d2ff56d8.js} +1 -1
- package/dist/vega/p-e0d3ca2d.js +1 -0
- package/dist/vega/{p-ee2e4bff.entry.js → p-ea78ddfa.entry.js} +1 -1
- package/dist/vega/{p-e9a5bd12.entry.js → p-f1ebe86b.entry.js} +1 -1
- package/dist/vega/{p-497f2f86.entry.js → p-fc49a98e.entry.js} +1 -1
- package/dist/vega/vega.esm.js +1 -1
- package/package.json +1 -1
- package/dist/cjs/content-state-f97d3278.js +0 -2990
- package/dist/cjs/node-annotation.abstract-4f6df9cf.js +0 -3223
- package/dist/collection/components/vega-rich-text-editor/dto/actions/clear-child-nodes-action.js +0 -12
- package/dist/collection/components/vega-rich-text-editor/dto/helper/block-base-operator.js +0 -47
- package/dist/esm/content-state-ccf5f960.js +0 -2954
- package/dist/esm/node-annotation.abstract-b2e36bc4.js +0 -3214
- package/dist/types/components/vega-rich-text-editor/dto/actions/clear-child-nodes-action.d.ts +0 -9
- package/dist/types/components/vega-rich-text-editor/dto/helper/block-base-operator.d.ts +0 -24
- package/dist/vega/p-0461e318.js +0 -1
- package/dist/vega/p-1d93b3a9.js +0 -1
- package/dist/vega/p-2fecbcf9.entry.js +0 -1
- package/dist/vega/p-52a8a4f8.js +0 -1
- package/dist/vega/p-7edcb8d0.entry.js +0 -1
- package/dist/vega/p-9728d571.entry.js +0 -1
- package/dist/vega/p-a7f40a65.entry.js +0 -1
- package/dist/vega/p-a8b16ff2.js +0 -1
- package/dist/vega/p-aed80794.entry.js +0 -1
- package/dist/vega/p-f86ec91b.js +0 -1
|
@@ -1,2954 +0,0 @@
|
|
|
1
|
-
import { B as BlockAnnotation, a as BlockAnnotationTypeEnum, M as ModifyContentAction, b as ModifyContentActionType, s as stateEntityRenderingRegistry, N as NodeAnnotation, c as NodeAnnotationTypeEnum, R as RTENode, d as NodeTypeEnum, A as Annotation, I as InternalAnnotationTypeEnum, V as VegaThemeManager } from './node-annotation.abstract-b2e36bc4.js';
|
|
2
|
-
import { C as ChangeManager } from './change-manager-6a7eb88c.js';
|
|
3
|
-
import { d as domNodeSubjectFactory } from './dom-node-subject-factory-97deb349.js';
|
|
4
|
-
import { V as VegaInternalRichTextEditorFlushChanges, b as VegaInternalRichTextEditorSelectionRangeChange } from './vega-internal-event-id-d0690d0d.js';
|
|
5
|
-
import { i as isNonNullable } from './type-guard-158f6d7a.js';
|
|
6
|
-
import './global-slimmer-registry-17c4efd4.js';
|
|
7
|
-
import { g as generateUUID } from './create-public-api-runtime-metrics-slimmer-9ab05523.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Annotation to make block with horizontal alignment
|
|
11
|
-
*/
|
|
12
|
-
class HorizontalAlignmentAnnotation extends BlockAnnotation {
|
|
13
|
-
constructor(textAlign) {
|
|
14
|
-
super();
|
|
15
|
-
this.type = BlockAnnotationTypeEnum.ALIGNMENT;
|
|
16
|
-
this.textAlign = textAlign;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Generate the map item for the annotation
|
|
20
|
-
*
|
|
21
|
-
* @param {VegaRTEBlockAlignment} textAlign - Text alignment
|
|
22
|
-
* @returns {[BlockAnnotationTypeEnum.ALIGNMENT, HorizontalAlignmentAnnotation]} Map item for the annotation
|
|
23
|
-
*/
|
|
24
|
-
static from(textAlign) {
|
|
25
|
-
return [BlockAnnotationTypeEnum.ALIGNMENT, new HorizontalAlignmentAnnotation(textAlign)];
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Generate the JSON item of the annotation
|
|
29
|
-
*
|
|
30
|
-
* @returns {Record<string, unknown>} JSON representation of the annotation
|
|
31
|
-
*/
|
|
32
|
-
toJSON() {
|
|
33
|
-
return {
|
|
34
|
-
textAlign: this.textAlign,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Generate the class for the annotation
|
|
39
|
-
*
|
|
40
|
-
* @returns {string} - Annotation class
|
|
41
|
-
*/
|
|
42
|
-
renderClass() {
|
|
43
|
-
return `v-rte--horizontal-alignment-${this.textAlign}`;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Generate the style for the annotation
|
|
47
|
-
*
|
|
48
|
-
* @returns {Nullable<AnnotationStyle>} - Annotation style
|
|
49
|
-
*/
|
|
50
|
-
render() {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Annotation for block indentation
|
|
57
|
-
*/
|
|
58
|
-
class IndentAnnotation extends BlockAnnotation {
|
|
59
|
-
constructor(indent) {
|
|
60
|
-
super();
|
|
61
|
-
this.type = BlockAnnotationTypeEnum.INDENT;
|
|
62
|
-
this.indent = Math.max(0, indent);
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Generate the map item for the annotation
|
|
66
|
-
*
|
|
67
|
-
* @param {number} indent - Text alignment
|
|
68
|
-
* @returns {[BlockAnnotationTypeEnum.INDENT, IndentAnnotation]} Map item for the annotation
|
|
69
|
-
*/
|
|
70
|
-
static from(indent) {
|
|
71
|
-
return [BlockAnnotationTypeEnum.INDENT, new IndentAnnotation(indent)];
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Generate the JSON item of the annotation
|
|
75
|
-
*
|
|
76
|
-
* @returns {Record<string, unknown>} JSON representation of the annotation
|
|
77
|
-
*/
|
|
78
|
-
toJSON() {
|
|
79
|
-
return this.indent > 0 ? { indent: this.indent } : null;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Generate the style for the annotation
|
|
83
|
-
*
|
|
84
|
-
* @returns {Nullable<AnnotationStyle>} - Annotation style
|
|
85
|
-
*/
|
|
86
|
-
render() {
|
|
87
|
-
return this.indent > 0 ? { 'margin-left': `${this.indent * 16}px` } : null;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** The class contains some common method to modify the blocks property */
|
|
92
|
-
class BlockBaseOperator {
|
|
93
|
-
/**
|
|
94
|
-
* Replaces a specific block with an array of blocks within a RTEContentBlock array.
|
|
95
|
-
*
|
|
96
|
-
* @param {RTEBlock} referBlock - Used as a reference block to identify the block that needs to be replaced in the `blocks` array.
|
|
97
|
-
* @param {RTEBlock[]} blocks - An array of RTEBlock objects that you want to replace the `referBlock` with in the `blocks` array.
|
|
98
|
-
*/
|
|
99
|
-
replaceBlockWithBlocks(referBlock, blocks) {
|
|
100
|
-
if (this.blocks) {
|
|
101
|
-
blocks.forEach((block) => {
|
|
102
|
-
block.parent = this;
|
|
103
|
-
});
|
|
104
|
-
this.blocks = this.blocks.flatMap((block) => {
|
|
105
|
-
if (block === referBlock) {
|
|
106
|
-
return blocks;
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
return block;
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Appends new blocks to an array and sets their parent property to a specific type.
|
|
116
|
-
*
|
|
117
|
-
* @param {RTEBlock[]} newBlocks - An array of `RTEBlock` objects that are being passed to the `appendChildBlocks` method.
|
|
118
|
-
*/
|
|
119
|
-
appendChildBlocks(newBlocks) {
|
|
120
|
-
if (this.blocks) {
|
|
121
|
-
newBlocks.forEach((block) => {
|
|
122
|
-
block.parent = this;
|
|
123
|
-
});
|
|
124
|
-
this.blocks = this.blocks.concat(newBlocks);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Removes a specified RTEBlock from an array of blocks.
|
|
129
|
-
*
|
|
130
|
-
* @param {RTEBlock} blockToBeRemoved - The block that needs to be removed from the `blocks` array.
|
|
131
|
-
*/
|
|
132
|
-
removeChildBlock(blockToBeRemoved) {
|
|
133
|
-
if (this.blocks) {
|
|
134
|
-
this.blocks = this.blocks.filter((block) => block !== blockToBeRemoved);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/** Append blocks or nodes to a block */
|
|
140
|
-
class AppendChildNodesAction extends ModifyContentAction {
|
|
141
|
-
constructor(childNodes) {
|
|
142
|
-
super();
|
|
143
|
-
this.type = ModifyContentActionType.APPEND_CHILD_NODES;
|
|
144
|
-
this.entityToBeAppended = childNodes;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Delete child node or child block from the current list action
|
|
150
|
-
*
|
|
151
|
-
* @example needRemovedNode.parentBlock.apply(new RemoveChildAction(needRemovedNode))
|
|
152
|
-
* @example needRemovedBlock.parent.apply(new RemoveChildAction(needRemovedBlock))
|
|
153
|
-
*/
|
|
154
|
-
class RemoveChildAction extends ModifyContentAction {
|
|
155
|
-
constructor(childNode) {
|
|
156
|
-
super();
|
|
157
|
-
this.type = ModifyContentActionType.DELETE_CHILD;
|
|
158
|
-
this.entityToBeRemoved = childNode;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const RTE_TEXT_COLORS = [
|
|
163
|
-
{
|
|
164
|
-
key: 'black',
|
|
165
|
-
light: '#111128',
|
|
166
|
-
dark: '#E3E3E8',
|
|
167
|
-
},
|
|
168
|
-
{
|
|
169
|
-
key: 'gray',
|
|
170
|
-
light: '#5E5E6D',
|
|
171
|
-
dark: '#B9B9C1',
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
key: 'green',
|
|
175
|
-
light: '#01801F',
|
|
176
|
-
dark: '#59D977',
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
key: 'red',
|
|
180
|
-
light: '#BD2947',
|
|
181
|
-
dark: '#FFB2B5',
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
key: 'purple',
|
|
185
|
-
light: '#563D82',
|
|
186
|
-
dark: '#BEB2FF',
|
|
187
|
-
},
|
|
188
|
-
{
|
|
189
|
-
key: 'teal',
|
|
190
|
-
light: '#17758F',
|
|
191
|
-
dark: '#4CD8FF',
|
|
192
|
-
},
|
|
193
|
-
];
|
|
194
|
-
const ZERO_WIDTH_SPACE = '\u200b';
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Abstract class for block
|
|
198
|
-
*/
|
|
199
|
-
class RTEBlock extends BlockBaseOperator {
|
|
200
|
-
constructor(id) {
|
|
201
|
-
super();
|
|
202
|
-
this.annotationMap = new Map();
|
|
203
|
-
this.id = id;
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* The function `createAnnotationEntity` creates a block annotation entity based on the provided type
|
|
207
|
-
* and value.
|
|
208
|
-
*
|
|
209
|
-
* @param {keyof VegaRTEBlockAnnotations} type - The `type` parameter is a key of the `VegaRTEBlockAnnotations` enum, which specifies
|
|
210
|
-
* the type of annotation entity to create.
|
|
211
|
-
* @param {unknown} value - The `value` parameter in the `createAnnotationEntity` function is the value
|
|
212
|
-
* that will be used to create the annotation entity. It can be of any type depending on the specific
|
|
213
|
-
* annotation being created.
|
|
214
|
-
* @returns {Nullable<[BlockAnnotationTypeEnum, BlockAnnotation]>} The `createAnnotationEntity` function returns a nullable tuple containing a
|
|
215
|
-
* `BlockAnnotationTypeEnum` and a `BlockAnnotation` object.
|
|
216
|
-
*/
|
|
217
|
-
static createAnnotationEntity(type, value) {
|
|
218
|
-
switch (type) {
|
|
219
|
-
case 'textAlign':
|
|
220
|
-
return HorizontalAlignmentAnnotation.from(value);
|
|
221
|
-
case 'indent':
|
|
222
|
-
return IndentAnnotation.from(value);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Class to JSON object
|
|
227
|
-
*
|
|
228
|
-
* @returns {VegaRTEBlockBase} - JSON object
|
|
229
|
-
*/
|
|
230
|
-
toJSON() {
|
|
231
|
-
const annotations = Array.from(this.annotationMap.values())
|
|
232
|
-
.filter((annotation) => annotation instanceof BlockAnnotation)
|
|
233
|
-
.reduce((record, annotation) => {
|
|
234
|
-
return Object.assign(Object.assign({}, record), annotation.toJSON());
|
|
235
|
-
}, {});
|
|
236
|
-
return Object.assign({ id: this.id }, (Object.keys(annotations).length > 0 ? { annotations } : {}));
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Get annotation by type
|
|
240
|
-
*
|
|
241
|
-
* @param {keyof typeof BlockAnnotationTypeEnum} type - Annotation type
|
|
242
|
-
* @returns {Nullable<BlockAnnotation> | Nullable<LinkGroupAnnotation>} - Annotation
|
|
243
|
-
*/
|
|
244
|
-
getAnnotationByType(type) {
|
|
245
|
-
return this.annotationMap.get(type);
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Apply action to block
|
|
249
|
-
*
|
|
250
|
-
* @param {AnnotationAction} action - Annotation action
|
|
251
|
-
*/
|
|
252
|
-
apply(action) {
|
|
253
|
-
this.doApply(action);
|
|
254
|
-
if (action.isFlushable) {
|
|
255
|
-
const domNode = stateEntityRenderingRegistry.getDOMByEntity(this);
|
|
256
|
-
if (domNode) {
|
|
257
|
-
const nodeSubject = domNodeSubjectFactory.getSubjectFromParentNodeByEventId(domNode, VegaInternalRichTextEditorFlushChanges);
|
|
258
|
-
if (nodeSubject) {
|
|
259
|
-
ChangeManager.notify(nodeSubject, {});
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* Apply action to block
|
|
266
|
-
*
|
|
267
|
-
* @param {AnnotationAction|ModifyContentAction} action - Annotation action
|
|
268
|
-
*/
|
|
269
|
-
doApply(action) {
|
|
270
|
-
if (action instanceof ModifyContentAction) {
|
|
271
|
-
this.doModifyActionApply(action);
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
this.applyAnnotationAction(action);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Apply annotation action to block
|
|
279
|
-
*
|
|
280
|
-
* @param {AnnotationAction} action - Annotation action
|
|
281
|
-
*/
|
|
282
|
-
applyAnnotationAction(action) {
|
|
283
|
-
const annotation = action.toAnnotation();
|
|
284
|
-
this.annotationMap.set(annotation.type, annotation);
|
|
285
|
-
typeof this.doAnnotationActionApply === 'function' && this.doAnnotationActionApply(action);
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Appends a list of RTENode objects to the current node's child nodes and sets the parent block of each node to the current node.
|
|
289
|
-
*
|
|
290
|
-
* @param {RTENode[]} nodesToBeAppended - An array of `RTENode` objects that you want to append to the current block.
|
|
291
|
-
*/
|
|
292
|
-
appendChildNodes(nodesToBeAppended) {
|
|
293
|
-
nodesToBeAppended.forEach((node) => {
|
|
294
|
-
node.parentBlock = this;
|
|
295
|
-
});
|
|
296
|
-
this['nodes'] = this['nodes'].concat(nodesToBeAppended);
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Merges the child nodes of two RTEBlocks if they have the same type or both are not images.
|
|
300
|
-
*
|
|
301
|
-
* @param {RTEBlock} secondBlock - A block of content in a rich text editor, such as a paragraph, heading, image, etc.
|
|
302
|
-
*/
|
|
303
|
-
mergeTwoBlocksNodes(secondBlock) {
|
|
304
|
-
if (this.type === secondBlock.type || (this.type !== 'image' && secondBlock.type !== 'image')) {
|
|
305
|
-
let shouldMergeNodes = secondBlock['nodes'];
|
|
306
|
-
if (this.type !== 'image') {
|
|
307
|
-
shouldMergeNodes = secondBlock['nodes'].filter((node) => node['text'] && node['text'] !== ZERO_WIDTH_SPACE);
|
|
308
|
-
}
|
|
309
|
-
this.apply(new AppendChildNodesAction(shouldMergeNodes));
|
|
310
|
-
secondBlock.parent.apply(new RemoveChildAction(secondBlock));
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Concat the child nodes of multiple RTEBlocks if both are not images.
|
|
315
|
-
*
|
|
316
|
-
* @param {RTEBlock[]} blocks - multiple block of content in a rich text editor, such as a paragraph, heading, image, etc.
|
|
317
|
-
* @returns {RTENode[]} Array of connected block nodes
|
|
318
|
-
*/
|
|
319
|
-
concatBlocksNodes(blocks) {
|
|
320
|
-
const nodes = [];
|
|
321
|
-
blocks.map((block) => {
|
|
322
|
-
if (block.type !== 'image') {
|
|
323
|
-
nodes.push(...block['nodes']);
|
|
324
|
-
block.parent.apply(new RemoveChildAction(block));
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
return nodes;
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Returns the previous node relative to the current node in a rich text editor structure.
|
|
331
|
-
*
|
|
332
|
-
* @param {RTENode} currentNode - An object of type `RTENode`.
|
|
333
|
-
* @returns {Nullable<RTENode>} the previous block last node
|
|
334
|
-
*/
|
|
335
|
-
getPreviousNode(currentNode) {
|
|
336
|
-
const currentBlock = currentNode.parentBlock;
|
|
337
|
-
const currentIndex = currentBlock['nodes'].indexOf(currentNode);
|
|
338
|
-
if (currentIndex > 0) {
|
|
339
|
-
return currentBlock['nodes'][currentIndex - 1];
|
|
340
|
-
}
|
|
341
|
-
else if (currentBlock.parent) {
|
|
342
|
-
const previousBlock = this.getPreviousBlock(currentBlock);
|
|
343
|
-
if (previousBlock) {
|
|
344
|
-
return this.getBlockLastNode(previousBlock);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* Returns the next node relative to the current node in a rich text editor structure.
|
|
350
|
-
*
|
|
351
|
-
* @param {RTENode} currentNode - An object of type `RTENode`.
|
|
352
|
-
* @returns {Nullable<RTENode>} the next block first node
|
|
353
|
-
*/
|
|
354
|
-
getNextNode(currentNode) {
|
|
355
|
-
const currentBlock = currentNode.parentBlock;
|
|
356
|
-
const currentIndex = currentBlock['nodes'].indexOf(currentNode);
|
|
357
|
-
if (currentBlock['nodes'][currentIndex + 1]) {
|
|
358
|
-
return currentBlock['nodes'][currentIndex + 1];
|
|
359
|
-
}
|
|
360
|
-
else if (currentBlock.parent) {
|
|
361
|
-
const nextBlock = this.getNextBlock(currentBlock);
|
|
362
|
-
if (nextBlock) {
|
|
363
|
-
return this.getBlockFirstNode(nextBlock);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
/**
|
|
368
|
-
* Determines if a given node is the first node within the current state.
|
|
369
|
-
*
|
|
370
|
-
* @param {RTENode} currentNode - An object representing a node in a rich text editor (RTE).
|
|
371
|
-
* @returns {boolean} True or false;
|
|
372
|
-
*/
|
|
373
|
-
isContentFirstNode(currentNode) {
|
|
374
|
-
const currentBlock = currentNode.parentBlock;
|
|
375
|
-
const currentIndex = currentBlock['nodes'].indexOf(currentNode);
|
|
376
|
-
const parent = currentBlock.parent;
|
|
377
|
-
if (currentBlock.type === 'list-item') {
|
|
378
|
-
const listParent = parent.parent;
|
|
379
|
-
return (currentIndex === 0 &&
|
|
380
|
-
Array.isArray(parent.blocks) &&
|
|
381
|
-
parent.blocks[0] === currentBlock &&
|
|
382
|
-
listParent['type'] !== 'list-item' &&
|
|
383
|
-
Array.isArray(listParent.blocks) &&
|
|
384
|
-
listParent.blocks[0] === parent);
|
|
385
|
-
}
|
|
386
|
-
else {
|
|
387
|
-
return currentIndex === 0 && Array.isArray(parent.blocks) && parent.blocks[0] === currentBlock;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* Returns the last node within a given RTE block, handling different block types accordingly.
|
|
392
|
-
*
|
|
393
|
-
* @param {RTEBlock} currentBlock - Returns the last node within that block.
|
|
394
|
-
* @returns {Nullable<RTENode>} Returns the last node of the given `currentBlock` object.
|
|
395
|
-
*/
|
|
396
|
-
getBlockLastNode(currentBlock) {
|
|
397
|
-
if (currentBlock.type === 'list-item') {
|
|
398
|
-
if (currentBlock['children'] && currentBlock['children'].length > 0) {
|
|
399
|
-
return this.getBlockLastNode(currentBlock['children'][currentBlock['children'].length - 1]);
|
|
400
|
-
}
|
|
401
|
-
else {
|
|
402
|
-
return currentBlock['nodes'][currentBlock['nodes'].length - 1];
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
else if (currentBlock.type === 'number-list' || currentBlock.type === 'bullet-list') {
|
|
406
|
-
if (currentBlock.blocks) {
|
|
407
|
-
const lastListItem = currentBlock.blocks[currentBlock.blocks.length - 1];
|
|
408
|
-
return this.getBlockLastNode(lastListItem);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
else {
|
|
412
|
-
if (currentBlock['nodes']) {
|
|
413
|
-
return currentBlock['nodes'][currentBlock['nodes'].length - 1];
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
/**
|
|
418
|
-
* Returns the first node within a given RTE block, handling different block types accordingly.
|
|
419
|
-
*
|
|
420
|
-
* @param {RTEBlock} currentBlock - Returns the first node within that block.
|
|
421
|
-
* @returns {Nullable<RTENode>} Returns the first node of the given `currentBlock` object.
|
|
422
|
-
*/
|
|
423
|
-
getBlockFirstNode(currentBlock) {
|
|
424
|
-
if (currentBlock.type === 'number-list' || currentBlock.type === 'bullet-list') {
|
|
425
|
-
if (currentBlock.blocks) {
|
|
426
|
-
const firstListItem = currentBlock.blocks[0];
|
|
427
|
-
return this.getBlockFirstNode(firstListItem);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
else {
|
|
431
|
-
if (currentBlock['nodes']) {
|
|
432
|
-
return currentBlock['nodes'][0];
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* TODO: The getPreviousBlock add nest list support
|
|
438
|
-
* This function retrieves the previous block in a rich text editor, considering different scenarios such as being in a bullet list.
|
|
439
|
-
*
|
|
440
|
-
* @param {RTEBlock} currentBlock - Used to retrieve the previous block relative to the given `currentBlock` within a rich text editor context.
|
|
441
|
-
* @returns {Nullable<RTEBlock>} The previous block if existing
|
|
442
|
-
*/
|
|
443
|
-
getPreviousBlock(currentBlock) {
|
|
444
|
-
if (currentBlock && currentBlock.parent && currentBlock.parent.blocks) {
|
|
445
|
-
const currentBlockIndex = currentBlock.parent.blocks.indexOf(currentBlock);
|
|
446
|
-
if (currentBlockIndex > 0) {
|
|
447
|
-
return currentBlock.parent.blocks[currentBlockIndex - 1];
|
|
448
|
-
}
|
|
449
|
-
else if ((currentBlock.parent['type'] === 'number-list' ||
|
|
450
|
-
currentBlock.parent['type'] === 'bullet-list') &&
|
|
451
|
-
currentBlockIndex === 0) {
|
|
452
|
-
return this.getPreviousBlock(currentBlock.parent);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
/**
|
|
457
|
-
* This function retrieves the next block in a rich text editor, considering different scenarios such as being in a bullet list.
|
|
458
|
-
*
|
|
459
|
-
* @param {RTEBlock} currentBlock - Used to retrieve the next block relative to the given `currentBlock` within a rich text editor context.
|
|
460
|
-
* @returns {Nullable<RTEBlock>} The next block if existing
|
|
461
|
-
*/
|
|
462
|
-
getNextBlock(currentBlock) {
|
|
463
|
-
if (currentBlock && currentBlock.parent && currentBlock.parent.blocks) {
|
|
464
|
-
const currentBlockIndex = currentBlock.parent.blocks.indexOf(currentBlock);
|
|
465
|
-
if (currentBlock.parent.blocks[currentBlockIndex + 1]) {
|
|
466
|
-
return currentBlock.parent.blocks[currentBlockIndex + 1];
|
|
467
|
-
}
|
|
468
|
-
else if (currentBlock.type === 'list-item' &&
|
|
469
|
-
currentBlock.parent.blocks.length === currentBlockIndex + 1) {
|
|
470
|
-
return this.getNextBlock(currentBlock.parent);
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Replaces a specific node with an array of nodes within a RTENode array.
|
|
476
|
-
*
|
|
477
|
-
* @param {RTENode} referNode - Used as a reference node to identify the node that needs to be replaced in the `nodes` array.
|
|
478
|
-
* @param {RTENode[]} nodes - An array of RTENode objects that you want to replace the `referNode` with in the `nodes` array.
|
|
479
|
-
*/
|
|
480
|
-
replaceNodeWithNodes(referNode, nodes) {
|
|
481
|
-
if (this['nodes']) {
|
|
482
|
-
nodes.forEach((node) => {
|
|
483
|
-
node.parentBlock = this;
|
|
484
|
-
});
|
|
485
|
-
this['nodes'] = this['nodes'].flatMap((node) => {
|
|
486
|
-
if (node === referNode) {
|
|
487
|
-
return nodes;
|
|
488
|
-
}
|
|
489
|
-
else {
|
|
490
|
-
return node;
|
|
491
|
-
}
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
/**
|
|
498
|
-
* Annotation for image
|
|
499
|
-
*/
|
|
500
|
-
class ImageAnnotation extends NodeAnnotation {
|
|
501
|
-
constructor(size = 'md', alt) {
|
|
502
|
-
super();
|
|
503
|
-
this.type = NodeAnnotationTypeEnum.IMAGE;
|
|
504
|
-
this.size = size;
|
|
505
|
-
this.alt = alt;
|
|
506
|
-
}
|
|
507
|
-
/**
|
|
508
|
-
* Generate the map item for the annotation
|
|
509
|
-
*
|
|
510
|
-
* @param {string} size - Image size
|
|
511
|
-
* @param {string} alt - Image alt
|
|
512
|
-
* @returns {[NodeAnnotationTypeEnum.IMAGE, ImageAnnotation]} Map item for the annotation
|
|
513
|
-
*/
|
|
514
|
-
static from(size, alt) {
|
|
515
|
-
return [NodeAnnotationTypeEnum.IMAGE, new ImageAnnotation(size, alt)];
|
|
516
|
-
}
|
|
517
|
-
/**
|
|
518
|
-
* Generate the JSON representation of the annotation
|
|
519
|
-
*
|
|
520
|
-
* @returns {Nullable<Record<string, unknown>>} JSON representation of the annotation
|
|
521
|
-
*/
|
|
522
|
-
toJSON() {
|
|
523
|
-
return isNonNullable(this.alt)
|
|
524
|
-
? {
|
|
525
|
-
size: this.size,
|
|
526
|
-
alt: this.alt,
|
|
527
|
-
}
|
|
528
|
-
: {
|
|
529
|
-
size: this.size,
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
/**
|
|
533
|
-
* Generate the style for the image
|
|
534
|
-
*
|
|
535
|
-
* @returns {Nullable<AnnotationStyle>} image style
|
|
536
|
-
*/
|
|
537
|
-
render() {
|
|
538
|
-
switch (this.size) {
|
|
539
|
-
case 'sm': {
|
|
540
|
-
return { width: '25%' };
|
|
541
|
-
}
|
|
542
|
-
case 'md': {
|
|
543
|
-
return { width: '50%' };
|
|
544
|
-
}
|
|
545
|
-
case 'lg': {
|
|
546
|
-
return { width: '100%' };
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
/**
|
|
553
|
-
* Image node
|
|
554
|
-
*/
|
|
555
|
-
class RTEImageNode extends RTENode {
|
|
556
|
-
constructor(id, url, parentBlock, annotationMap) {
|
|
557
|
-
super(id, annotationMap);
|
|
558
|
-
this.type = NodeTypeEnum.IMAGE;
|
|
559
|
-
this.url = url;
|
|
560
|
-
this.parentBlock = parentBlock;
|
|
561
|
-
}
|
|
562
|
-
/**
|
|
563
|
-
* Converts a VegaRTEImageNode into an RTEImageNode by mapping nodes and creating annotations.
|
|
564
|
-
*
|
|
565
|
-
* @param {VegaRTEImageNode} node - The node to be converted.
|
|
566
|
-
* @param {RTEImageBlock} parentBlock - The parent block
|
|
567
|
-
* @returns {RTEImageBlock} An instance of `RTEImageBlock`
|
|
568
|
-
*/
|
|
569
|
-
static from(node, parentBlock) {
|
|
570
|
-
const imageNode = new RTEImageNode(node.id, node.url, parentBlock);
|
|
571
|
-
let annotations;
|
|
572
|
-
if (!node.annotations || Object.keys(node.annotations).length === 0) {
|
|
573
|
-
annotations = { size: 'md' };
|
|
574
|
-
}
|
|
575
|
-
else {
|
|
576
|
-
annotations = node.annotations;
|
|
577
|
-
}
|
|
578
|
-
imageNode.annotationMap = new Map(Object.keys(annotations)
|
|
579
|
-
.map(() => ImageAnnotation.from(annotations.size, annotations.alt))
|
|
580
|
-
.filter(isNonNullable));
|
|
581
|
-
return imageNode;
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* @inheritDoc
|
|
585
|
-
*/
|
|
586
|
-
toJSON() {
|
|
587
|
-
const imageAnnotation = this.annotationMap.get(NodeAnnotationTypeEnum.IMAGE);
|
|
588
|
-
const annotations = {};
|
|
589
|
-
if (imageAnnotation === null || imageAnnotation === void 0 ? void 0 : imageAnnotation.size) {
|
|
590
|
-
annotations.size = imageAnnotation.size;
|
|
591
|
-
}
|
|
592
|
-
if (imageAnnotation === null || imageAnnotation === void 0 ? void 0 : imageAnnotation.alt) {
|
|
593
|
-
annotations.alt = imageAnnotation.alt;
|
|
594
|
-
}
|
|
595
|
-
return Object.assign(Object.assign({ id: this.id }, (Object.keys(annotations).length > 0 ? { annotations } : {})), { type: 'image', url: this.url });
|
|
596
|
-
}
|
|
597
|
-
/**
|
|
598
|
-
* @inheritDoc
|
|
599
|
-
*/
|
|
600
|
-
doAnnotationActionApply(action) {
|
|
601
|
-
const annotation = action.toAnnotation();
|
|
602
|
-
this.annotationMap.set(annotation.type, annotation);
|
|
603
|
-
}
|
|
604
|
-
// placeholder method
|
|
605
|
-
/* istanbul ignore next */
|
|
606
|
-
/**
|
|
607
|
-
* @inheritDoc
|
|
608
|
-
*/
|
|
609
|
-
doModifyActionApply(action) {
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
/**
|
|
614
|
-
* Clear the current block nodes and append new nodes
|
|
615
|
-
*
|
|
616
|
-
* @example block.apply(new ReplaceChildNodesAction(newNodes))
|
|
617
|
-
*/
|
|
618
|
-
class ReplaceChildNodesAction extends ModifyContentAction {
|
|
619
|
-
constructor(newChildNodes) {
|
|
620
|
-
super();
|
|
621
|
-
this.type = ModifyContentActionType.REPLACE_CHILD_NODES;
|
|
622
|
-
this.newChildNodes = newChildNodes;
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
/**
|
|
627
|
-
* Insert a new block after a existing block
|
|
628
|
-
*
|
|
629
|
-
* @example currentBlock.parent.apply(new InsertBlocksAfterAction(currentBlock, newBlock, ...))
|
|
630
|
-
*/
|
|
631
|
-
class InsertBlocksAfterAction extends ModifyContentAction {
|
|
632
|
-
constructor(referBlock, ...blocksToBeInserted) {
|
|
633
|
-
super();
|
|
634
|
-
this.type = ModifyContentActionType.INSERT_BLOCKS_AFTER;
|
|
635
|
-
this.referBlock = referBlock;
|
|
636
|
-
this.blocksToBeInserted = blocksToBeInserted;
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
/**
|
|
641
|
-
* Split the block with a split point node.
|
|
642
|
-
* The property `newBlock` use to store the new create block if need.
|
|
643
|
-
*
|
|
644
|
-
* @example block.apply(new SplitBlockWithNodeAction(node, offset))
|
|
645
|
-
*/
|
|
646
|
-
class SplitBlockWithNodeAction extends ModifyContentAction {
|
|
647
|
-
constructor(splitPointNode, startOffsetOfNode) {
|
|
648
|
-
super();
|
|
649
|
-
this.type = ModifyContentActionType.SPLIT_BLOCK_WITH_NODE;
|
|
650
|
-
this.splitPointNode = splitPointNode;
|
|
651
|
-
this.startOffsetOfNode = startOffsetOfNode;
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
/**
|
|
656
|
-
* Abstract class for annotation actions
|
|
657
|
-
*/
|
|
658
|
-
class AnnotationAction {
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
/**
|
|
662
|
-
* Abstract class for which can be splittable
|
|
663
|
-
*/
|
|
664
|
-
class TextSplittableAction extends AnnotationAction {
|
|
665
|
-
constructor() {
|
|
666
|
-
super(...arguments);
|
|
667
|
-
/**
|
|
668
|
-
* Whether the action should split the node
|
|
669
|
-
*/
|
|
670
|
-
this.doSplit = true;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
/**
|
|
675
|
-
* Annotation to represent a selection range
|
|
676
|
-
*/
|
|
677
|
-
class SelectionRangeAnnotation extends Annotation {
|
|
678
|
-
constructor(range) {
|
|
679
|
-
super();
|
|
680
|
-
this.type = InternalAnnotationTypeEnum.SELECTION_RANGE;
|
|
681
|
-
this.range = range;
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
/**
|
|
686
|
-
* Annotation to make text with strikethrough
|
|
687
|
-
*/
|
|
688
|
-
class StrikethroughAnnotation extends NodeAnnotation {
|
|
689
|
-
constructor(underline) {
|
|
690
|
-
super();
|
|
691
|
-
this.type = NodeAnnotationTypeEnum.STRIKETHROUGH;
|
|
692
|
-
this.strikethrough = underline;
|
|
693
|
-
}
|
|
694
|
-
/**
|
|
695
|
-
* Generate the map item for the annotation
|
|
696
|
-
*
|
|
697
|
-
* @param {Nullable<boolean>} strikethrough - Strikethrough annotation
|
|
698
|
-
* @returns {[NodeAnnotationTypeEnum.STRIKETHROUGH, StrikethroughAnnotation]} Map item for the annotation
|
|
699
|
-
*/
|
|
700
|
-
static from(strikethrough) {
|
|
701
|
-
return [NodeAnnotationTypeEnum.STRIKETHROUGH, new StrikethroughAnnotation(strikethrough)];
|
|
702
|
-
}
|
|
703
|
-
/**
|
|
704
|
-
* Generate the JSON representation of the annotation
|
|
705
|
-
*
|
|
706
|
-
* @returns {Record<string, unknown>} JSON representation of the annotation
|
|
707
|
-
*/
|
|
708
|
-
toJSON() {
|
|
709
|
-
return {
|
|
710
|
-
strikethrough: this.strikethrough,
|
|
711
|
-
};
|
|
712
|
-
}
|
|
713
|
-
/**
|
|
714
|
-
* Generate the class for the annotation
|
|
715
|
-
*
|
|
716
|
-
* @returns {Nullable<string>} - Annotation class
|
|
717
|
-
*/
|
|
718
|
-
renderClass() {
|
|
719
|
-
return this.strikethrough ? 'v-rte--strikethrough' : null;
|
|
720
|
-
}
|
|
721
|
-
/**
|
|
722
|
-
* Generate the style for the annotation
|
|
723
|
-
*
|
|
724
|
-
* @returns {Nullable<AnnotationStyle>} - Annotation style
|
|
725
|
-
*/
|
|
726
|
-
render() {
|
|
727
|
-
return null;
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
/**
|
|
732
|
-
* Annotation to make text with underline
|
|
733
|
-
*/
|
|
734
|
-
class UnderlineAnnotation extends NodeAnnotation {
|
|
735
|
-
constructor(underline) {
|
|
736
|
-
super();
|
|
737
|
-
this.type = NodeAnnotationTypeEnum.UNDERLINE;
|
|
738
|
-
this.underline = underline;
|
|
739
|
-
}
|
|
740
|
-
/**
|
|
741
|
-
* Generate the map item for the annotation
|
|
742
|
-
*
|
|
743
|
-
* @param {boolean} underline - Underline annotation
|
|
744
|
-
* @returns {[NodeAnnotationTypeEnum.UNDERLINE, UnderlineAnnotation]} Map item for the annotation
|
|
745
|
-
*/
|
|
746
|
-
static from(underline) {
|
|
747
|
-
return [NodeAnnotationTypeEnum.UNDERLINE, new UnderlineAnnotation(underline)];
|
|
748
|
-
}
|
|
749
|
-
/**
|
|
750
|
-
* Generate the JSON representation of the annotation
|
|
751
|
-
*
|
|
752
|
-
* @returns {Record<string, unknown>} JSON representation of the annotation
|
|
753
|
-
*/
|
|
754
|
-
toJSON() {
|
|
755
|
-
return {
|
|
756
|
-
underline: this.underline,
|
|
757
|
-
};
|
|
758
|
-
}
|
|
759
|
-
/**
|
|
760
|
-
* Generate the class for the annotation
|
|
761
|
-
*
|
|
762
|
-
* @returns {Nullable<string>} - Annotation class
|
|
763
|
-
*/
|
|
764
|
-
renderClass() {
|
|
765
|
-
return this.underline ? 'v-rte--underline' : null;
|
|
766
|
-
}
|
|
767
|
-
/**
|
|
768
|
-
* Generate the style for the annotation
|
|
769
|
-
*
|
|
770
|
-
* @returns {Nullable<AnnotationStyle>} - Annotation style
|
|
771
|
-
*/
|
|
772
|
-
render() {
|
|
773
|
-
return null;
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
/**
|
|
778
|
-
* Annotation to make text Italic
|
|
779
|
-
*/
|
|
780
|
-
class ItalicAnnotation extends NodeAnnotation {
|
|
781
|
-
constructor(italic) {
|
|
782
|
-
super();
|
|
783
|
-
this.type = NodeAnnotationTypeEnum.ITALIC;
|
|
784
|
-
this.italic = italic;
|
|
785
|
-
}
|
|
786
|
-
/**
|
|
787
|
-
* Generate the map item for the annotation
|
|
788
|
-
*
|
|
789
|
-
* @param {boolean} italic - Italic annotation
|
|
790
|
-
* @returns {Nullable<[NodeAnnotationTypeEnum.ITALIC, ItalicAnnotation]>} Map item for the annotation
|
|
791
|
-
*/
|
|
792
|
-
static from(italic) {
|
|
793
|
-
return [NodeAnnotationTypeEnum.ITALIC, new ItalicAnnotation(italic)];
|
|
794
|
-
}
|
|
795
|
-
/**
|
|
796
|
-
* Generate the JSON representation of the annotation
|
|
797
|
-
*
|
|
798
|
-
* @returns {Record<string, unknown>} JSON representation of the annotation
|
|
799
|
-
*/
|
|
800
|
-
toJSON() {
|
|
801
|
-
return {
|
|
802
|
-
italic: this.italic,
|
|
803
|
-
};
|
|
804
|
-
}
|
|
805
|
-
/**
|
|
806
|
-
* Generate the style for the annotation
|
|
807
|
-
*
|
|
808
|
-
* @returns {Nullable<AnnotationStyle>} Italic style
|
|
809
|
-
*/
|
|
810
|
-
render() {
|
|
811
|
-
return this.italic ? { 'font-style': 'italic' } : null;
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
/**
|
|
816
|
-
* Annotation to make text bold
|
|
817
|
-
*/
|
|
818
|
-
class BoldAnnotation extends NodeAnnotation {
|
|
819
|
-
constructor(bold) {
|
|
820
|
-
super();
|
|
821
|
-
this.type = NodeAnnotationTypeEnum.BOLD;
|
|
822
|
-
this.bold = bold;
|
|
823
|
-
}
|
|
824
|
-
/**
|
|
825
|
-
* Generate the map item for the annotation
|
|
826
|
-
*
|
|
827
|
-
* @param {boolean} bold - Bold annotation
|
|
828
|
-
* @returns {[NodeAnnotationTypeEnum.BOLD, BoldAnnotation]} Map item for the annotation
|
|
829
|
-
*/
|
|
830
|
-
static from(bold) {
|
|
831
|
-
return [NodeAnnotationTypeEnum.BOLD, new BoldAnnotation(bold)];
|
|
832
|
-
}
|
|
833
|
-
/**
|
|
834
|
-
* Generate the JSON representation of the annotation
|
|
835
|
-
*
|
|
836
|
-
* @returns {Record<string, unknown>} JSON representation of the annotation
|
|
837
|
-
*/
|
|
838
|
-
toJSON() {
|
|
839
|
-
return {
|
|
840
|
-
bold: this.bold,
|
|
841
|
-
};
|
|
842
|
-
}
|
|
843
|
-
/**
|
|
844
|
-
* Generate the style for the annotation
|
|
845
|
-
*
|
|
846
|
-
* @returns {Nullable<AnnotationStyle>} Bold style
|
|
847
|
-
*/
|
|
848
|
-
render() {
|
|
849
|
-
return this.bold ? { 'font-weight': '700' } : null;
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
/**
|
|
854
|
-
* Annotation to host which annotations will be clear formatting
|
|
855
|
-
*/
|
|
856
|
-
class ClearFormattingAnnotation extends Annotation {
|
|
857
|
-
constructor() {
|
|
858
|
-
super(...arguments);
|
|
859
|
-
this.type = InternalAnnotationTypeEnum.CLEAR_FORMATTING;
|
|
860
|
-
this.items = [
|
|
861
|
-
NodeAnnotationTypeEnum.BOLD,
|
|
862
|
-
NodeAnnotationTypeEnum.ITALIC,
|
|
863
|
-
NodeAnnotationTypeEnum.UNDERLINE,
|
|
864
|
-
NodeAnnotationTypeEnum.STRIKETHROUGH,
|
|
865
|
-
NodeAnnotationTypeEnum.TEXT_COLOR,
|
|
866
|
-
NodeAnnotationTypeEnum.CODE,
|
|
867
|
-
];
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
/**
|
|
872
|
-
* Annotation to make text code
|
|
873
|
-
*/
|
|
874
|
-
class CodeAnnotation extends NodeAnnotation {
|
|
875
|
-
constructor(code) {
|
|
876
|
-
super();
|
|
877
|
-
this.type = NodeAnnotationTypeEnum.CODE;
|
|
878
|
-
this.code = code;
|
|
879
|
-
}
|
|
880
|
-
/**
|
|
881
|
-
* Generate the map item for the annotation
|
|
882
|
-
*
|
|
883
|
-
* @param {boolean} code - Bold annotation
|
|
884
|
-
* @returns {[NodeAnnotationTypeEnum.CODE, CodeAnnotation]} Map item for the annotation
|
|
885
|
-
*/
|
|
886
|
-
static from(code) {
|
|
887
|
-
return [NodeAnnotationTypeEnum.CODE, new CodeAnnotation(code)];
|
|
888
|
-
}
|
|
889
|
-
/**
|
|
890
|
-
* Generate the JSON representation of the annotation
|
|
891
|
-
*
|
|
892
|
-
* @returns {Record<string, unknown>} JSON representation of the annotation
|
|
893
|
-
*/
|
|
894
|
-
toJSON() {
|
|
895
|
-
return {
|
|
896
|
-
code: this.code,
|
|
897
|
-
};
|
|
898
|
-
}
|
|
899
|
-
/**
|
|
900
|
-
* Generate the class for the annotation
|
|
901
|
-
*
|
|
902
|
-
* @returns {Nullable<string>} - Annotation class
|
|
903
|
-
*/
|
|
904
|
-
renderClass() {
|
|
905
|
-
return this.code ? 'v-rte--code' : null;
|
|
906
|
-
}
|
|
907
|
-
/**
|
|
908
|
-
* Generate the style for the annotation
|
|
909
|
-
*
|
|
910
|
-
* @returns {Nullable<AnnotationStyle>} Bold style
|
|
911
|
-
*/
|
|
912
|
-
render() {
|
|
913
|
-
return null;
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
/**
|
|
918
|
-
* Annotation to make text with text color
|
|
919
|
-
*/
|
|
920
|
-
class TextColorAnnotation extends NodeAnnotation {
|
|
921
|
-
constructor(textColor) {
|
|
922
|
-
super();
|
|
923
|
-
this.type = NodeAnnotationTypeEnum.TEXT_COLOR;
|
|
924
|
-
this.textColor = this.formatTextColor(textColor);
|
|
925
|
-
}
|
|
926
|
-
/**
|
|
927
|
-
* Generate the map item for the annotation
|
|
928
|
-
*
|
|
929
|
-
* @param {string} textColor - text color annotation
|
|
930
|
-
* @returns {[NodeAnnotationTypeEnum.TEXT_COLOR, TextColorAnnotation]} Map item for the annotation
|
|
931
|
-
*/
|
|
932
|
-
static from(textColor) {
|
|
933
|
-
return [NodeAnnotationTypeEnum.TEXT_COLOR, new TextColorAnnotation(textColor)];
|
|
934
|
-
}
|
|
935
|
-
/**
|
|
936
|
-
* Generate the JSON representation of the annotation
|
|
937
|
-
*
|
|
938
|
-
* @returns {Record<string, unknown>} JSON representation of the annotation
|
|
939
|
-
*/
|
|
940
|
-
toJSON() {
|
|
941
|
-
return {
|
|
942
|
-
textColor: this.textColor.key,
|
|
943
|
-
};
|
|
944
|
-
}
|
|
945
|
-
/**
|
|
946
|
-
* Generate the class for the annotation
|
|
947
|
-
*
|
|
948
|
-
* @returns {Nullable<string>} - Annotation class
|
|
949
|
-
*/
|
|
950
|
-
renderClass() {
|
|
951
|
-
return null;
|
|
952
|
-
}
|
|
953
|
-
/**
|
|
954
|
-
* Generate the style for the annotation
|
|
955
|
-
*
|
|
956
|
-
* @returns {Nullable<AnnotationStyle>} - Annotation style
|
|
957
|
-
*/
|
|
958
|
-
render() {
|
|
959
|
-
return {
|
|
960
|
-
color: VegaThemeManager.isDarkMode() ? this.textColor.dark : this.textColor.light,
|
|
961
|
-
};
|
|
962
|
-
}
|
|
963
|
-
/**
|
|
964
|
-
* format text color
|
|
965
|
-
*
|
|
966
|
-
* @param {string} textColor - text color
|
|
967
|
-
* @returns {VegaRTEColorSchema} - VegaRTEColorSchema
|
|
968
|
-
*/
|
|
969
|
-
formatTextColor(textColor) {
|
|
970
|
-
return (RTE_TEXT_COLORS.find((item) => item.key === textColor) || RTE_TEXT_COLORS[0]);
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
/**
|
|
975
|
-
* Annotation to make text a link
|
|
976
|
-
*/
|
|
977
|
-
class LinkAnnotation extends NodeAnnotation {
|
|
978
|
-
constructor(link) {
|
|
979
|
-
super();
|
|
980
|
-
this.type = NodeAnnotationTypeEnum.LINK;
|
|
981
|
-
this.link = link;
|
|
982
|
-
}
|
|
983
|
-
/**
|
|
984
|
-
* Generate the map item for the annotation
|
|
985
|
-
*
|
|
986
|
-
* @param {VegaRTELink} link - Bold annotation
|
|
987
|
-
* @returns {[NodeAnnotationTypeEnum.LINK, LinkAnnotation]} Map item for the annotation
|
|
988
|
-
*/
|
|
989
|
-
static from(link) {
|
|
990
|
-
return [
|
|
991
|
-
NodeAnnotationTypeEnum.LINK,
|
|
992
|
-
new LinkAnnotation({ href: link.href, groupKey: link.groupKey }),
|
|
993
|
-
];
|
|
994
|
-
}
|
|
995
|
-
/**
|
|
996
|
-
* Generate the JSON representation of the annotation
|
|
997
|
-
*
|
|
998
|
-
* @returns {Record<string, unknown>} JSON representation of the annotation
|
|
999
|
-
*/
|
|
1000
|
-
toJSON() {
|
|
1001
|
-
return { link: { href: this.link.href, groupKey: this.link.groupKey } };
|
|
1002
|
-
}
|
|
1003
|
-
/**
|
|
1004
|
-
* Verify whether two link annotation is same or not
|
|
1005
|
-
*
|
|
1006
|
-
* @param {LinkAnnotation} annotation - Compared annotation
|
|
1007
|
-
* @returns {boolean} Whether two link annotation is same or not
|
|
1008
|
-
*/
|
|
1009
|
-
toEqual(annotation) {
|
|
1010
|
-
return this.link.groupKey === annotation.link.groupKey;
|
|
1011
|
-
}
|
|
1012
|
-
/**
|
|
1013
|
-
* Generate the style for the annotation
|
|
1014
|
-
*
|
|
1015
|
-
* @returns {Nullable<AnnotationStyle>} Link style
|
|
1016
|
-
*/
|
|
1017
|
-
render() {
|
|
1018
|
-
return null;
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
/**
|
|
1023
|
-
* Action to toggle link annotation
|
|
1024
|
-
*/
|
|
1025
|
-
class LinkAnnotationAction extends TextSplittableAction {
|
|
1026
|
-
constructor({ link, newText, needMergeNode, doSplit, }) {
|
|
1027
|
-
super();
|
|
1028
|
-
this.isFlushable = true;
|
|
1029
|
-
this.link = link;
|
|
1030
|
-
this.needMergeNode = needMergeNode;
|
|
1031
|
-
this.newText = newText;
|
|
1032
|
-
if (isNonNullable(doSplit)) {
|
|
1033
|
-
this.doSplit = doSplit;
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
/**
|
|
1037
|
-
* Converts the action to an annotation
|
|
1038
|
-
*
|
|
1039
|
-
* @returns {LinkAnnotation} the annotation
|
|
1040
|
-
*/
|
|
1041
|
-
toAnnotation() {
|
|
1042
|
-
return new LinkAnnotation(this.link);
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
/**
|
|
1047
|
-
* Action to toggle code annotation
|
|
1048
|
-
*/
|
|
1049
|
-
class CodeAnnotationAction extends TextSplittableAction {
|
|
1050
|
-
constructor(code) {
|
|
1051
|
-
super();
|
|
1052
|
-
this.isFlushable = true;
|
|
1053
|
-
this.code = code;
|
|
1054
|
-
}
|
|
1055
|
-
/**
|
|
1056
|
-
* Converts the action to an annotation
|
|
1057
|
-
*
|
|
1058
|
-
* @returns {CodeAnnotation} the annotation
|
|
1059
|
-
*/
|
|
1060
|
-
toAnnotation() {
|
|
1061
|
-
return new CodeAnnotation(this.code);
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
/**
|
|
1066
|
-
* Action to toggle clear formatting
|
|
1067
|
-
*/
|
|
1068
|
-
class ClearFormattingAnnotationAction extends TextSplittableAction {
|
|
1069
|
-
constructor() {
|
|
1070
|
-
super(...arguments);
|
|
1071
|
-
this.isFlushable = true;
|
|
1072
|
-
}
|
|
1073
|
-
/**
|
|
1074
|
-
* Converts the action to an annotation
|
|
1075
|
-
*
|
|
1076
|
-
* @returns {ClearFormattingAnnotation} the annotation
|
|
1077
|
-
*/
|
|
1078
|
-
toAnnotation() {
|
|
1079
|
-
return new ClearFormattingAnnotation();
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
/**
|
|
1084
|
-
* Update the text node property text action
|
|
1085
|
-
*
|
|
1086
|
-
* @example textNode.apply(new UpdateTextAction(newText))
|
|
1087
|
-
*/
|
|
1088
|
-
class UpdateTextAction extends ModifyContentAction {
|
|
1089
|
-
constructor(text) {
|
|
1090
|
-
super();
|
|
1091
|
-
this.type = ModifyContentActionType.UPDATE_TEXT;
|
|
1092
|
-
this.newTextContent = '';
|
|
1093
|
-
this.newTextContent = text;
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
/**
|
|
1098
|
-
* Annotation to represent a link of grouped nodes
|
|
1099
|
-
*/
|
|
1100
|
-
class LinkGroupAnnotation extends Annotation {
|
|
1101
|
-
constructor(groupKey) {
|
|
1102
|
-
super();
|
|
1103
|
-
this.type = InternalAnnotationTypeEnum.LINK_GROUP;
|
|
1104
|
-
this.linkGroups = new Map();
|
|
1105
|
-
this.linkGroups = new Map([[groupKey, []]]);
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
|
-
/**
|
|
1110
|
-
* Action to link a group of nodes
|
|
1111
|
-
*/
|
|
1112
|
-
class LinkGroupAnnotationAction extends AnnotationAction {
|
|
1113
|
-
constructor(groupKey, nodes) {
|
|
1114
|
-
super();
|
|
1115
|
-
this.isFlushable = false;
|
|
1116
|
-
this.groupKey = groupKey;
|
|
1117
|
-
this.nodes = nodes;
|
|
1118
|
-
}
|
|
1119
|
-
/**
|
|
1120
|
-
* Converts the action to an annotation
|
|
1121
|
-
*
|
|
1122
|
-
* @returns {LinkGroupAnnotation} The annotation
|
|
1123
|
-
*/
|
|
1124
|
-
toAnnotation() {
|
|
1125
|
-
return new LinkGroupAnnotation(this.groupKey);
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
/**
|
|
1130
|
-
* Sync up selection action
|
|
1131
|
-
*/
|
|
1132
|
-
class SyncUpSelectionAction extends AnnotationAction {
|
|
1133
|
-
constructor() {
|
|
1134
|
-
super();
|
|
1135
|
-
this.isFlushable = false;
|
|
1136
|
-
}
|
|
1137
|
-
/**
|
|
1138
|
-
* annotation null
|
|
1139
|
-
*
|
|
1140
|
-
* @returns {Nullable<Annotation>} null
|
|
1141
|
-
*/
|
|
1142
|
-
toAnnotation() {
|
|
1143
|
-
return null;
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
/**
|
|
1148
|
-
* Delete the node annotation by type
|
|
1149
|
-
*/
|
|
1150
|
-
class DeleteNodeAnnotationAction extends AnnotationAction {
|
|
1151
|
-
constructor(annotationType) {
|
|
1152
|
-
super();
|
|
1153
|
-
this.isFlushable = true;
|
|
1154
|
-
this.annotationType = annotationType;
|
|
1155
|
-
}
|
|
1156
|
-
/**
|
|
1157
|
-
* Don't need this for this action
|
|
1158
|
-
*
|
|
1159
|
-
* @returns {Nullable<Annotation>} undefined
|
|
1160
|
-
*/
|
|
1161
|
-
toAnnotation() {
|
|
1162
|
-
return undefined;
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
/**
|
|
1167
|
-
* Text node
|
|
1168
|
-
*/
|
|
1169
|
-
class RTETextNode extends RTENode {
|
|
1170
|
-
constructor(id, text, parentBlock, annotationMap) {
|
|
1171
|
-
super(id, annotationMap);
|
|
1172
|
-
this.type = NodeTypeEnum.TEXT;
|
|
1173
|
-
this.parentBlock = parentBlock;
|
|
1174
|
-
this.text = text;
|
|
1175
|
-
}
|
|
1176
|
-
/**
|
|
1177
|
-
* Creates an RTETextNode from a VegaRTETextNode with annotations and a parent RTETextBlock.
|
|
1178
|
-
*
|
|
1179
|
-
* @param {VegaRTETextNode} richText - A rich text node
|
|
1180
|
-
* @param {RTETextBlock} parentBlock - Parent block
|
|
1181
|
-
* @returns {RTETextNode} an RTETextNode
|
|
1182
|
-
*/
|
|
1183
|
-
static from(richText, parentBlock) {
|
|
1184
|
-
const textNode = new RTETextNode(richText.id, richText.text, parentBlock);
|
|
1185
|
-
const { annotations } = richText;
|
|
1186
|
-
if (annotations) {
|
|
1187
|
-
textNode.annotationMap = new Map(Object.keys(annotations)
|
|
1188
|
-
.map((type) => {
|
|
1189
|
-
if (annotations.link) {
|
|
1190
|
-
parentBlock.apply(new LinkGroupAnnotationAction(annotations.link.groupKey, [textNode]));
|
|
1191
|
-
}
|
|
1192
|
-
return this.createAnnotationEntity(type, annotations[type]);
|
|
1193
|
-
})
|
|
1194
|
-
.filter(isNonNullable));
|
|
1195
|
-
}
|
|
1196
|
-
return textNode;
|
|
1197
|
-
}
|
|
1198
|
-
/**
|
|
1199
|
-
* Creates different types of text annotations based on the provided type and value.
|
|
1200
|
-
*
|
|
1201
|
-
* @param {keyof VegaRTETextAnnotations} type - The key of the type.
|
|
1202
|
-
* @param {unknown} value - The value that will be used to create the specific type of annotation entity based on the `type` provided.
|
|
1203
|
-
* @returns {Nullable<[RTENodeAnnotationMapKey, RTENodeAnnotationMapValue]>} Returning a nullable tuple containing a key and a
|
|
1204
|
-
* value from the `RTENodeAnnotationMapKey` and `RTENodeAnnotationMapValue` types.
|
|
1205
|
-
*/
|
|
1206
|
-
static createAnnotationEntity(type, value) {
|
|
1207
|
-
switch (type) {
|
|
1208
|
-
case 'bold':
|
|
1209
|
-
return BoldAnnotation.from(value);
|
|
1210
|
-
case 'italic':
|
|
1211
|
-
return ItalicAnnotation.from(value);
|
|
1212
|
-
case 'underline':
|
|
1213
|
-
return UnderlineAnnotation.from(value);
|
|
1214
|
-
case 'strikethrough':
|
|
1215
|
-
return StrikethroughAnnotation.from(value);
|
|
1216
|
-
case 'code':
|
|
1217
|
-
return CodeAnnotation.from(value);
|
|
1218
|
-
case 'textColor':
|
|
1219
|
-
return TextColorAnnotation.from(value);
|
|
1220
|
-
case 'link':
|
|
1221
|
-
return LinkAnnotation.from(value);
|
|
1222
|
-
}
|
|
1223
|
-
}
|
|
1224
|
-
/**
|
|
1225
|
-
* @inheritDoc
|
|
1226
|
-
*/
|
|
1227
|
-
toJSON() {
|
|
1228
|
-
const annotations = Array.from(this.annotationMap.values())
|
|
1229
|
-
.filter((annotation) => annotation instanceof NodeAnnotation)
|
|
1230
|
-
.reduce((record, annotation) => {
|
|
1231
|
-
return Object.assign(Object.assign({}, record), annotation.toJSON());
|
|
1232
|
-
}, {});
|
|
1233
|
-
return Object.assign(Object.assign({ id: this.id }, (Object.keys(annotations).length > 0 ? { annotations } : {})), { type: 'text', text: this.text });
|
|
1234
|
-
}
|
|
1235
|
-
/**
|
|
1236
|
-
* Creates a new RTETextNode with the specified text and copies the parent block and annotation map from the original node.
|
|
1237
|
-
*
|
|
1238
|
-
* @param {string} text - The text content of the RTETextNode that will be created.
|
|
1239
|
-
* @returns {RTETextNode} An new RTETextNode
|
|
1240
|
-
*/
|
|
1241
|
-
cloneWithText(text) {
|
|
1242
|
-
return new RTETextNode(generateUUID(), text, this.parentBlock, new Map(this.annotationMap));
|
|
1243
|
-
}
|
|
1244
|
-
/**
|
|
1245
|
-
* Checks if a node is empty
|
|
1246
|
-
*
|
|
1247
|
-
* @returns {boolean} It returns `true` if the node is empty
|
|
1248
|
-
*/
|
|
1249
|
-
isEmpty() {
|
|
1250
|
-
return !this.text || this.text === ZERO_WIDTH_SPACE || this.text === '\n';
|
|
1251
|
-
}
|
|
1252
|
-
/**
|
|
1253
|
-
* @inheritDoc
|
|
1254
|
-
*/
|
|
1255
|
-
doAnnotationActionApply(action) {
|
|
1256
|
-
const selectionRangeAnnotation = this.getAnnotationByType(InternalAnnotationTypeEnum.SELECTION_RANGE);
|
|
1257
|
-
if (action instanceof TextSplittableAction && action.doSplit && selectionRangeAnnotation) {
|
|
1258
|
-
const { startContainer, endContainer, startOffset, endOffset } = selectionRangeAnnotation.range;
|
|
1259
|
-
const noTextRangeSelected = startContainer === endContainer && startOffset === endOffset;
|
|
1260
|
-
this.parentBlock.nodes = this.parentBlock.nodes.flatMap((item) => {
|
|
1261
|
-
if (item.id === this.id) {
|
|
1262
|
-
if (noTextRangeSelected) {
|
|
1263
|
-
return this.insertNewNode(startOffset, action);
|
|
1264
|
-
}
|
|
1265
|
-
if (this.shouldSplitSelection(selectionRangeAnnotation.range)) {
|
|
1266
|
-
return this.splitTextNode(action, selectionRangeAnnotation.range);
|
|
1267
|
-
}
|
|
1268
|
-
else {
|
|
1269
|
-
this.applyActionToNode(this, action);
|
|
1270
|
-
return this;
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
return item;
|
|
1274
|
-
});
|
|
1275
|
-
}
|
|
1276
|
-
else {
|
|
1277
|
-
this.applyActionToNode(this, action);
|
|
1278
|
-
}
|
|
1279
|
-
this.parentBlock.mergeNodes(action);
|
|
1280
|
-
}
|
|
1281
|
-
/**
|
|
1282
|
-
* @inheritDoc
|
|
1283
|
-
*/
|
|
1284
|
-
doModifyActionApply(action) {
|
|
1285
|
-
switch (action.type) {
|
|
1286
|
-
case ModifyContentActionType.UPDATE_TEXT:
|
|
1287
|
-
this.updateText(action.newTextContent);
|
|
1288
|
-
break;
|
|
1289
|
-
case ModifyContentActionType.REPLACE_SELECTED_TEXT:
|
|
1290
|
-
this.replaceSelectedText(action.textToBeInsert, action.currentRange);
|
|
1291
|
-
break;
|
|
1292
|
-
}
|
|
1293
|
-
}
|
|
1294
|
-
/**
|
|
1295
|
-
* Split text node with range
|
|
1296
|
-
*
|
|
1297
|
-
* @param {TextSplittableAction} action - Annotation action
|
|
1298
|
-
* @param {Range} range - Selection range
|
|
1299
|
-
* @returns {RTETextNode[] | this} RTETextNode array
|
|
1300
|
-
*/
|
|
1301
|
-
splitTextNode(action, range) {
|
|
1302
|
-
const { startContainer, endContainer, startOffset } = range;
|
|
1303
|
-
const startNode = startContainer.parentElement;
|
|
1304
|
-
const endNode = endContainer.parentElement;
|
|
1305
|
-
/**
|
|
1306
|
-
* Split the text from the start offset to the end offset
|
|
1307
|
-
*
|
|
1308
|
-
* @param {string} text - The text string
|
|
1309
|
-
* @param {number} startOffset - The start offset position
|
|
1310
|
-
* @param {number} endOffset - The end offset position
|
|
1311
|
-
* @returns {RTETextNode[]} - The split text node array
|
|
1312
|
-
*/
|
|
1313
|
-
const splitText = (text, startOffset, endOffset) => {
|
|
1314
|
-
const beforeText = text.substring(0, startOffset);
|
|
1315
|
-
const selectedText = text.substring(startOffset, endOffset);
|
|
1316
|
-
const afterText = text.substring(endOffset);
|
|
1317
|
-
return [
|
|
1318
|
-
this.cloneWithText(beforeText),
|
|
1319
|
-
this.cloneWithText(selectedText),
|
|
1320
|
-
this.cloneWithText(afterText),
|
|
1321
|
-
];
|
|
1322
|
-
};
|
|
1323
|
-
const startItemDto = startNode && stateEntityRenderingRegistry.getEntityByDOM(startNode);
|
|
1324
|
-
const endItemDto = endNode && stateEntityRenderingRegistry.getEntityByDOM(endNode);
|
|
1325
|
-
if (startItemDto && startItemDto.id === this.id) {
|
|
1326
|
-
const endOffset = startContainer === endContainer ? range.endOffset : this.text.length;
|
|
1327
|
-
const [beforeNode, selectedNode, afterNode] = splitText(this.text, startOffset, endOffset);
|
|
1328
|
-
this.applyActionToNode(selectedNode, action);
|
|
1329
|
-
return [beforeNode, selectedNode, afterNode].filter((node) => !!node.text);
|
|
1330
|
-
}
|
|
1331
|
-
else if (endItemDto && endItemDto.id === this.id) {
|
|
1332
|
-
const [beforeNode, selectedNode, afterNode] = splitText(this.text, 0, range.endOffset);
|
|
1333
|
-
this.applyActionToNode(selectedNode, action);
|
|
1334
|
-
return [beforeNode, selectedNode, afterNode].filter((node) => !!node.text);
|
|
1335
|
-
}
|
|
1336
|
-
else {
|
|
1337
|
-
this.applyActionToNode(this, action);
|
|
1338
|
-
return this;
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
/**
|
|
1342
|
-
* Apply action to node
|
|
1343
|
-
*
|
|
1344
|
-
* @param {RTETextNode} node - Text node
|
|
1345
|
-
* @param {AnnotationAction} action - AnnotationAction
|
|
1346
|
-
*/
|
|
1347
|
-
applyActionToNode(node, action) {
|
|
1348
|
-
const annotation = action.toAnnotation();
|
|
1349
|
-
if (action instanceof SyncUpSelectionAction) {
|
|
1350
|
-
this.syncUpSelectedNodes(node);
|
|
1351
|
-
return;
|
|
1352
|
-
}
|
|
1353
|
-
// Sync up RTETextNode selected state to selection controller for any action apply, except selection range change.
|
|
1354
|
-
if (!(annotation instanceof SelectionRangeAnnotation)) {
|
|
1355
|
-
this.syncUpSelectedNodes(node);
|
|
1356
|
-
}
|
|
1357
|
-
if (action instanceof DeleteNodeAnnotationAction) {
|
|
1358
|
-
this.annotationMap.delete(action.annotationType);
|
|
1359
|
-
return;
|
|
1360
|
-
}
|
|
1361
|
-
if (annotation instanceof ClearFormattingAnnotation) {
|
|
1362
|
-
annotation.items.forEach((item) => {
|
|
1363
|
-
node.deleteAnnotationByType(item);
|
|
1364
|
-
});
|
|
1365
|
-
return;
|
|
1366
|
-
}
|
|
1367
|
-
if (annotation instanceof NodeAnnotation || annotation instanceof SelectionRangeAnnotation) {
|
|
1368
|
-
if (action instanceof LinkAnnotationAction) {
|
|
1369
|
-
if (isNonNullable(action.newText)) {
|
|
1370
|
-
node.text = action.newText;
|
|
1371
|
-
}
|
|
1372
|
-
this.parentBlock.apply(new LinkGroupAnnotationAction(action.link.groupKey, [node]));
|
|
1373
|
-
}
|
|
1374
|
-
if (action instanceof CodeAnnotationAction) {
|
|
1375
|
-
this.applyActionToNode(node, new ClearFormattingAnnotationAction());
|
|
1376
|
-
}
|
|
1377
|
-
node.annotationMap.set(annotation.type, annotation);
|
|
1378
|
-
return;
|
|
1379
|
-
}
|
|
1380
|
-
}
|
|
1381
|
-
/**
|
|
1382
|
-
* Replaces the selected text within a given range with a new text in a TypeScript class.
|
|
1383
|
-
*
|
|
1384
|
-
* @param {string} text - The new text that will replace the currently selected text within the specified range.
|
|
1385
|
-
* @param {RTERange} currentRange - A range of text within a Rich Text Editor (RTE).
|
|
1386
|
-
*/
|
|
1387
|
-
replaceSelectedText(text, currentRange) {
|
|
1388
|
-
if (currentRange && currentRange.startContainer && currentRange.endContainer) {
|
|
1389
|
-
const { startContainer, endContainer, startOffset, endOffset } = currentRange;
|
|
1390
|
-
const startNode = startContainer.parentElement;
|
|
1391
|
-
const endNode = endContainer.parentElement;
|
|
1392
|
-
const startItemDto = startNode && stateEntityRenderingRegistry.getEntityByDOM(startNode);
|
|
1393
|
-
const endItemDto = endNode && stateEntityRenderingRegistry.getEntityByDOM(endNode);
|
|
1394
|
-
let startIndex = 0, endIndex = this.text.length;
|
|
1395
|
-
if (startItemDto && startItemDto === this) {
|
|
1396
|
-
startIndex = startOffset;
|
|
1397
|
-
endIndex = startContainer === endContainer ? endOffset : endIndex;
|
|
1398
|
-
}
|
|
1399
|
-
else if (endItemDto && endItemDto === this) {
|
|
1400
|
-
endIndex = endOffset;
|
|
1401
|
-
}
|
|
1402
|
-
this.apply(new UpdateTextAction(this.text.slice(0, startIndex) + text + this.text.slice(endIndex)));
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
/**
|
|
1406
|
-
* Updates the text content of a node and unlink the node if it is a link node and the text is deleted.
|
|
1407
|
-
*
|
|
1408
|
-
* @param {string} newText - The new text string
|
|
1409
|
-
*/
|
|
1410
|
-
updateText(newText) {
|
|
1411
|
-
this.text = newText;
|
|
1412
|
-
// The link node should unlink when delete all text
|
|
1413
|
-
if (!this.text && this.isLinkNode()) {
|
|
1414
|
-
this.annotationMap.delete(NodeAnnotationTypeEnum.LINK);
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
/**
|
|
1418
|
-
* Checks if a node has an annotation with the key 'LINK'.
|
|
1419
|
-
*
|
|
1420
|
-
* @returns {boolean} A boolean value indicating whether the `annotationMap` has a key 'LINK'.
|
|
1421
|
-
*/
|
|
1422
|
-
isLinkNode() {
|
|
1423
|
-
return this.annotationMap.has('LINK');
|
|
1424
|
-
}
|
|
1425
|
-
/**
|
|
1426
|
-
* Whether a given range should be split based on various conditions within the range.
|
|
1427
|
-
*
|
|
1428
|
-
* @param {Range} range - Selection range
|
|
1429
|
-
* @returns {boolean} Returns a boolean value indicating whether the
|
|
1430
|
-
* selection range should be split.
|
|
1431
|
-
*/
|
|
1432
|
-
shouldSplitSelection(range) {
|
|
1433
|
-
const { startContainer, endContainer, startOffset, endOffset } = range;
|
|
1434
|
-
const isCrossNode = startContainer !== endContainer;
|
|
1435
|
-
const isPartialStart = startOffset > 0;
|
|
1436
|
-
const isPartialEnd = endOffset < (endContainer.textContent ? endContainer.textContent.length : 0);
|
|
1437
|
-
const isPartialSelection = isPartialStart || isPartialEnd;
|
|
1438
|
-
return isCrossNode || isPartialSelection;
|
|
1439
|
-
}
|
|
1440
|
-
/**
|
|
1441
|
-
* Sync up the selected node by change manager
|
|
1442
|
-
*
|
|
1443
|
-
* @param {RTETextNode} selectedNode - The selected node
|
|
1444
|
-
*/
|
|
1445
|
-
syncUpSelectedNodes(selectedNode) {
|
|
1446
|
-
const currentNodeDom = stateEntityRenderingRegistry.getDOMByEntity(this);
|
|
1447
|
-
if (currentNodeDom) {
|
|
1448
|
-
const nodeSubject = domNodeSubjectFactory.getSubjectFromParentNodeByEventId(currentNodeDom, VegaInternalRichTextEditorSelectionRangeChange);
|
|
1449
|
-
if (nodeSubject) {
|
|
1450
|
-
ChangeManager.notify(nodeSubject, { node: selectedNode });
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
/**
|
|
1455
|
-
* Insert the new node at the start offset
|
|
1456
|
-
*
|
|
1457
|
-
* @param {number} startOffset - The start position offset
|
|
1458
|
-
* @param {AnnotationAction} action - AnnotationAction
|
|
1459
|
-
* @returns {RTETextNode[]} - RTETextNode array
|
|
1460
|
-
*/
|
|
1461
|
-
insertNewNode(startOffset, action) {
|
|
1462
|
-
if (startOffset === 0) {
|
|
1463
|
-
const newNode = this.cloneWithText('');
|
|
1464
|
-
this.applyActionToNode(newNode, action);
|
|
1465
|
-
return [newNode, this];
|
|
1466
|
-
}
|
|
1467
|
-
if (startOffset === this.text.length) {
|
|
1468
|
-
const newNode = this.cloneWithText('');
|
|
1469
|
-
this.applyActionToNode(newNode, action);
|
|
1470
|
-
return [this, newNode];
|
|
1471
|
-
}
|
|
1472
|
-
const beforeNode = this.cloneWithText(this.text.substring(0, startOffset));
|
|
1473
|
-
const newNode = this.cloneWithText('');
|
|
1474
|
-
const afterNode = this.cloneWithText(this.text.substring(startOffset));
|
|
1475
|
-
this.applyActionToNode(newNode, action);
|
|
1476
|
-
return [beforeNode, newNode, afterNode];
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
|
|
1480
|
-
/**
|
|
1481
|
-
* Text style annotation
|
|
1482
|
-
*/
|
|
1483
|
-
class TextStyleAnnotation extends BlockAnnotation {
|
|
1484
|
-
constructor(textStyle) {
|
|
1485
|
-
super();
|
|
1486
|
-
this.type = BlockAnnotationTypeEnum.TEXT_STYLE;
|
|
1487
|
-
this.textStyle = textStyle;
|
|
1488
|
-
}
|
|
1489
|
-
/**
|
|
1490
|
-
* Generate the map item for the annotations
|
|
1491
|
-
*
|
|
1492
|
-
* @param {VegaRTETextStyleType} textStyle - the text style type
|
|
1493
|
-
* @returns {[BlockAnnotationTypeEnum.TEXT_STYLE, TextStyleAnnotation]} Map item for the annotation
|
|
1494
|
-
*/
|
|
1495
|
-
static from(textStyle) {
|
|
1496
|
-
return [BlockAnnotationTypeEnum.TEXT_STYLE, new TextStyleAnnotation(textStyle)];
|
|
1497
|
-
}
|
|
1498
|
-
/**
|
|
1499
|
-
* Generate the JSON representation of the annotation
|
|
1500
|
-
*
|
|
1501
|
-
* @returns {Nullable<Record<string, unknown>>} JSON representation of the annotation
|
|
1502
|
-
*/
|
|
1503
|
-
toJSON() {
|
|
1504
|
-
return { textStyle: this.textStyle };
|
|
1505
|
-
}
|
|
1506
|
-
/**
|
|
1507
|
-
* Render the styles by block type
|
|
1508
|
-
*
|
|
1509
|
-
* @returns {AnnotationStyle} the styles to apply
|
|
1510
|
-
*/
|
|
1511
|
-
render() {
|
|
1512
|
-
const paragraphStyle = {
|
|
1513
|
-
fontFamily: 'Inter',
|
|
1514
|
-
fontSize: '16px',
|
|
1515
|
-
lineHeight: '22px',
|
|
1516
|
-
fontWeight: '500',
|
|
1517
|
-
};
|
|
1518
|
-
switch (this.textStyle) {
|
|
1519
|
-
case 'paragraph': {
|
|
1520
|
-
return paragraphStyle;
|
|
1521
|
-
}
|
|
1522
|
-
case 'title': {
|
|
1523
|
-
return { fontFamily: 'Inter', fontSize: '36px', lineHeight: '40px', fontWeight: '500' };
|
|
1524
|
-
}
|
|
1525
|
-
case 'subtitle': {
|
|
1526
|
-
return { fontFamily: 'Inter', fontSize: '28px', lineHeight: '32px', fontWeight: '500' };
|
|
1527
|
-
}
|
|
1528
|
-
case 'heading-1': {
|
|
1529
|
-
return { fontFamily: 'Inter', fontSize: '22px', lineHeight: '24px', fontWeight: '500' };
|
|
1530
|
-
}
|
|
1531
|
-
case 'heading-2': {
|
|
1532
|
-
return { fontFamily: 'Inter', fontSize: '20px', lineHeight: '24px', fontWeight: '500' };
|
|
1533
|
-
}
|
|
1534
|
-
case 'heading-3': {
|
|
1535
|
-
return { fontFamily: 'Inter', fontSize: '18px', lineHeight: '22px', fontWeight: '500' };
|
|
1536
|
-
}
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1539
|
-
}
|
|
1540
|
-
|
|
1541
|
-
/**
|
|
1542
|
-
* Action to change the text style of a block
|
|
1543
|
-
*/
|
|
1544
|
-
class TextStyleAnnotationAction extends AnnotationAction {
|
|
1545
|
-
constructor(textStyle, bold) {
|
|
1546
|
-
super();
|
|
1547
|
-
this.isFlushable = true;
|
|
1548
|
-
this.textStyle = textStyle;
|
|
1549
|
-
this.bold = bold;
|
|
1550
|
-
}
|
|
1551
|
-
/**
|
|
1552
|
-
* Converts the action to a block annotation
|
|
1553
|
-
*
|
|
1554
|
-
* @returns {BlockAnnotation} the block annotation
|
|
1555
|
-
*/
|
|
1556
|
-
toAnnotation() {
|
|
1557
|
-
return new TextStyleAnnotation(this.textStyle);
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
|
-
/**
|
|
1562
|
-
* Action to toggle bold annotation
|
|
1563
|
-
*/
|
|
1564
|
-
class BoldAnnotationAction extends TextSplittableAction {
|
|
1565
|
-
constructor(bold) {
|
|
1566
|
-
super();
|
|
1567
|
-
this.isFlushable = true;
|
|
1568
|
-
this.bold = bold;
|
|
1569
|
-
}
|
|
1570
|
-
/**
|
|
1571
|
-
* Converts the action to an annotation
|
|
1572
|
-
*
|
|
1573
|
-
* @returns {BoldAnnotation} the annotation
|
|
1574
|
-
*/
|
|
1575
|
-
toAnnotation() {
|
|
1576
|
-
return new BoldAnnotation(this.bold);
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
|
|
1580
|
-
/**
|
|
1581
|
-
* Merge the two blocks node into first block if the two blocks nodes type is same(text node or image node)
|
|
1582
|
-
*
|
|
1583
|
-
* @example firstBlock.apply(new MergeTwoBlocksNodesAction(secondBlock))
|
|
1584
|
-
*/
|
|
1585
|
-
class MergeTwoBlocksNodesAction extends ModifyContentAction {
|
|
1586
|
-
constructor(blockNeedToBeMerged) {
|
|
1587
|
-
super();
|
|
1588
|
-
this.type = ModifyContentActionType.MERGE_TWO_BLOCKS_NODES;
|
|
1589
|
-
this.blockNeedToBeMerged = blockNeedToBeMerged;
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1593
|
-
/**
|
|
1594
|
-
* Insert a new block before a existing block
|
|
1595
|
-
*
|
|
1596
|
-
* @example currentBlock.parent.apply(new InsertBlocksBeforeAction(currentBlock, newBlock, ...))
|
|
1597
|
-
*/
|
|
1598
|
-
class InsertBlocksBeforeAction extends ModifyContentAction {
|
|
1599
|
-
constructor(referBlock, ...blocksToBeInserted) {
|
|
1600
|
-
super();
|
|
1601
|
-
this.type = ModifyContentActionType.INSERT_BLOCKS_BEFORE;
|
|
1602
|
-
this.referBlock = referBlock;
|
|
1603
|
-
this.blocksToBeInserted = blocksToBeInserted;
|
|
1604
|
-
}
|
|
1605
|
-
}
|
|
1606
|
-
|
|
1607
|
-
/**
|
|
1608
|
-
* Text block
|
|
1609
|
-
*/
|
|
1610
|
-
class RTETextBlock extends RTEBlock {
|
|
1611
|
-
constructor(id, type) {
|
|
1612
|
-
super(id);
|
|
1613
|
-
this.nodes = [];
|
|
1614
|
-
this.type = type;
|
|
1615
|
-
if (RTETextBlock.isAcceptableTextStyle(type)) {
|
|
1616
|
-
this.annotationMap = new Map([TextStyleAnnotation.from(type)]);
|
|
1617
|
-
}
|
|
1618
|
-
else {
|
|
1619
|
-
this.annotationMap = new Map([TextStyleAnnotation.from('paragraph')]);
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
/**
|
|
1623
|
-
* Converts a VegaRTETextBlock into an RTETextBlock.
|
|
1624
|
-
*
|
|
1625
|
-
* @param {VegaRTETextBlock} block - The block object
|
|
1626
|
-
* @returns {RTETextBlock} A RTETextBlock class
|
|
1627
|
-
*/
|
|
1628
|
-
static from(block) {
|
|
1629
|
-
const textBlock = new RTETextBlock(block.id, block.type);
|
|
1630
|
-
const { annotations } = block;
|
|
1631
|
-
textBlock.nodes = block.nodes.map((richText) => RTETextNode.from(richText, textBlock));
|
|
1632
|
-
if (annotations) {
|
|
1633
|
-
Object.entries(annotations).forEach(([type, value]) => {
|
|
1634
|
-
const item = this.createAnnotationEntity(type, value);
|
|
1635
|
-
if (isNonNullable(item)) {
|
|
1636
|
-
textBlock.annotationMap.set(...item);
|
|
1637
|
-
}
|
|
1638
|
-
});
|
|
1639
|
-
}
|
|
1640
|
-
return textBlock;
|
|
1641
|
-
}
|
|
1642
|
-
/**
|
|
1643
|
-
* The function `createAnnotationEntity` creates a block annotation entity based on the provided type
|
|
1644
|
-
* and value.
|
|
1645
|
-
*
|
|
1646
|
-
* @param {keyof VegaRTEBlockAnnotations} type - The `type` parameter is a key of the `VegaRTEBlockAnnotations` enum, which specifies
|
|
1647
|
-
* the type of annotation entity to create.
|
|
1648
|
-
* @param {unknown} value - The `value` parameter in the `createAnnotationEntity` function is the value
|
|
1649
|
-
* that will be used to create the annotation entity. It can be of any type depending on the specific
|
|
1650
|
-
* annotation being created.
|
|
1651
|
-
* @returns {Nullable<[BlockAnnotationTypeEnum, BlockAnnotation]>} The `createAnnotationEntity` function returns a nullable tuple containing a
|
|
1652
|
-
* `BlockAnnotationTypeEnum` and a `BlockAnnotation` object.
|
|
1653
|
-
*/
|
|
1654
|
-
static createAnnotationEntity(type, value) {
|
|
1655
|
-
if (type === 'textStyle') {
|
|
1656
|
-
return TextStyleAnnotation.from(value);
|
|
1657
|
-
}
|
|
1658
|
-
else {
|
|
1659
|
-
return super.createAnnotationEntity(type, value);
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
/**
|
|
1663
|
-
* Checks if a given text block type is one of the acceptable text styles.
|
|
1664
|
-
*
|
|
1665
|
-
* @param {VegaRTETextBlockType} type - The text block type
|
|
1666
|
-
* @returns {boolean} Return a boolean value indicating whether the `type` parameter is valid.
|
|
1667
|
-
*/
|
|
1668
|
-
static isAcceptableTextStyle(type) {
|
|
1669
|
-
return ['title', 'subtitle', 'paragraph', 'heading-1', 'heading-2', 'heading-3'].includes(type);
|
|
1670
|
-
}
|
|
1671
|
-
/**
|
|
1672
|
-
* Merges RTETextNode nodes based on certain conditions.
|
|
1673
|
-
*
|
|
1674
|
-
* @param {AnnotationAction} action - AnnotationAction
|
|
1675
|
-
*/
|
|
1676
|
-
mergeNodes(action) {
|
|
1677
|
-
this.nodes = this.nodes.reduce((prev, cur) => {
|
|
1678
|
-
const lastNode = prev.at(-1);
|
|
1679
|
-
if (action instanceof LinkAnnotationAction && action.needMergeNode) {
|
|
1680
|
-
const lastNodeLinkAnnotation = lastNode === null || lastNode === void 0 ? void 0 : lastNode.getAnnotationByType(NodeAnnotationTypeEnum.LINK);
|
|
1681
|
-
const curNodeLinkAnnotation = cur.getAnnotationByType(NodeAnnotationTypeEnum.LINK);
|
|
1682
|
-
if (lastNodeLinkAnnotation &&
|
|
1683
|
-
curNodeLinkAnnotation &&
|
|
1684
|
-
lastNodeLinkAnnotation.toEqual(curNodeLinkAnnotation)) {
|
|
1685
|
-
return prev;
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
// TODO: handle other cases like merge bold nodes
|
|
1689
|
-
return [...prev, cur];
|
|
1690
|
-
}, []);
|
|
1691
|
-
}
|
|
1692
|
-
/**
|
|
1693
|
-
* @inheritDoc
|
|
1694
|
-
*/
|
|
1695
|
-
toJSON() {
|
|
1696
|
-
return Object.assign(Object.assign({}, super.toJSON()), { type: this.type, nodes: this.nodes.map((node) => node.toJSON()) });
|
|
1697
|
-
}
|
|
1698
|
-
/**
|
|
1699
|
-
* Clone the nodes to a new block
|
|
1700
|
-
*
|
|
1701
|
-
* @param {RTEBlock} nodes - The nodes will be copied
|
|
1702
|
-
* @returns {RTEBlock} New block
|
|
1703
|
-
*/
|
|
1704
|
-
cloneWithNodes(nodes) {
|
|
1705
|
-
const block = new RTETextBlock(generateUUID(), this.type);
|
|
1706
|
-
block.nodes = [];
|
|
1707
|
-
block.apply(new AppendChildNodesAction(nodes));
|
|
1708
|
-
return block;
|
|
1709
|
-
}
|
|
1710
|
-
/**
|
|
1711
|
-
* @inheritDoc
|
|
1712
|
-
*/
|
|
1713
|
-
isNotEmpty() {
|
|
1714
|
-
return this.nodes.length > 0 && this.nodes.some((node) => !node.isEmpty());
|
|
1715
|
-
}
|
|
1716
|
-
/**
|
|
1717
|
-
* @inheritDoc
|
|
1718
|
-
*/
|
|
1719
|
-
getLastNode() {
|
|
1720
|
-
return this.nodes[this.nodes.length - 1];
|
|
1721
|
-
}
|
|
1722
|
-
/**
|
|
1723
|
-
* @inheritDoc
|
|
1724
|
-
*/
|
|
1725
|
-
doAnnotationActionApply(action) {
|
|
1726
|
-
if (action instanceof TextStyleAnnotationAction) {
|
|
1727
|
-
if (this.type !== 'list-item') {
|
|
1728
|
-
this.type = action.textStyle;
|
|
1729
|
-
}
|
|
1730
|
-
if (action.bold) {
|
|
1731
|
-
this.nodes.forEach((node) => {
|
|
1732
|
-
const boldAnnotationAction = new BoldAnnotationAction(true);
|
|
1733
|
-
boldAnnotationAction.doSplit = false;
|
|
1734
|
-
node.apply(boldAnnotationAction);
|
|
1735
|
-
});
|
|
1736
|
-
}
|
|
1737
|
-
else {
|
|
1738
|
-
this.nodes.forEach((node) => {
|
|
1739
|
-
node.apply(new DeleteNodeAnnotationAction(NodeAnnotationTypeEnum.BOLD));
|
|
1740
|
-
});
|
|
1741
|
-
}
|
|
1742
|
-
return;
|
|
1743
|
-
}
|
|
1744
|
-
if (action instanceof LinkGroupAnnotationAction) {
|
|
1745
|
-
const linkGroupAnnotation = this.getAnnotationByType(InternalAnnotationTypeEnum.LINK_GROUP);
|
|
1746
|
-
if (linkGroupAnnotation) {
|
|
1747
|
-
const linkGroup = linkGroupAnnotation.linkGroups.get(action.groupKey);
|
|
1748
|
-
linkGroupAnnotation.linkGroups.set(action.groupKey, [...linkGroup, ...action.nodes]);
|
|
1749
|
-
this.annotationMap.set(InternalAnnotationTypeEnum.LINK_GROUP, linkGroupAnnotation);
|
|
1750
|
-
}
|
|
1751
|
-
return;
|
|
1752
|
-
}
|
|
1753
|
-
}
|
|
1754
|
-
/**
|
|
1755
|
-
* Apply a modify action to block
|
|
1756
|
-
*
|
|
1757
|
-
* @param {ModifyContentAction} action - Modify action
|
|
1758
|
-
*/
|
|
1759
|
-
doModifyActionApply(action) {
|
|
1760
|
-
switch (action.type) {
|
|
1761
|
-
case ModifyContentActionType.DELETE_CHILD:
|
|
1762
|
-
this.removeChildNode(action);
|
|
1763
|
-
break;
|
|
1764
|
-
case ModifyContentActionType.APPEND_CHILD_NODES:
|
|
1765
|
-
this.appendChildNodes(action.entityToBeAppended);
|
|
1766
|
-
break;
|
|
1767
|
-
case ModifyContentActionType.CLEAR_CHILD_NODES:
|
|
1768
|
-
this.nodes = [];
|
|
1769
|
-
break;
|
|
1770
|
-
case ModifyContentActionType.SPLIT_BLOCK_WITH_NODE:
|
|
1771
|
-
action.newBlock = this.splitTextNodeBlock(action.splitPointNode, action.startOffsetOfNode);
|
|
1772
|
-
break;
|
|
1773
|
-
case ModifyContentActionType.REPLACE_CHILD_NODES:
|
|
1774
|
-
this.nodes = [];
|
|
1775
|
-
this.appendChildNodes(action.newChildNodes);
|
|
1776
|
-
break;
|
|
1777
|
-
case ModifyContentActionType.MERGE_TWO_BLOCKS_NODES:
|
|
1778
|
-
this.mergeTwoBlocksNodes(action.blockNeedToBeMerged);
|
|
1779
|
-
break;
|
|
1780
|
-
case ModifyContentActionType.BREAK_SINGLE_BLOCK:
|
|
1781
|
-
action.newBlock = this.breakSingleTextBlock(action.startContainerNode, action.startOffset);
|
|
1782
|
-
break;
|
|
1783
|
-
case ModifyContentActionType.LINE_BREAK_SINGLE_BLOCK:
|
|
1784
|
-
action.lineBreakNode = this.lineBreakSingleBlock(action.startContainerNode, action.startOffset);
|
|
1785
|
-
break;
|
|
1786
|
-
case ModifyContentActionType.LINE_BREAK_MULTIPLE_BLOCKS:
|
|
1787
|
-
action.lineBreakNode = this.lineBreakMultipleBlocks(action.selectedBlocks);
|
|
1788
|
-
break;
|
|
1789
|
-
case ModifyContentActionType.TRANSFORM_LIST_BLOCK:
|
|
1790
|
-
this.convertParagraphToList(action);
|
|
1791
|
-
break;
|
|
1792
|
-
case ModifyContentActionType.DELETE_BLOCK_CONTENT:
|
|
1793
|
-
this.deleteNodeContent(action);
|
|
1794
|
-
break;
|
|
1795
|
-
case ModifyContentActionType.INSERT_IMAGE_TO_BLOCK:
|
|
1796
|
-
this.insertImage(action);
|
|
1797
|
-
break;
|
|
1798
|
-
case ModifyContentActionType.INSERT_NODES_BEFORE:
|
|
1799
|
-
this.replaceNodeWithNodes(action.referNode, [
|
|
1800
|
-
...action.nodesToBeInserted,
|
|
1801
|
-
action.referNode,
|
|
1802
|
-
]);
|
|
1803
|
-
break;
|
|
1804
|
-
}
|
|
1805
|
-
}
|
|
1806
|
-
/**
|
|
1807
|
-
* Splits a text node at a specified offset within a block of nodes and returns a new block with the split nodes.
|
|
1808
|
-
*
|
|
1809
|
-
* @param {RTETextNode} splitNode - The text node that will be split
|
|
1810
|
-
* @param {number} startOffsetOfNode - The index at which will split the text content of the `splitNode`.
|
|
1811
|
-
* @returns {Nullable<RTEBlock>} return either an RTEBlock object or null.
|
|
1812
|
-
*/
|
|
1813
|
-
splitTextNodeBlock(splitNode, startOffsetOfNode) {
|
|
1814
|
-
if (splitNode) {
|
|
1815
|
-
const beforeText = splitNode.text.slice(0, startOffsetOfNode);
|
|
1816
|
-
const afterText = splitNode.text.slice(startOffsetOfNode);
|
|
1817
|
-
const nodesSplitIndex = this.nodes.indexOf(splitNode);
|
|
1818
|
-
if (nodesSplitIndex > -1) {
|
|
1819
|
-
const beforeNodes = this.nodes.slice(0, nodesSplitIndex);
|
|
1820
|
-
const afterNodes = this.nodes.slice(nodesSplitIndex + 1);
|
|
1821
|
-
if (beforeText) {
|
|
1822
|
-
beforeNodes.push(splitNode.cloneWithText(beforeText));
|
|
1823
|
-
}
|
|
1824
|
-
if (afterText) {
|
|
1825
|
-
afterNodes.unshift(splitNode.cloneWithText(afterText));
|
|
1826
|
-
}
|
|
1827
|
-
this.apply(new ReplaceChildNodesAction(beforeNodes));
|
|
1828
|
-
const newBlock = this.cloneWithNodes(afterNodes);
|
|
1829
|
-
this.parent.apply(new InsertBlocksAfterAction(this, newBlock));
|
|
1830
|
-
return newBlock;
|
|
1831
|
-
}
|
|
1832
|
-
}
|
|
1833
|
-
}
|
|
1834
|
-
/**
|
|
1835
|
-
* Checks if the caret position is at the start of a specified RTETextNode.
|
|
1836
|
-
*
|
|
1837
|
-
* @param {RTETextNode} node - `RTETextNode` - a node representing an image in a rich text editor.
|
|
1838
|
-
* @param {number} startOffset - The position within the text node where the caret is located.
|
|
1839
|
-
* @returns {boolean} a boolean value, which indicates whether the caret position is at the start of the RTETextNode.
|
|
1840
|
-
*/
|
|
1841
|
-
isCaretPositionAtStart(node, startOffset) {
|
|
1842
|
-
return node === this.nodes[0] && startOffset === 0;
|
|
1843
|
-
}
|
|
1844
|
-
/**
|
|
1845
|
-
* Checks if the caret position is at the end of a specified RTETextNode.
|
|
1846
|
-
*
|
|
1847
|
-
* @param {RTETextNode} node - `RTETextNode` - a node representing an image in a rich text editor.
|
|
1848
|
-
* @param {number} startOffset - The position within the text node where the caret is located.
|
|
1849
|
-
* @returns {boolean} a boolean value, which indicates whether the caret position is at the start of the RTETextNode.
|
|
1850
|
-
*/
|
|
1851
|
-
isCaretPositionAtEnd(node, startOffset) {
|
|
1852
|
-
const lastNode = this.nodes[this.nodes.length - 1];
|
|
1853
|
-
return node === lastNode && (node.isEmpty() || startOffset === lastNode.text.length);
|
|
1854
|
-
}
|
|
1855
|
-
/**
|
|
1856
|
-
* lineBreakSingleBlock
|
|
1857
|
-
*
|
|
1858
|
-
* @param {RTETextNode} splitNode -
|
|
1859
|
-
* @param {number} startOffsetOfNode -
|
|
1860
|
-
* @returns {Nullable<RTETextNode>} Nullable<RTETextNode>
|
|
1861
|
-
*/
|
|
1862
|
-
lineBreakSingleBlock(splitNode, startOffsetOfNode) {
|
|
1863
|
-
if (splitNode) {
|
|
1864
|
-
const lineBreakNode = new RTETextNode(generateUUID(), '\n', this);
|
|
1865
|
-
const beforeText = splitNode.text.slice(0, startOffsetOfNode);
|
|
1866
|
-
const afterText = splitNode.text.slice(startOffsetOfNode);
|
|
1867
|
-
const nodesSplitIndex = this.nodes.indexOf(splitNode);
|
|
1868
|
-
if (nodesSplitIndex > -1) {
|
|
1869
|
-
const beforeNodes = this.nodes.slice(0, nodesSplitIndex);
|
|
1870
|
-
const afterNodes = this.nodes.slice(nodesSplitIndex + 1);
|
|
1871
|
-
if (beforeText) {
|
|
1872
|
-
beforeNodes.push(splitNode.cloneWithText(beforeText));
|
|
1873
|
-
}
|
|
1874
|
-
if (afterText) {
|
|
1875
|
-
afterNodes.unshift(splitNode.cloneWithText(afterText));
|
|
1876
|
-
}
|
|
1877
|
-
this.mergeLineBreakNodes(beforeNodes, lineBreakNode, afterNodes);
|
|
1878
|
-
}
|
|
1879
|
-
return lineBreakNode;
|
|
1880
|
-
}
|
|
1881
|
-
}
|
|
1882
|
-
/**
|
|
1883
|
-
* lineBreakMultipleBlocks
|
|
1884
|
-
*
|
|
1885
|
-
* @param {RTEBlock[]} selectedBlocks -
|
|
1886
|
-
* @returns {Nullable<RTETextNode>} Nullable<RTETextNode>
|
|
1887
|
-
*/
|
|
1888
|
-
lineBreakMultipleBlocks(selectedBlocks) {
|
|
1889
|
-
const beforeNodes = this['nodes'];
|
|
1890
|
-
const lineBreakNode = new RTETextNode(generateUUID(), '\n', this);
|
|
1891
|
-
const afterNodes = this.concatBlocksNodes(selectedBlocks.slice(1));
|
|
1892
|
-
this.mergeLineBreakNodes(beforeNodes, lineBreakNode, afterNodes);
|
|
1893
|
-
return lineBreakNode;
|
|
1894
|
-
}
|
|
1895
|
-
/**
|
|
1896
|
-
* deleteNodeContent
|
|
1897
|
-
*
|
|
1898
|
-
* @param {DeleteBlockContentAction} action - ModifyContentAction
|
|
1899
|
-
*/
|
|
1900
|
-
deleteNodeContent(action) {
|
|
1901
|
-
const startContainerNode = action.startContainerNode;
|
|
1902
|
-
const startOffset = action.startOffset;
|
|
1903
|
-
if (startOffset !== 0 && !startContainerNode.isEmpty()) {
|
|
1904
|
-
const newText = startContainerNode.text.slice(0, startOffset - 1) +
|
|
1905
|
-
startContainerNode.text.slice(startOffset);
|
|
1906
|
-
startContainerNode.apply(new UpdateTextAction(newText));
|
|
1907
|
-
if (newText) {
|
|
1908
|
-
action.previousNode = startContainerNode;
|
|
1909
|
-
return;
|
|
1910
|
-
}
|
|
1911
|
-
else {
|
|
1912
|
-
const previousNode = this.getPreviousNode(startContainerNode);
|
|
1913
|
-
// Remove the last character will not delete paragraph, the paragraph will removed after press delete again
|
|
1914
|
-
if ((previousNode && previousNode.parentBlock === this && previousNode['text'] === '\n') ||
|
|
1915
|
-
this.nodes.length === 1) {
|
|
1916
|
-
action.previousNode = startContainerNode;
|
|
1917
|
-
return;
|
|
1918
|
-
}
|
|
1919
|
-
else {
|
|
1920
|
-
this.apply(new RemoveChildAction(startContainerNode));
|
|
1921
|
-
action.previousNode = previousNode;
|
|
1922
|
-
return;
|
|
1923
|
-
}
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
else {
|
|
1927
|
-
let previousNode = this.getPreviousNode(startContainerNode);
|
|
1928
|
-
let nextNode = null;
|
|
1929
|
-
if (this.nodes.length && previousNode && previousNode.parentBlock !== this) {
|
|
1930
|
-
if (startContainerNode.isEmpty()) {
|
|
1931
|
-
this.apply(new RemoveChildAction(startContainerNode));
|
|
1932
|
-
}
|
|
1933
|
-
previousNode.parentBlock.apply(new MergeTwoBlocksNodesAction(this));
|
|
1934
|
-
}
|
|
1935
|
-
else {
|
|
1936
|
-
if (this.isContentFirstNode(startContainerNode) && startContainerNode.isEmpty()) {
|
|
1937
|
-
nextNode = this.getNextNode(startContainerNode);
|
|
1938
|
-
}
|
|
1939
|
-
/**
|
|
1940
|
-
* Remove line break
|
|
1941
|
-
*
|
|
1942
|
-
* @example caret at the first line
|
|
1943
|
-
* \n
|
|
1944
|
-
* test
|
|
1945
|
-
*/
|
|
1946
|
-
if (startContainerNode.isEmpty()) {
|
|
1947
|
-
this.apply(new RemoveChildAction(startContainerNode));
|
|
1948
|
-
}
|
|
1949
|
-
/**
|
|
1950
|
-
* Remove line break
|
|
1951
|
-
*
|
|
1952
|
-
* @example caret at the begin of second line
|
|
1953
|
-
* \n
|
|
1954
|
-
* test
|
|
1955
|
-
*/
|
|
1956
|
-
if (previousNode instanceof RTETextNode && previousNode.isEmpty()) {
|
|
1957
|
-
const shouldRemoveNode = previousNode;
|
|
1958
|
-
previousNode = this.getPreviousNode(previousNode);
|
|
1959
|
-
shouldRemoveNode.parentBlock.apply(new RemoveChildAction(shouldRemoveNode));
|
|
1960
|
-
if (!previousNode) {
|
|
1961
|
-
nextNode = startContainerNode;
|
|
1962
|
-
}
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1965
|
-
//Remove the paragraph block if the content is empty
|
|
1966
|
-
if (this.nodes.length === 0) {
|
|
1967
|
-
this.parent.apply(new RemoveChildAction(this));
|
|
1968
|
-
}
|
|
1969
|
-
if (previousNode) {
|
|
1970
|
-
action.previousNode = previousNode;
|
|
1971
|
-
}
|
|
1972
|
-
else if (nextNode) {
|
|
1973
|
-
action.nextNode = nextNode;
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
/**
|
|
1978
|
-
* Remove the child node
|
|
1979
|
-
*
|
|
1980
|
-
* @param {RemoveChildAction} action - Modify action
|
|
1981
|
-
*/
|
|
1982
|
-
removeChildNode(action) {
|
|
1983
|
-
this.nodes = this.nodes.filter((node) => node !== action.entityToBeRemoved);
|
|
1984
|
-
if (this.nodes.length === 0) {
|
|
1985
|
-
this.parent.apply(new RemoveChildAction(this));
|
|
1986
|
-
}
|
|
1987
|
-
}
|
|
1988
|
-
/**
|
|
1989
|
-
* mergeLineBreakNodes
|
|
1990
|
-
*
|
|
1991
|
-
* @param {RTENode[]} beforeNodes -
|
|
1992
|
-
* @param {RTETextNode} lineBreakNode -
|
|
1993
|
-
* @param {RTENode[]} afterNodes -
|
|
1994
|
-
*/
|
|
1995
|
-
mergeLineBreakNodes(beforeNodes, lineBreakNode, afterNodes) {
|
|
1996
|
-
if (afterNodes.length === 0 || (afterNodes[0] && afterNodes[0].text === '')) {
|
|
1997
|
-
afterNodes.push(new RTETextNode(generateUUID(), '\n', this, beforeNodes[beforeNodes.length - 1] && beforeNodes[beforeNodes.length - 1].annotationMap));
|
|
1998
|
-
}
|
|
1999
|
-
this.apply(new ReplaceChildNodesAction([...beforeNodes, lineBreakNode, ...afterNodes]));
|
|
2000
|
-
}
|
|
2001
|
-
/**
|
|
2002
|
-
* breakSingleTextBlock
|
|
2003
|
-
*
|
|
2004
|
-
* @param {RTETextNode} splitNode -
|
|
2005
|
-
* @param {number} startOffsetOfNode -
|
|
2006
|
-
* @returns {Nullable<RTEBlock>} Nullable<RTEBlock>
|
|
2007
|
-
*/
|
|
2008
|
-
breakSingleTextBlock(splitNode, startOffsetOfNode) {
|
|
2009
|
-
const newParagraph = this.copyInlineStyleToNewParagraph(splitNode);
|
|
2010
|
-
if (this.isCaretPositionAtEnd(splitNode, startOffsetOfNode)) {
|
|
2011
|
-
this.parent.apply(new InsertBlocksAfterAction(this, newParagraph));
|
|
2012
|
-
}
|
|
2013
|
-
else if (this.isCaretPositionAtStart(splitNode, startOffsetOfNode)) {
|
|
2014
|
-
this.parent.apply(new InsertBlocksBeforeAction(this, newParagraph));
|
|
2015
|
-
}
|
|
2016
|
-
else {
|
|
2017
|
-
const splitBlockAction = new SplitBlockWithNodeAction(splitNode, startOffsetOfNode);
|
|
2018
|
-
this.apply(splitBlockAction);
|
|
2019
|
-
return splitBlockAction.newBlock;
|
|
2020
|
-
}
|
|
2021
|
-
return newParagraph;
|
|
2022
|
-
}
|
|
2023
|
-
/**
|
|
2024
|
-
* convertParagraphToList
|
|
2025
|
-
*
|
|
2026
|
-
* @param {TransformListAction} action - ModifyContentAction
|
|
2027
|
-
*/
|
|
2028
|
-
convertParagraphToList(action) {
|
|
2029
|
-
const bulletList = this.parent.createList(action.listType);
|
|
2030
|
-
const listItems = action.selectedBlocks.map((node) => this.parent.toListItem(node));
|
|
2031
|
-
bulletList.apply(new AppendChildNodesAction(listItems));
|
|
2032
|
-
this.parent.apply(new InsertBlocksAfterAction(action.selectedBlocks[0], bulletList));
|
|
2033
|
-
action.selectedBlocks.forEach((node) => {
|
|
2034
|
-
node.parent.apply(new RemoveChildAction(node));
|
|
2035
|
-
});
|
|
2036
|
-
}
|
|
2037
|
-
/**
|
|
2038
|
-
* insertImage
|
|
2039
|
-
*
|
|
2040
|
-
* @param {InsertImageToBlockAction} action - ModifyContentAction
|
|
2041
|
-
*/
|
|
2042
|
-
insertImage(action) {
|
|
2043
|
-
const splitNode = action.splitPointNode;
|
|
2044
|
-
const startOffsetOfNode = action.startOffsetOfNode;
|
|
2045
|
-
const newImageBlock = action.imageBlockToBeInserted;
|
|
2046
|
-
if (this.isCaretPositionAtEnd(splitNode, startOffsetOfNode)) {
|
|
2047
|
-
this.parent.apply(new InsertBlocksAfterAction(this, newImageBlock));
|
|
2048
|
-
}
|
|
2049
|
-
else if (this.isCaretPositionAtStart(splitNode, startOffsetOfNode)) {
|
|
2050
|
-
this.parent.apply(new InsertBlocksBeforeAction(this, newImageBlock));
|
|
2051
|
-
}
|
|
2052
|
-
else {
|
|
2053
|
-
const splitBlockAction = new SplitBlockWithNodeAction(splitNode, startOffsetOfNode);
|
|
2054
|
-
this.apply(splitBlockAction);
|
|
2055
|
-
this.parent.apply(new InsertBlocksAfterAction(this, newImageBlock));
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
/**
|
|
2059
|
-
* copyInlineStyleToNewParagraph
|
|
2060
|
-
*
|
|
2061
|
-
* @param {RTETextNode} needCopedNode -
|
|
2062
|
-
* @returns {RTETextBlock} RTETextBlock
|
|
2063
|
-
*/
|
|
2064
|
-
copyInlineStyleToNewParagraph(needCopedNode) {
|
|
2065
|
-
const textNode = needCopedNode.cloneWithText('');
|
|
2066
|
-
// The link annotation don't need inherited
|
|
2067
|
-
textNode.annotationMap.delete(NodeAnnotationTypeEnum.LINK);
|
|
2068
|
-
const newParagraph = new RTETextBlock(generateUUID(), 'paragraph');
|
|
2069
|
-
newParagraph.apply(new AppendChildNodesAction([textNode]));
|
|
2070
|
-
return newParagraph;
|
|
2071
|
-
}
|
|
2072
|
-
}
|
|
2073
|
-
|
|
2074
|
-
/**
|
|
2075
|
-
* Image block
|
|
2076
|
-
*/
|
|
2077
|
-
class RTEImageBlock extends RTEBlock {
|
|
2078
|
-
constructor(id) {
|
|
2079
|
-
super(id);
|
|
2080
|
-
this.type = 'image';
|
|
2081
|
-
this.nodes = [];
|
|
2082
|
-
}
|
|
2083
|
-
/**
|
|
2084
|
-
* Converts a VegaRTEImageBlock object into an RTEImageBlock object by mapping nodes and creating annotations.
|
|
2085
|
-
*
|
|
2086
|
-
* @param {VegaRTEImageBlock} block - The block object to be converted.
|
|
2087
|
-
* @returns {RTEImageBlock} An instance of `RTEImageBlock`
|
|
2088
|
-
*/
|
|
2089
|
-
static from(block) {
|
|
2090
|
-
const imageBlock = new RTEImageBlock(block.id);
|
|
2091
|
-
const { annotations } = block;
|
|
2092
|
-
imageBlock.nodes = block.nodes.map((image) => RTEImageNode.from(image, imageBlock));
|
|
2093
|
-
if (annotations) {
|
|
2094
|
-
Object.entries(annotations).forEach(([type, value]) => {
|
|
2095
|
-
const item = this.createAnnotationEntity(type, value);
|
|
2096
|
-
if (isNonNullable(item)) {
|
|
2097
|
-
imageBlock.annotationMap.set(...item);
|
|
2098
|
-
}
|
|
2099
|
-
});
|
|
2100
|
-
}
|
|
2101
|
-
return imageBlock;
|
|
2102
|
-
}
|
|
2103
|
-
/**
|
|
2104
|
-
* @inheritDoc
|
|
2105
|
-
*/
|
|
2106
|
-
toJSON() {
|
|
2107
|
-
return Object.assign(Object.assign({}, super.toJSON()), { type: 'image', nodes: this.nodes.map((node) => node.toJSON()) });
|
|
2108
|
-
}
|
|
2109
|
-
/**
|
|
2110
|
-
* @inheritDoc
|
|
2111
|
-
*/
|
|
2112
|
-
isNotEmpty() {
|
|
2113
|
-
return this.nodes.length > 0 && this.nodes.some((node) => node.url.length > 0);
|
|
2114
|
-
}
|
|
2115
|
-
/**
|
|
2116
|
-
* @inheritDoc
|
|
2117
|
-
*/
|
|
2118
|
-
getLastNode() {
|
|
2119
|
-
return this.nodes[this.nodes.length - 1];
|
|
2120
|
-
}
|
|
2121
|
-
/**
|
|
2122
|
-
* Apply a modify action to block
|
|
2123
|
-
*
|
|
2124
|
-
* @param {ModifyContentAction} action - Modify action
|
|
2125
|
-
*/
|
|
2126
|
-
doModifyActionApply(action) {
|
|
2127
|
-
switch (action.type) {
|
|
2128
|
-
case ModifyContentActionType.DELETE_CHILD:
|
|
2129
|
-
this.removeChildNode(action);
|
|
2130
|
-
break;
|
|
2131
|
-
case ModifyContentActionType.CLEAR_CHILD_NODES:
|
|
2132
|
-
this.nodes = [];
|
|
2133
|
-
break;
|
|
2134
|
-
case ModifyContentActionType.APPEND_CHILD_NODES:
|
|
2135
|
-
this.appendChildNodes(action.entityToBeAppended);
|
|
2136
|
-
break;
|
|
2137
|
-
case ModifyContentActionType.REPLACE_CHILD_NODES:
|
|
2138
|
-
this.nodes = [];
|
|
2139
|
-
this.appendChildNodes(action.newChildNodes);
|
|
2140
|
-
break;
|
|
2141
|
-
case ModifyContentActionType.SPLIT_BLOCK_WITH_NODE:
|
|
2142
|
-
action.newBlock = this.splitImageNodes(action.splitPointNode, action.startOffsetOfNode);
|
|
2143
|
-
break;
|
|
2144
|
-
case ModifyContentActionType.MERGE_TWO_BLOCKS_NODES:
|
|
2145
|
-
this.mergeTwoBlocksNodes(action.blockNeedToBeMerged);
|
|
2146
|
-
break;
|
|
2147
|
-
case ModifyContentActionType.BREAK_SINGLE_BLOCK:
|
|
2148
|
-
action.newBlock = this.breakSingleBlock(action.startContainerNode, action.startOffset);
|
|
2149
|
-
break;
|
|
2150
|
-
case ModifyContentActionType.LINE_BREAK_SINGLE_BLOCK:
|
|
2151
|
-
action.lineBreakNode = this.lineBreakSingleBlock(action.startContainerNode, action.startOffset);
|
|
2152
|
-
break;
|
|
2153
|
-
case ModifyContentActionType.LINE_BREAK_MULTIPLE_BLOCKS:
|
|
2154
|
-
action.lineBreakNode = this.lineBreakMultipleBlocks(action.selectedBlocks);
|
|
2155
|
-
break;
|
|
2156
|
-
case ModifyContentActionType.DELETE_BLOCK_CONTENT:
|
|
2157
|
-
this.deleteNodeContent(action);
|
|
2158
|
-
break;
|
|
2159
|
-
case ModifyContentActionType.INSERT_IMAGE_TO_BLOCK:
|
|
2160
|
-
this.insertImage(action);
|
|
2161
|
-
break;
|
|
2162
|
-
case ModifyContentActionType.INSERT_NODES_AFTER:
|
|
2163
|
-
this.replaceNodeWithNodes(action.referNode, [
|
|
2164
|
-
action.referNode,
|
|
2165
|
-
...action.nodesToBeInserted,
|
|
2166
|
-
]);
|
|
2167
|
-
break;
|
|
2168
|
-
case ModifyContentActionType.INSERT_NODES_BEFORE:
|
|
2169
|
-
this.replaceNodeWithNodes(action.referNode, [
|
|
2170
|
-
...action.nodesToBeInserted,
|
|
2171
|
-
action.referNode,
|
|
2172
|
-
]);
|
|
2173
|
-
break;
|
|
2174
|
-
}
|
|
2175
|
-
}
|
|
2176
|
-
/**
|
|
2177
|
-
* Removes a specified child node from a list of nodes and triggers a parent action if the list becomes empty.
|
|
2178
|
-
*
|
|
2179
|
-
* @param {RemoveChildAction} action - Action to be performed when removing a child node from the list of nodes.
|
|
2180
|
-
*/
|
|
2181
|
-
removeChildNode(action) {
|
|
2182
|
-
this.nodes = this.nodes.filter((node) => node !== action.entityToBeRemoved);
|
|
2183
|
-
if (this.nodes.length === 0) {
|
|
2184
|
-
this.parent.apply(new RemoveChildAction(this));
|
|
2185
|
-
}
|
|
2186
|
-
}
|
|
2187
|
-
/**
|
|
2188
|
-
* The image offset should be 0 or 1
|
|
2189
|
-
* <vega-rich-text-image-editor><img /></vega-rich-text-image-editor>
|
|
2190
|
-
*
|
|
2191
|
-
* @param {RTEImageNode} imageNode The split point image node
|
|
2192
|
-
* @param {number} imageOffset The cursor point 0 | 1
|
|
2193
|
-
* @returns {Nullable<RTEBlock>} The new block after split
|
|
2194
|
-
*/
|
|
2195
|
-
splitImageNodes(imageNode, imageOffset) {
|
|
2196
|
-
const nodesSplitIndex = this.nodes.indexOf(imageNode);
|
|
2197
|
-
if (nodesSplitIndex > -1) {
|
|
2198
|
-
const beforeNodes = this.nodes.slice(0, nodesSplitIndex + imageOffset);
|
|
2199
|
-
const afterNodes = this.nodes.slice(nodesSplitIndex + imageOffset);
|
|
2200
|
-
this.apply(new ReplaceChildNodesAction(beforeNodes));
|
|
2201
|
-
const newBlock = this.cloneWithNodes(afterNodes);
|
|
2202
|
-
this.parent.apply(new InsertBlocksAfterAction(this, newBlock));
|
|
2203
|
-
return newBlock;
|
|
2204
|
-
}
|
|
2205
|
-
}
|
|
2206
|
-
/**
|
|
2207
|
-
* Creates a new RTEImageBlock instance with the provided RTEImageNode instances appended to it.
|
|
2208
|
-
*
|
|
2209
|
-
* @param {RTEImageNode[]} nodes - An array of RTEImageNode objects that will be used to create a new RTEImageBlock instance.
|
|
2210
|
-
* @returns {RTEImageBlock} A new `RTEImageBlock` object with the provided `nodes` appended to it.
|
|
2211
|
-
*/
|
|
2212
|
-
cloneWithNodes(nodes) {
|
|
2213
|
-
const block = new RTEImageBlock(generateUUID());
|
|
2214
|
-
block.nodes = [];
|
|
2215
|
-
block.apply(new AppendChildNodesAction(nodes));
|
|
2216
|
-
return block;
|
|
2217
|
-
}
|
|
2218
|
-
/**
|
|
2219
|
-
* Used to split a block of text at a specific position and insert a new paragraph block.
|
|
2220
|
-
*
|
|
2221
|
-
* @param {RTEImageNode} splitNode - The node that needs to be split into separate blocks.
|
|
2222
|
-
* @param {number} startOffsetOfNode - The index or position within the `splitNode` where the block should be broken or split.
|
|
2223
|
-
* @returns {Nullable<RTEBlock>} Returns either a new paragraph block or the new block created after splitting the original block.
|
|
2224
|
-
*/
|
|
2225
|
-
breakSingleBlock(splitNode, startOffsetOfNode) {
|
|
2226
|
-
const newParagraph = RTETextBlock.from({
|
|
2227
|
-
id: generateUUID(),
|
|
2228
|
-
type: 'paragraph',
|
|
2229
|
-
nodes: [{ id: generateUUID(), type: 'text', text: '' }],
|
|
2230
|
-
});
|
|
2231
|
-
if (this.isCaretPositionAtEnd(splitNode, startOffsetOfNode)) {
|
|
2232
|
-
this.parent.apply(new InsertBlocksAfterAction(this, newParagraph));
|
|
2233
|
-
}
|
|
2234
|
-
else if (this.isCaretPositionAtStart(splitNode, startOffsetOfNode)) {
|
|
2235
|
-
this.parent.apply(new InsertBlocksBeforeAction(this, newParagraph));
|
|
2236
|
-
}
|
|
2237
|
-
else {
|
|
2238
|
-
const splitBlockAction = new SplitBlockWithNodeAction(splitNode, startOffsetOfNode);
|
|
2239
|
-
this.apply(splitBlockAction);
|
|
2240
|
-
return splitBlockAction.newBlock;
|
|
2241
|
-
}
|
|
2242
|
-
return newParagraph;
|
|
2243
|
-
}
|
|
2244
|
-
/**
|
|
2245
|
-
* Breaks a single block of text at a specified offset and returns the first node of the new paragraph if created.
|
|
2246
|
-
*
|
|
2247
|
-
* @param {RTEImageNode} splitNode - It represents a node in a rich text editor that contains an image.
|
|
2248
|
-
* @param {number} startOffset - The index at which the line break should occur within the `RTEImageNode` block.
|
|
2249
|
-
* @returns {Nullable<RTETextNode>} Returning the first node of the `newParagraph` block if `newParagraph` is not null.
|
|
2250
|
-
*/
|
|
2251
|
-
lineBreakSingleBlock(splitNode, startOffset) {
|
|
2252
|
-
const newParagraph = this.breakSingleBlock(splitNode, startOffset);
|
|
2253
|
-
if (newParagraph) {
|
|
2254
|
-
return newParagraph['nodes'][0];
|
|
2255
|
-
}
|
|
2256
|
-
}
|
|
2257
|
-
/**
|
|
2258
|
-
* Checks if the caret position is at the start of a specified RTEImageNode.
|
|
2259
|
-
*
|
|
2260
|
-
* @param {RTEImageNode} node - `RTEImageNode` - a node representing an image in a rich text editor.
|
|
2261
|
-
* @param {number} startOffset - The position within the text node where the caret is located.
|
|
2262
|
-
* @returns {boolean} a boolean value, which indicates whether the caret position is at the start of the RTEImageNode.
|
|
2263
|
-
*/
|
|
2264
|
-
isCaretPositionAtStart(node, startOffset) {
|
|
2265
|
-
return node === this.nodes[0] && startOffset === 0;
|
|
2266
|
-
}
|
|
2267
|
-
/**
|
|
2268
|
-
* Checks if the caret position is at the end of a given RTEImageNode.
|
|
2269
|
-
*
|
|
2270
|
-
* @param {RTEImageNode} node - `node` is a RTEImageNode
|
|
2271
|
-
* @param {number} startOffset - The position within the `RTEImageNode` where the caret is located.
|
|
2272
|
-
* @returns {boolean}Returns a boolean value indicating whether the caret position is at the end of the `RTEImageNode`.
|
|
2273
|
-
*/
|
|
2274
|
-
isCaretPositionAtEnd(node, startOffset) {
|
|
2275
|
-
const lastNode = this.nodes[this.nodes.length - 1];
|
|
2276
|
-
return node === lastNode && startOffset === 1;
|
|
2277
|
-
}
|
|
2278
|
-
/**
|
|
2279
|
-
* Inserts a new paragraph block with a line break after a selected block of text in a rich text editor.
|
|
2280
|
-
*
|
|
2281
|
-
* @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.
|
|
2282
|
-
* @returns {Nullable<RTETextNode>} Returns a Nullable RTETextNode.
|
|
2283
|
-
*/
|
|
2284
|
-
lineBreakMultipleBlocks(selectedBlocks) {
|
|
2285
|
-
const newParagraph = RTETextBlock.from({
|
|
2286
|
-
id: generateUUID(),
|
|
2287
|
-
type: 'paragraph',
|
|
2288
|
-
nodes: [{ id: generateUUID(), type: 'text', text: '\n' }],
|
|
2289
|
-
});
|
|
2290
|
-
this.parent.apply(new InsertBlocksAfterAction(this, newParagraph));
|
|
2291
|
-
const afterNodes = this.concatBlocksNodes(selectedBlocks.slice(1));
|
|
2292
|
-
if (afterNodes.length === 0 || (afterNodes[0] && afterNodes[0].text === '')) {
|
|
2293
|
-
afterNodes.push(new RTETextNode(generateUUID(), '\n', newParagraph));
|
|
2294
|
-
}
|
|
2295
|
-
newParagraph.apply(new AppendChildNodesAction(afterNodes));
|
|
2296
|
-
return newParagraph['nodes'][0];
|
|
2297
|
-
}
|
|
2298
|
-
/**
|
|
2299
|
-
* Deletes content from a block node based on specific conditions.
|
|
2300
|
-
*
|
|
2301
|
-
* @param {DeleteBlockContentAction} action - Delete block content action
|
|
2302
|
-
*/
|
|
2303
|
-
deleteNodeContent(action) {
|
|
2304
|
-
const startContainerNode = action
|
|
2305
|
-
.startContainerNode, startOffset = action.startOffset;
|
|
2306
|
-
let previousNode = this.getPreviousNode(startContainerNode);
|
|
2307
|
-
let nextNode = null;
|
|
2308
|
-
if (startOffset === 1) {
|
|
2309
|
-
const parentBlock = startContainerNode.parentBlock;
|
|
2310
|
-
if (this.isContentFirstNode(startContainerNode)) {
|
|
2311
|
-
nextNode = this.getNextNode(startContainerNode);
|
|
2312
|
-
}
|
|
2313
|
-
if (parentBlock.nodes.length === 1) {
|
|
2314
|
-
parentBlock.parent.apply(new RemoveChildAction(parentBlock));
|
|
2315
|
-
}
|
|
2316
|
-
else {
|
|
2317
|
-
startContainerNode.parentBlock.apply(new RemoveChildAction(startContainerNode));
|
|
2318
|
-
}
|
|
2319
|
-
}
|
|
2320
|
-
else {
|
|
2321
|
-
const shouldRemoveNode = previousNode;
|
|
2322
|
-
if (shouldRemoveNode && shouldRemoveNode instanceof RTEImageNode) {
|
|
2323
|
-
previousNode = this.getPreviousNode(shouldRemoveNode);
|
|
2324
|
-
shouldRemoveNode.parentBlock.apply(new RemoveChildAction(shouldRemoveNode));
|
|
2325
|
-
if (!previousNode) {
|
|
2326
|
-
action.nextNode = startContainerNode;
|
|
2327
|
-
}
|
|
2328
|
-
}
|
|
2329
|
-
}
|
|
2330
|
-
if (previousNode) {
|
|
2331
|
-
action.previousNode = previousNode;
|
|
2332
|
-
}
|
|
2333
|
-
else if (nextNode) {
|
|
2334
|
-
action.nextNode = nextNode;
|
|
2335
|
-
}
|
|
2336
|
-
}
|
|
2337
|
-
/**
|
|
2338
|
-
* Image will always create new image block
|
|
2339
|
-
*
|
|
2340
|
-
* @param {InsertImageToBlockAction} action insert image to current block
|
|
2341
|
-
*/
|
|
2342
|
-
insertImage(action) {
|
|
2343
|
-
const splitNode = action.splitPointNode;
|
|
2344
|
-
const startOffsetOfNode = action.startOffsetOfNode;
|
|
2345
|
-
const newImageNodes = action.imageBlockToBeInserted.nodes;
|
|
2346
|
-
const newImageBlock = action.imageBlockToBeInserted;
|
|
2347
|
-
if (this.nodes.length < 1) {
|
|
2348
|
-
this.apply(new AppendChildNodesAction(newImageNodes));
|
|
2349
|
-
}
|
|
2350
|
-
else if (this.isCaretPositionAtEnd(splitNode, startOffsetOfNode)) {
|
|
2351
|
-
this.parent.apply(new InsertBlocksAfterAction(this, newImageBlock));
|
|
2352
|
-
}
|
|
2353
|
-
else if (this.isCaretPositionAtStart(splitNode, startOffsetOfNode)) {
|
|
2354
|
-
this.parent.apply(new InsertBlocksBeforeAction(this, newImageBlock));
|
|
2355
|
-
}
|
|
2356
|
-
else {
|
|
2357
|
-
this.apply(new SplitBlockWithNodeAction(splitNode, startOffsetOfNode));
|
|
2358
|
-
this.parent.apply(new InsertBlocksAfterAction(this, newImageBlock));
|
|
2359
|
-
}
|
|
2360
|
-
}
|
|
2361
|
-
}
|
|
2362
|
-
|
|
2363
|
-
/**
|
|
2364
|
-
* List item block
|
|
2365
|
-
*/
|
|
2366
|
-
class RTEListItemBlock extends RTETextBlock {
|
|
2367
|
-
constructor(id, children) {
|
|
2368
|
-
super(id, 'list-item');
|
|
2369
|
-
this.children = [];
|
|
2370
|
-
this.children = children;
|
|
2371
|
-
}
|
|
2372
|
-
/**
|
|
2373
|
-
* Converts a VegaRTEListItemBlock object to an RTEListItemBlock
|
|
2374
|
-
*
|
|
2375
|
-
* @param {VegaRTEListBlock} block - Converts a `VegaRTEListItemBlock` object into an `RTEListItemBlock`.
|
|
2376
|
-
* @returns {RTEListBlock} Return an instance of `RTEListItemBlock`
|
|
2377
|
-
*/
|
|
2378
|
-
static from(block) {
|
|
2379
|
-
const listItemBlock = new RTEListItemBlock(block.id);
|
|
2380
|
-
listItemBlock.nodes = block.nodes.map((richText) => RTETextNode.from(richText, listItemBlock));
|
|
2381
|
-
if (block.children) {
|
|
2382
|
-
listItemBlock.children = block.children.map((child) => {
|
|
2383
|
-
const listBlock = RTEListBlock.from(child);
|
|
2384
|
-
listBlock.parent = listItemBlock;
|
|
2385
|
-
return listBlock;
|
|
2386
|
-
});
|
|
2387
|
-
}
|
|
2388
|
-
const { annotations } = block;
|
|
2389
|
-
if (annotations) {
|
|
2390
|
-
Object.entries(annotations).forEach(([type, value]) => {
|
|
2391
|
-
const item = this.createAnnotationEntity(type, value);
|
|
2392
|
-
if (isNonNullable(item)) {
|
|
2393
|
-
listItemBlock.annotationMap.set(...item);
|
|
2394
|
-
}
|
|
2395
|
-
});
|
|
2396
|
-
}
|
|
2397
|
-
return listItemBlock;
|
|
2398
|
-
}
|
|
2399
|
-
/**
|
|
2400
|
-
* @inheritDoc
|
|
2401
|
-
*/
|
|
2402
|
-
toJSON() {
|
|
2403
|
-
var _a;
|
|
2404
|
-
return Object.assign(Object.assign({}, super.toJSON()), { type: 'list-item', children: (_a = this.children) === null || _a === void 0 ? void 0 : _a.map((block) => block.toJSON()) });
|
|
2405
|
-
}
|
|
2406
|
-
/**
|
|
2407
|
-
* @inheritDoc
|
|
2408
|
-
*/
|
|
2409
|
-
cloneWithNodes(nodes) {
|
|
2410
|
-
const block = new RTEListItemBlock(generateUUID());
|
|
2411
|
-
block.nodes = [];
|
|
2412
|
-
block.apply(new AppendChildNodesAction(nodes));
|
|
2413
|
-
return block;
|
|
2414
|
-
}
|
|
2415
|
-
/**
|
|
2416
|
-
* @inheritDoc
|
|
2417
|
-
*/
|
|
2418
|
-
isNotEmpty() {
|
|
2419
|
-
if (this.children) {
|
|
2420
|
-
return super.isNotEmpty() || this.children.some((block) => block.isNotEmpty());
|
|
2421
|
-
}
|
|
2422
|
-
else {
|
|
2423
|
-
return super.isNotEmpty();
|
|
2424
|
-
}
|
|
2425
|
-
}
|
|
2426
|
-
/**
|
|
2427
|
-
* @inheritDoc
|
|
2428
|
-
*/
|
|
2429
|
-
getLastNode() {
|
|
2430
|
-
if (this.children && this.children.length > 0) {
|
|
2431
|
-
const childListBlock = this.children[this.children.length - 1];
|
|
2432
|
-
return childListBlock.getLastNode();
|
|
2433
|
-
}
|
|
2434
|
-
return super.getLastNode();
|
|
2435
|
-
}
|
|
2436
|
-
/**
|
|
2437
|
-
* Apply a modify action to block
|
|
2438
|
-
*
|
|
2439
|
-
* @param {ModifyContentAction} action - Modify action
|
|
2440
|
-
*/
|
|
2441
|
-
doModifyActionApply(action) {
|
|
2442
|
-
switch (action.type) {
|
|
2443
|
-
case ModifyContentActionType.DELETE_CHILD:
|
|
2444
|
-
this.removeListChildNode(action);
|
|
2445
|
-
break;
|
|
2446
|
-
case ModifyContentActionType.DELETE_NEST_LIST:
|
|
2447
|
-
this.removeNestList(action);
|
|
2448
|
-
break;
|
|
2449
|
-
case ModifyContentActionType.APPEND_CHILD_NODES:
|
|
2450
|
-
this.appendChildNodes(action.entityToBeAppended);
|
|
2451
|
-
break;
|
|
2452
|
-
case ModifyContentActionType.CLEAR_CHILD_NODES:
|
|
2453
|
-
this.nodes = [];
|
|
2454
|
-
break;
|
|
2455
|
-
case ModifyContentActionType.SPLIT_BLOCK_WITH_NODE:
|
|
2456
|
-
this.splitListItemBlock(action);
|
|
2457
|
-
break;
|
|
2458
|
-
case ModifyContentActionType.REPLACE_CHILD_NODES:
|
|
2459
|
-
this.nodes = [];
|
|
2460
|
-
this.appendChildNodes(action.newChildNodes);
|
|
2461
|
-
break;
|
|
2462
|
-
case ModifyContentActionType.REPLACE_NEST_LIST:
|
|
2463
|
-
this.replaceNestList(action.newList);
|
|
2464
|
-
break;
|
|
2465
|
-
case ModifyContentActionType.MERGE_TWO_BLOCKS_NODES:
|
|
2466
|
-
this.mergeTwoBlocksNodes(action.blockNeedToBeMerged);
|
|
2467
|
-
break;
|
|
2468
|
-
case ModifyContentActionType.BREAK_SINGLE_BLOCK:
|
|
2469
|
-
action.newBlock = this.breakSingleListItemBlock(action.startContainerNode, action.startOffset);
|
|
2470
|
-
break;
|
|
2471
|
-
case ModifyContentActionType.LINE_BREAK_SINGLE_BLOCK:
|
|
2472
|
-
action.lineBreakNode = this.lineBreakSingleBlock(action.startContainerNode, action.startOffset);
|
|
2473
|
-
break;
|
|
2474
|
-
case ModifyContentActionType.LINE_BREAK_MULTIPLE_BLOCKS:
|
|
2475
|
-
action.lineBreakNode = this.lineBreakMultipleBlocks(action.selectedBlocks);
|
|
2476
|
-
break;
|
|
2477
|
-
case ModifyContentActionType.DELETE_BLOCK_CONTENT:
|
|
2478
|
-
this.deleteListNodeContent(action);
|
|
2479
|
-
break;
|
|
2480
|
-
case ModifyContentActionType.INSERT_IMAGE_TO_BLOCK:
|
|
2481
|
-
this.parent.apply(action);
|
|
2482
|
-
break;
|
|
2483
|
-
case ModifyContentActionType.INSERT_NODES_BEFORE:
|
|
2484
|
-
this.replaceNodeWithNodes(action.referNode, [
|
|
2485
|
-
...action.nodesToBeInserted,
|
|
2486
|
-
action.referNode,
|
|
2487
|
-
]);
|
|
2488
|
-
break;
|
|
2489
|
-
}
|
|
2490
|
-
}
|
|
2491
|
-
/**
|
|
2492
|
-
* Remove the list child node
|
|
2493
|
-
*
|
|
2494
|
-
* @param {RemoveChildAction} action - Modify action
|
|
2495
|
-
*/
|
|
2496
|
-
removeListChildNode(action) {
|
|
2497
|
-
this.nodes = this.nodes.filter((node) => node !== action.entityToBeRemoved);
|
|
2498
|
-
if (this.nodes.length === 0 && (!this.children || !this.children.length)) {
|
|
2499
|
-
this.parent.apply(new RemoveChildAction(this));
|
|
2500
|
-
}
|
|
2501
|
-
}
|
|
2502
|
-
/**
|
|
2503
|
-
* Remove the nest list
|
|
2504
|
-
*
|
|
2505
|
-
* @param {RemoveNestListAction} action - Modify action
|
|
2506
|
-
*/
|
|
2507
|
-
removeNestList(action) {
|
|
2508
|
-
if (this.children) {
|
|
2509
|
-
if (this.children.length > 1) {
|
|
2510
|
-
this.children = this.children.filter((child) => child !== action.nestListBlockToBeRemoved);
|
|
2511
|
-
}
|
|
2512
|
-
else {
|
|
2513
|
-
this.children = undefined;
|
|
2514
|
-
}
|
|
2515
|
-
}
|
|
2516
|
-
}
|
|
2517
|
-
/**
|
|
2518
|
-
* Iterates through a list of RTEListBlock and sets their parent property to the current object, then replaces the children property with the new list.
|
|
2519
|
-
*
|
|
2520
|
-
* @param {RTEListBlock[]} newList - new list that you want to replace the existing children of the current object with.
|
|
2521
|
-
*/
|
|
2522
|
-
replaceNestList(newList) {
|
|
2523
|
-
newList.forEach((listBlock) => {
|
|
2524
|
-
listBlock.parent = this;
|
|
2525
|
-
});
|
|
2526
|
-
this.children = newList;
|
|
2527
|
-
}
|
|
2528
|
-
/**
|
|
2529
|
-
* Split list item block
|
|
2530
|
-
*
|
|
2531
|
-
* @param {SplitBlockWithNodeAction} action - Modify action
|
|
2532
|
-
*/
|
|
2533
|
-
splitListItemBlock(action) {
|
|
2534
|
-
action.newBlock = this.splitTextNodeBlock(action.splitPointNode, action.startOffsetOfNode);
|
|
2535
|
-
}
|
|
2536
|
-
/**
|
|
2537
|
-
* Breaks a single list item block at a specific position.
|
|
2538
|
-
*
|
|
2539
|
-
* @param {RTETextNode} splitNode - The node that needs to be split within a list item block.
|
|
2540
|
-
* @param {number} startOffsetOfNode - The index within the `splitNode` where the break operation should occur.
|
|
2541
|
-
* @returns {Nullable<RTEBlock>} Returns either a new `RTEListItemBlock` if the caret
|
|
2542
|
-
* position is at the end of the `splitNode`, or it returns the result of splitting the block at the
|
|
2543
|
-
* caret position if it is neither at the start nor at the end.
|
|
2544
|
-
*/
|
|
2545
|
-
breakSingleListItemBlock(splitNode, startOffsetOfNode) {
|
|
2546
|
-
const newListItem = new RTEListItemBlock(generateUUID());
|
|
2547
|
-
const newBreakNode = this.copyInlineStyleToNewNode(splitNode);
|
|
2548
|
-
newListItem.apply(new AppendChildNodesAction([newBreakNode]));
|
|
2549
|
-
if (this.isCaretPositionAtEnd(splitNode, startOffsetOfNode)) {
|
|
2550
|
-
return this.breakListItemAtEnd(newListItem);
|
|
2551
|
-
}
|
|
2552
|
-
else if (this.isCaretPositionAtStart(splitNode, startOffsetOfNode)) {
|
|
2553
|
-
this.parent.apply(new InsertBlocksBeforeAction(this, newListItem));
|
|
2554
|
-
}
|
|
2555
|
-
else {
|
|
2556
|
-
const splitBlockAction = new SplitBlockWithNodeAction(splitNode, startOffsetOfNode);
|
|
2557
|
-
this.apply(splitBlockAction);
|
|
2558
|
-
return splitBlockAction.newBlock;
|
|
2559
|
-
}
|
|
2560
|
-
return newListItem;
|
|
2561
|
-
}
|
|
2562
|
-
/**
|
|
2563
|
-
* Breaks a list item at the end and handles the insertion of a new list item or paragraph accordingly.
|
|
2564
|
-
*
|
|
2565
|
-
* @param {RTEListItemBlock} newListItem - Item that represents a new list item to be added to the existing list.
|
|
2566
|
-
* @returns {RTEBlock} Returns a `RTEBlock`.
|
|
2567
|
-
*/
|
|
2568
|
-
breakListItemAtEnd(newListItem) {
|
|
2569
|
-
const lastItem = this.parent.blocks[this.parent.blocks.length - 1];
|
|
2570
|
-
const currentItemIsEmpty = this.nodes.length === 1 && this.nodes[0].isEmpty();
|
|
2571
|
-
if (this === lastItem && currentItemIsEmpty) {
|
|
2572
|
-
const parentParent = this.parent.parent;
|
|
2573
|
-
if (parentParent['type'] !== 'list-item') {
|
|
2574
|
-
const newParagraph = RTETextBlock.from({
|
|
2575
|
-
id: generateUUID(),
|
|
2576
|
-
type: 'paragraph',
|
|
2577
|
-
nodes: [],
|
|
2578
|
-
});
|
|
2579
|
-
newParagraph.apply(new AppendChildNodesAction(newListItem.nodes));
|
|
2580
|
-
parentParent.apply(new InsertBlocksAfterAction(this.parent, newParagraph));
|
|
2581
|
-
this.parent.apply(new RemoveChildAction(this));
|
|
2582
|
-
return newParagraph;
|
|
2583
|
-
}
|
|
2584
|
-
else {
|
|
2585
|
-
parentParent.parent.apply(new InsertBlocksAfterAction(parentParent, newListItem));
|
|
2586
|
-
this.parent.apply(new RemoveChildAction(this));
|
|
2587
|
-
}
|
|
2588
|
-
}
|
|
2589
|
-
else {
|
|
2590
|
-
this.parent.apply(new InsertBlocksAfterAction(this, newListItem));
|
|
2591
|
-
}
|
|
2592
|
-
return newListItem;
|
|
2593
|
-
}
|
|
2594
|
-
/**
|
|
2595
|
-
* Delete list node content
|
|
2596
|
-
*
|
|
2597
|
-
* @param {DeleteBlockContentAction} action - Modify action
|
|
2598
|
-
*/
|
|
2599
|
-
deleteListNodeContent(action) {
|
|
2600
|
-
const startContainerNode = action.startContainerNode;
|
|
2601
|
-
const listBlock = startContainerNode.parentBlock.parent;
|
|
2602
|
-
this.deleteNodeContent(action);
|
|
2603
|
-
if (listBlock.blocks.length === 0) {
|
|
2604
|
-
listBlock.parent.apply(new RemoveChildAction(listBlock));
|
|
2605
|
-
}
|
|
2606
|
-
}
|
|
2607
|
-
/**
|
|
2608
|
-
* Copy the inline style to new node
|
|
2609
|
-
*
|
|
2610
|
-
* @param {RTETextNode} needCopedNode - The node that needed to be copied to
|
|
2611
|
-
* @returns {RTETextNode} Returns a `RTETextNode`.
|
|
2612
|
-
*/
|
|
2613
|
-
copyInlineStyleToNewNode(needCopedNode) {
|
|
2614
|
-
const textNode = needCopedNode.cloneWithText('');
|
|
2615
|
-
// The link annotation doesn't need to inherit
|
|
2616
|
-
textNode.annotationMap.delete(NodeAnnotationTypeEnum.LINK);
|
|
2617
|
-
return textNode;
|
|
2618
|
-
}
|
|
2619
|
-
}
|
|
2620
|
-
|
|
2621
|
-
/**
|
|
2622
|
-
* Delete the nest list block action
|
|
2623
|
-
*
|
|
2624
|
-
* @example needRemovedNestList.parent.apply(new RemoveNestListAction(needRemovedNestList))
|
|
2625
|
-
*/
|
|
2626
|
-
class RemoveNestListAction extends ModifyContentAction {
|
|
2627
|
-
constructor(childList) {
|
|
2628
|
-
super();
|
|
2629
|
-
this.type = ModifyContentActionType.DELETE_NEST_LIST;
|
|
2630
|
-
this.nestListBlockToBeRemoved = childList;
|
|
2631
|
-
}
|
|
2632
|
-
}
|
|
2633
|
-
|
|
2634
|
-
/**
|
|
2635
|
-
* List block
|
|
2636
|
-
*/
|
|
2637
|
-
class RTEListBlock extends RTEBlock {
|
|
2638
|
-
constructor(id, type) {
|
|
2639
|
-
super(id);
|
|
2640
|
-
this.type = 'bullet-list';
|
|
2641
|
-
this.blocks = [];
|
|
2642
|
-
this.type = type;
|
|
2643
|
-
}
|
|
2644
|
-
/**
|
|
2645
|
-
* Converts a VegaRTEListBlock object to an RTEListBlock
|
|
2646
|
-
*
|
|
2647
|
-
* @param {VegaRTEListBlock} block - Converts a `VegaRTEListBlock` object into an `RTEListBlock`.
|
|
2648
|
-
* @returns {RTEListBlock} Return an instance of `RTEListBlock`
|
|
2649
|
-
*/
|
|
2650
|
-
static from(block) {
|
|
2651
|
-
const listBlock = new RTEListBlock(block.id, block.type);
|
|
2652
|
-
listBlock.blocks = block.blocks.map((item) => {
|
|
2653
|
-
const listItemBlock = RTEListItemBlock.from(item);
|
|
2654
|
-
listItemBlock.parent = listBlock;
|
|
2655
|
-
return listItemBlock;
|
|
2656
|
-
});
|
|
2657
|
-
return listBlock;
|
|
2658
|
-
}
|
|
2659
|
-
/**
|
|
2660
|
-
* @inheritDoc
|
|
2661
|
-
*/
|
|
2662
|
-
toJSON() {
|
|
2663
|
-
return Object.assign(Object.assign({}, super.toJSON()), { id: this.id, type: this.type, blocks: this.blocks.map((block) => block.toJSON()) });
|
|
2664
|
-
}
|
|
2665
|
-
/**
|
|
2666
|
-
* @inheritDoc
|
|
2667
|
-
*/
|
|
2668
|
-
isNotEmpty() {
|
|
2669
|
-
return (this.blocks.length > 0 &&
|
|
2670
|
-
this.blocks.some((listItemBlock) => listItemBlock.isNotEmpty()));
|
|
2671
|
-
}
|
|
2672
|
-
/**
|
|
2673
|
-
* @inheritDoc
|
|
2674
|
-
*/
|
|
2675
|
-
getLastNode() {
|
|
2676
|
-
return this.blocks[this.blocks.length - 1].getLastNode();
|
|
2677
|
-
}
|
|
2678
|
-
/**
|
|
2679
|
-
* Apply a modify action to block
|
|
2680
|
-
*
|
|
2681
|
-
* @param {ModifyContentAction} action - Modify action
|
|
2682
|
-
*/
|
|
2683
|
-
doModifyActionApply(action) {
|
|
2684
|
-
switch (action.type) {
|
|
2685
|
-
case ModifyContentActionType.DELETE_CHILD:
|
|
2686
|
-
this.removeListItemBlock(action.entityToBeRemoved);
|
|
2687
|
-
break;
|
|
2688
|
-
case ModifyContentActionType.INSERT_BLOCKS_AFTER:
|
|
2689
|
-
this.replaceBlockWithBlocks(action.referBlock, [
|
|
2690
|
-
action.referBlock,
|
|
2691
|
-
...action.blocksToBeInserted,
|
|
2692
|
-
]);
|
|
2693
|
-
break;
|
|
2694
|
-
case ModifyContentActionType.INSERT_BLOCKS_BEFORE:
|
|
2695
|
-
this.replaceBlockWithBlocks(action.referBlock, [
|
|
2696
|
-
...action.blocksToBeInserted,
|
|
2697
|
-
action.referBlock,
|
|
2698
|
-
]);
|
|
2699
|
-
break;
|
|
2700
|
-
case ModifyContentActionType.APPEND_CHILD_NODES:
|
|
2701
|
-
this.appendChildBlocks(action.entityToBeAppended);
|
|
2702
|
-
break;
|
|
2703
|
-
case ModifyContentActionType.TRANSFORM_LIST_BLOCK:
|
|
2704
|
-
this.convertToList(action);
|
|
2705
|
-
break;
|
|
2706
|
-
case ModifyContentActionType.TRANSFORM_PARAGRAPH_BLOCK:
|
|
2707
|
-
this.convertToParagraph(action);
|
|
2708
|
-
break;
|
|
2709
|
-
case ModifyContentActionType.INSERT_IMAGE_TO_BLOCK:
|
|
2710
|
-
this.insertImage(action);
|
|
2711
|
-
break;
|
|
2712
|
-
}
|
|
2713
|
-
}
|
|
2714
|
-
/**
|
|
2715
|
-
* Converts a RTEListItemBlock to a RTETextBlock representing a paragraph.
|
|
2716
|
-
*
|
|
2717
|
-
* @param {RTEListItemBlock} block - The block that will be covered
|
|
2718
|
-
* @returns {RTETextBlock} Returns a `RTETextBlock`.
|
|
2719
|
-
*/
|
|
2720
|
-
toParagraph(block) {
|
|
2721
|
-
const textBlock = new RTETextBlock(generateUUID(), 'paragraph');
|
|
2722
|
-
textBlock.apply(new AppendChildNodesAction(block['nodes']));
|
|
2723
|
-
textBlock['annotationMap'] = block['annotationMap'];
|
|
2724
|
-
return textBlock;
|
|
2725
|
-
}
|
|
2726
|
-
/**
|
|
2727
|
-
* Covert block to List
|
|
2728
|
-
*
|
|
2729
|
-
* @param {TransformListAction} action - Modify action
|
|
2730
|
-
*/
|
|
2731
|
-
convertToList(action) {
|
|
2732
|
-
const selectedBlocks = action.selectedBlocks;
|
|
2733
|
-
const bulletList = this.parent.createList(action.listType);
|
|
2734
|
-
const isSameList = selectedBlocks.every((block) => block.parent === this);
|
|
2735
|
-
if (isSameList) {
|
|
2736
|
-
// Select one or more list items belonging to the same list, and all items in this list should be updated
|
|
2737
|
-
bulletList.apply(new AppendChildNodesAction(this.blocks));
|
|
2738
|
-
this.parent.apply(new InsertBlocksAfterAction(this, bulletList));
|
|
2739
|
-
this.parent.apply(new RemoveChildAction(this));
|
|
2740
|
-
selectedBlocks.forEach((block) => block.nodes.map((node) => node.apply(new SyncUpSelectionAction())));
|
|
2741
|
-
}
|
|
2742
|
-
else {
|
|
2743
|
-
const listItems = action.selectedBlocks.map((block) => this.parent.toListItem(block));
|
|
2744
|
-
bulletList.apply(new AppendChildNodesAction(listItems));
|
|
2745
|
-
this.parent.apply(new InsertBlocksAfterAction(this, bulletList));
|
|
2746
|
-
action.selectedBlocks.forEach((block) => {
|
|
2747
|
-
block.parent.apply(new RemoveChildAction(block));
|
|
2748
|
-
});
|
|
2749
|
-
if (this.blocks.length === 0) {
|
|
2750
|
-
this.parent.apply(new RemoveChildAction(this));
|
|
2751
|
-
}
|
|
2752
|
-
}
|
|
2753
|
-
}
|
|
2754
|
-
/**
|
|
2755
|
-
* Covert block to paragraph
|
|
2756
|
-
*
|
|
2757
|
-
* @param {TransformListAction} action - Modify action
|
|
2758
|
-
*/
|
|
2759
|
-
convertToParagraph(action) {
|
|
2760
|
-
let isSelectedFirstBlock = false;
|
|
2761
|
-
let isSelectedLastBlock = false;
|
|
2762
|
-
const selectedBlocks = action.selectedBlocks;
|
|
2763
|
-
const currentParagraph = selectedBlocks.map((block) => {
|
|
2764
|
-
block.nodes.map((node) => node.apply(new SyncUpSelectionAction()));
|
|
2765
|
-
if (block === this.blocks[0])
|
|
2766
|
-
isSelectedFirstBlock = true;
|
|
2767
|
-
if (block === this.blocks[this.blocks.length - 1])
|
|
2768
|
-
isSelectedLastBlock = true;
|
|
2769
|
-
return this.toParagraph(block);
|
|
2770
|
-
});
|
|
2771
|
-
if (isSelectedFirstBlock) {
|
|
2772
|
-
this.parent.apply(new InsertBlocksBeforeAction(this, ...currentParagraph));
|
|
2773
|
-
}
|
|
2774
|
-
else if (isSelectedLastBlock) {
|
|
2775
|
-
this.parent.apply(new InsertBlocksAfterAction(this, ...currentParagraph));
|
|
2776
|
-
}
|
|
2777
|
-
else {
|
|
2778
|
-
const startIndex = this.blocks.indexOf(selectedBlocks[0]);
|
|
2779
|
-
const lastIndex = this.blocks.indexOf(selectedBlocks[selectedBlocks.length - 1]);
|
|
2780
|
-
const firstBulletList = this.parent.createList(this.type);
|
|
2781
|
-
firstBulletList.apply(new AppendChildNodesAction(this.blocks.slice(0, startIndex)));
|
|
2782
|
-
const lastBulletList = this.parent.createList(this.type);
|
|
2783
|
-
lastBulletList.apply(new AppendChildNodesAction(this.blocks.slice(lastIndex + 1)));
|
|
2784
|
-
this.parent.apply(new InsertBlocksBeforeAction(this, firstBulletList, ...currentParagraph, lastBulletList));
|
|
2785
|
-
this.parent.apply(new RemoveChildAction(this));
|
|
2786
|
-
}
|
|
2787
|
-
selectedBlocks.map((block) => {
|
|
2788
|
-
this.apply(new RemoveChildAction(block));
|
|
2789
|
-
});
|
|
2790
|
-
if (this.blocks.length === 0) {
|
|
2791
|
-
this.parent.apply(new RemoveChildAction(this));
|
|
2792
|
-
}
|
|
2793
|
-
}
|
|
2794
|
-
/**
|
|
2795
|
-
* Inserts an image block into a rich text editor block based on the parent block type.
|
|
2796
|
-
*
|
|
2797
|
-
* @param {InsertImageToBlockAction} action - Modify action
|
|
2798
|
-
*/
|
|
2799
|
-
insertImage(action) {
|
|
2800
|
-
const imageBlock = action.imageBlockToBeInserted;
|
|
2801
|
-
if (this.parent['type'] !== 'list-item') {
|
|
2802
|
-
this.parent.apply(new InsertBlocksAfterAction(this, imageBlock));
|
|
2803
|
-
}
|
|
2804
|
-
else {
|
|
2805
|
-
this.parent.apply(action);
|
|
2806
|
-
}
|
|
2807
|
-
}
|
|
2808
|
-
/**
|
|
2809
|
-
* Removes a specified block and handles the removal of nested lists if necessary.
|
|
2810
|
-
*
|
|
2811
|
-
* @param {RTEBlock} blockToBeRemoved - block that will be removed
|
|
2812
|
-
*/
|
|
2813
|
-
removeListItemBlock(blockToBeRemoved) {
|
|
2814
|
-
super.removeChildBlock(blockToBeRemoved);
|
|
2815
|
-
if (this.blocks.length === 0 && this.parent) {
|
|
2816
|
-
// The parent is a list item mean the current block is a nest list, so we need to use RemoveNestListAction to remove the item
|
|
2817
|
-
if (this.parent instanceof RTEListItemBlock) {
|
|
2818
|
-
this.parent.apply(new RemoveNestListAction(this));
|
|
2819
|
-
}
|
|
2820
|
-
else {
|
|
2821
|
-
this.parent.apply(new RemoveChildAction(this));
|
|
2822
|
-
}
|
|
2823
|
-
}
|
|
2824
|
-
}
|
|
2825
|
-
}
|
|
2826
|
-
|
|
2827
|
-
/**
|
|
2828
|
-
* Class representing the content state of the rich text editor.
|
|
2829
|
-
*/
|
|
2830
|
-
class VegaRTEContent extends BlockBaseOperator {
|
|
2831
|
-
constructor(blocks) {
|
|
2832
|
-
super();
|
|
2833
|
-
blocks.forEach((block) => {
|
|
2834
|
-
block.parent = this;
|
|
2835
|
-
});
|
|
2836
|
-
this.blocks = blocks;
|
|
2837
|
-
}
|
|
2838
|
-
/**
|
|
2839
|
-
* Converts a JSON array of blocks to a class array of RTEContentBlock.
|
|
2840
|
-
*
|
|
2841
|
-
* @param {VegaRTEContentBlock[]} value The JSON array of blocks to convert.
|
|
2842
|
-
* @returns {RTEContentBlock[]} The converted array of RTEContentBlock.
|
|
2843
|
-
*/
|
|
2844
|
-
static fromJSON(value) {
|
|
2845
|
-
const blocks = value.map((block) => {
|
|
2846
|
-
switch (block.type) {
|
|
2847
|
-
case 'paragraph':
|
|
2848
|
-
case 'title':
|
|
2849
|
-
case 'subtitle':
|
|
2850
|
-
case 'heading-1':
|
|
2851
|
-
case 'heading-2':
|
|
2852
|
-
case 'heading-3': {
|
|
2853
|
-
return RTETextBlock.from(block);
|
|
2854
|
-
}
|
|
2855
|
-
case 'image':
|
|
2856
|
-
return RTEImageBlock.from(block);
|
|
2857
|
-
case 'bullet-list':
|
|
2858
|
-
case 'number-list':
|
|
2859
|
-
return RTEListBlock.from(block);
|
|
2860
|
-
default: {
|
|
2861
|
-
throw new Error(`[Vega] Unknown block type: ${block.type}`);
|
|
2862
|
-
}
|
|
2863
|
-
}
|
|
2864
|
-
});
|
|
2865
|
-
return new VegaRTEContent(blocks);
|
|
2866
|
-
}
|
|
2867
|
-
/**
|
|
2868
|
-
* Create an empty content state
|
|
2869
|
-
*
|
|
2870
|
-
* @returns {VegaRTEContent} An empty content state
|
|
2871
|
-
*/
|
|
2872
|
-
static createEmptyContent() {
|
|
2873
|
-
return VegaRTEContent.fromJSON([
|
|
2874
|
-
{
|
|
2875
|
-
id: generateUUID(),
|
|
2876
|
-
type: 'paragraph',
|
|
2877
|
-
nodes: [
|
|
2878
|
-
{
|
|
2879
|
-
id: generateUUID(),
|
|
2880
|
-
type: 'text',
|
|
2881
|
-
text: '',
|
|
2882
|
-
},
|
|
2883
|
-
],
|
|
2884
|
-
},
|
|
2885
|
-
]);
|
|
2886
|
-
}
|
|
2887
|
-
/**
|
|
2888
|
-
* Clones the content state.
|
|
2889
|
-
*
|
|
2890
|
-
* @returns {VegaRTEContent} The cloned content state.
|
|
2891
|
-
*/
|
|
2892
|
-
clone() {
|
|
2893
|
-
return new VegaRTEContent([...this.blocks]);
|
|
2894
|
-
}
|
|
2895
|
-
/**
|
|
2896
|
-
* Converts the content state to a JSON array of blocks.
|
|
2897
|
-
*
|
|
2898
|
-
* @returns {VegaRTEContentBlock[]} The JSON array of blocks.
|
|
2899
|
-
*/
|
|
2900
|
-
toJSON() {
|
|
2901
|
-
return this.blocks.map((block) => block.toJSON());
|
|
2902
|
-
}
|
|
2903
|
-
/**
|
|
2904
|
-
* Internal method to add the block item, remove the block item
|
|
2905
|
-
*
|
|
2906
|
-
* @param {ModifyContentAction} action - Modify content action
|
|
2907
|
-
*/
|
|
2908
|
-
apply(action) {
|
|
2909
|
-
switch (action.type) {
|
|
2910
|
-
case ModifyContentActionType.DELETE_CHILD:
|
|
2911
|
-
this.removeChildBlock(action.entityToBeRemoved);
|
|
2912
|
-
break;
|
|
2913
|
-
case ModifyContentActionType.APPEND_CHILD_NODES:
|
|
2914
|
-
this.appendChildBlocks(action.entityToBeAppended);
|
|
2915
|
-
break;
|
|
2916
|
-
case ModifyContentActionType.INSERT_BLOCKS_AFTER:
|
|
2917
|
-
this.replaceBlockWithBlocks(action.referBlock, [
|
|
2918
|
-
action.referBlock,
|
|
2919
|
-
...action.blocksToBeInserted,
|
|
2920
|
-
]);
|
|
2921
|
-
break;
|
|
2922
|
-
case ModifyContentActionType.INSERT_BLOCKS_BEFORE:
|
|
2923
|
-
this.replaceBlockWithBlocks(action.referBlock, [
|
|
2924
|
-
...action.blocksToBeInserted,
|
|
2925
|
-
action.referBlock,
|
|
2926
|
-
]);
|
|
2927
|
-
break;
|
|
2928
|
-
}
|
|
2929
|
-
}
|
|
2930
|
-
/**
|
|
2931
|
-
* Convert text to list.
|
|
2932
|
-
*
|
|
2933
|
-
* @param {RTETextBlock} block - block
|
|
2934
|
-
* @returns {RTEListItemBlock} list item block dto.
|
|
2935
|
-
*/
|
|
2936
|
-
toListItem(block) {
|
|
2937
|
-
block.nodes.map((node) => node.apply(new SyncUpSelectionAction()));
|
|
2938
|
-
const listItemBlock = new RTEListItemBlock(generateUUID());
|
|
2939
|
-
listItemBlock.apply(new AppendChildNodesAction(block['nodes']));
|
|
2940
|
-
listItemBlock['annotationMap'] = block['annotationMap'];
|
|
2941
|
-
return listItemBlock;
|
|
2942
|
-
}
|
|
2943
|
-
/**
|
|
2944
|
-
* create list.
|
|
2945
|
-
*
|
|
2946
|
-
* @param {ListType} type - type
|
|
2947
|
-
* @returns {RTEListBlock} list block dto.
|
|
2948
|
-
*/
|
|
2949
|
-
createList(type) {
|
|
2950
|
-
return new RTEListBlock(generateUUID(), type);
|
|
2951
|
-
}
|
|
2952
|
-
}
|
|
2953
|
-
|
|
2954
|
-
export { AnnotationAction as A, BoldAnnotationAction as B, ClearFormattingAnnotationAction as C, HorizontalAlignmentAnnotation as H, ImageAnnotation as I, LinkAnnotationAction as L, MergeTwoBlocksNodesAction as M, RTETextBlock as R, StrikethroughAnnotation as S, TextSplittableAction as T, UnderlineAnnotation as U, VegaRTEContent as V, ZERO_WIDTH_SPACE as Z, RTEImageBlock as a, RTEListItemBlock as b, RTEListBlock as c, RTEBlock as d, RTEImageNode as e, RTETextNode as f, TextColorAnnotation as g, RTE_TEXT_COLORS as h, ItalicAnnotation as i, TextStyleAnnotationAction as j, TextStyleAnnotation as k, BoldAnnotation as l, CodeAnnotationAction as m, SelectionRangeAnnotation as n, IndentAnnotation as o, AppendChildNodesAction as p, UpdateTextAction as q, SplitBlockWithNodeAction as r, RemoveChildAction as s, ReplaceChildNodesAction as t, InsertBlocksBeforeAction as u, InsertBlocksAfterAction as v };
|