@opentiny/fluent-editor 4.0.0-alpha.14 → 4.0.0-alpha.16
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/README.md +88 -88
- package/es/attributors/line-height.es.js.map +1 -1
- package/es/config/base64-image.es.js.map +1 -1
- package/es/config/editor.config.es.js +27 -0
- package/es/config/editor.config.es.js.map +1 -1
- package/es/config/editor.utils.es.js.map +1 -1
- package/es/config/i18n/en-us.es.js.map +1 -1
- package/es/config/i18n/zh-cn.es.js.map +1 -1
- package/es/config/index.es.js +3 -1
- package/es/config/index.es.js.map +1 -1
- package/es/core/fluent-editor.es.js.map +1 -1
- package/es/fluent-editor.es.js.map +1 -1
- package/es/formats/emoji.es.js.map +1 -1
- package/es/formats/soft-break.es.js.map +1 -1
- package/es/formats/strike.es.js.map +1 -1
- package/es/formats/video.es.js.map +1 -1
- package/es/index.es.js +31 -2
- package/es/index.es.js.map +1 -1
- package/es/modules/ai/constants.es.js.map +1 -1
- package/es/modules/ai/icons.es.js.map +1 -1
- package/es/modules/ai/index.es.js.map +1 -1
- package/es/modules/collaborative-editing/awareness/awareness.es.js.map +1 -1
- package/es/modules/collaborative-editing/awareness/y-indexeddb.es.js.map +1 -1
- package/es/modules/collaborative-editing/collaborative-editing.es.js.map +1 -1
- package/es/modules/collaborative-editing/module.es.js.map +1 -1
- package/es/modules/collaborative-editing/provider/providerRegistry.es.js.map +1 -1
- package/es/modules/collaborative-editing/provider/webrtc.es.js.map +1 -1
- package/es/modules/collaborative-editing/provider/websocket.es.js.map +1 -1
- package/es/modules/counter.es.js.map +1 -1
- package/es/modules/custom-clipboard.es.js.map +1 -1
- package/es/modules/custom-image/actions/action.es.js.map +1 -1
- package/es/modules/custom-image/actions/custom-resize-action.es.js.map +1 -1
- package/es/modules/custom-image/actions/delete-action.es.js.map +1 -1
- package/es/modules/custom-image/blot-formatter.es.js.map +1 -1
- package/es/modules/custom-image/image.es.js.map +1 -1
- package/es/modules/custom-image/options.es.js.map +1 -1
- package/es/modules/custom-image/specs/blot-spec.es.js.map +1 -1
- package/es/modules/custom-image/specs/custom-image-spec.es.js.map +1 -1
- package/es/modules/custom-image/specs/image-spec.es.js.map +1 -1
- package/es/modules/divider.es.js.map +1 -1
- package/es/modules/emoji.es.js.map +1 -1
- package/es/modules/file/formats/file.es.js.map +1 -1
- package/es/modules/file/modules/file-bar.es.js.map +1 -1
- package/es/modules/file/modules/file-module.es.js.map +1 -1
- package/es/modules/flow-chart/config-utils.es.js.map +1 -1
- package/es/modules/flow-chart/formats/flow-chart-blot.es.js.map +1 -1
- package/es/modules/flow-chart/i18n/en-us.es.js.map +1 -1
- package/es/modules/flow-chart/i18n/index.es.js.map +1 -1
- package/es/modules/flow-chart/i18n/zh-cn.es.js.map +1 -1
- package/es/modules/flow-chart/icons.es.js.map +1 -1
- package/es/modules/flow-chart/index.es.js.map +1 -1
- package/es/modules/flow-chart/modules/context-menu.es.js.map +1 -1
- package/es/modules/flow-chart/modules/control-panel.es.js.map +1 -1
- package/es/modules/flow-chart/modules/custom-resize-action.es.js.map +1 -1
- package/es/modules/link/formats/link.es.js.map +1 -1
- package/es/modules/link/modules/tooltip.es.js.map +1 -1
- package/es/modules/mathlive/formats.es.js.map +1 -1
- package/es/modules/mathlive/tooltip.es.js.map +1 -1
- package/es/modules/mention/constants.es.js.map +1 -1
- package/es/modules/mention/mention-link.es.js.map +1 -1
- package/es/modules/mention/mention.es.js.map +1 -1
- package/es/modules/mind-map/config-utils.es.js.map +1 -1
- package/es/modules/mind-map/formats/mind-map-blot.es.js.map +1 -1
- package/es/modules/mind-map/i18n/en-us.es.js.map +1 -1
- package/es/modules/mind-map/i18n/index.es.js.map +1 -1
- package/es/modules/mind-map/i18n/zh-cn.es.js.map +1 -1
- package/es/modules/mind-map/icons.es.js.map +1 -1
- package/es/modules/mind-map/index.es.js.map +1 -1
- package/es/modules/mind-map/modules/context-menu.es.js.map +1 -1
- package/es/modules/mind-map/modules/control-panel.es.js.map +1 -1
- package/es/modules/mind-map/modules/custom-resize-action.es.js.map +1 -1
- package/es/modules/syntax.es.js.map +1 -1
- package/es/modules/toolbar/better-picker.es.js.map +1 -1
- package/es/themes/snow.es.js.map +1 -1
- package/es/tools/screenshot.es.js.map +1 -1
- package/es/ui/icons.config.es.js.map +1 -1
- package/es/ui/icons.es.js.map +1 -1
- package/es/utils/debounce.es.js.map +1 -1
- package/es/utils/merge.es.js.map +1 -1
- package/es/utils/method.es.js.map +1 -1
- package/lib/attributors/line-height.cjs.js.map +1 -1
- package/lib/config/base64-image.cjs.js.map +1 -1
- package/lib/config/editor.config.cjs.js +27 -0
- package/lib/config/editor.config.cjs.js.map +1 -1
- package/lib/config/editor.utils.cjs.js.map +1 -1
- package/lib/config/i18n/en-us.cjs.js.map +1 -1
- package/lib/config/i18n/zh-cn.cjs.js.map +1 -1
- package/lib/config/index.cjs.js +2 -0
- package/lib/config/index.cjs.js.map +1 -1
- package/lib/core/fluent-editor.cjs.js.map +1 -1
- package/lib/fluent-editor.cjs.js.map +1 -1
- package/lib/formats/emoji.cjs.js.map +1 -1
- package/lib/formats/soft-break.cjs.js.map +1 -1
- package/lib/formats/strike.cjs.js.map +1 -1
- package/lib/formats/video.cjs.js.map +1 -1
- package/lib/index.cjs.js +39 -10
- package/lib/index.cjs.js.map +1 -1
- package/lib/modules/ai/constants.cjs.js.map +1 -1
- package/lib/modules/ai/icons.cjs.js.map +1 -1
- package/lib/modules/ai/index.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/awareness/awareness.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/awareness/y-indexeddb.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/collaborative-editing.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/module.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/provider/providerRegistry.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/provider/webrtc.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/provider/websocket.cjs.js.map +1 -1
- package/lib/modules/counter.cjs.js.map +1 -1
- package/lib/modules/custom-clipboard.cjs.js.map +1 -1
- package/lib/modules/custom-image/actions/action.cjs.js.map +1 -1
- package/lib/modules/custom-image/actions/custom-resize-action.cjs.js.map +1 -1
- package/lib/modules/custom-image/actions/delete-action.cjs.js.map +1 -1
- package/lib/modules/custom-image/blot-formatter.cjs.js.map +1 -1
- package/lib/modules/custom-image/image.cjs.js.map +1 -1
- package/lib/modules/custom-image/options.cjs.js.map +1 -1
- package/lib/modules/custom-image/specs/blot-spec.cjs.js.map +1 -1
- package/lib/modules/custom-image/specs/custom-image-spec.cjs.js.map +1 -1
- package/lib/modules/custom-image/specs/image-spec.cjs.js.map +1 -1
- package/lib/modules/divider.cjs.js.map +1 -1
- package/lib/modules/emoji.cjs.js.map +1 -1
- package/lib/modules/file/formats/file.cjs.js.map +1 -1
- package/lib/modules/file/modules/file-bar.cjs.js.map +1 -1
- package/lib/modules/file/modules/file-module.cjs.js.map +1 -1
- package/lib/modules/flow-chart/config-utils.cjs.js.map +1 -1
- package/lib/modules/flow-chart/formats/flow-chart-blot.cjs.js.map +1 -1
- package/lib/modules/flow-chart/i18n/en-us.cjs.js.map +1 -1
- package/lib/modules/flow-chart/i18n/index.cjs.js.map +1 -1
- package/lib/modules/flow-chart/i18n/zh-cn.cjs.js.map +1 -1
- package/lib/modules/flow-chart/icons.cjs.js.map +1 -1
- package/lib/modules/flow-chart/index.cjs.js.map +1 -1
- package/lib/modules/flow-chart/modules/context-menu.cjs.js.map +1 -1
- package/lib/modules/flow-chart/modules/control-panel.cjs.js.map +1 -1
- package/lib/modules/flow-chart/modules/custom-resize-action.cjs.js.map +1 -1
- package/lib/modules/link/formats/link.cjs.js.map +1 -1
- package/lib/modules/link/modules/tooltip.cjs.js.map +1 -1
- package/lib/modules/mathlive/formats.cjs.js.map +1 -1
- package/lib/modules/mathlive/tooltip.cjs.js.map +1 -1
- package/lib/modules/mention/constants.cjs.js.map +1 -1
- package/lib/modules/mention/mention-link.cjs.js.map +1 -1
- package/lib/modules/mention/mention.cjs.js.map +1 -1
- package/lib/modules/mind-map/config-utils.cjs.js.map +1 -1
- package/lib/modules/mind-map/formats/mind-map-blot.cjs.js.map +1 -1
- package/lib/modules/mind-map/i18n/en-us.cjs.js.map +1 -1
- package/lib/modules/mind-map/i18n/index.cjs.js.map +1 -1
- package/lib/modules/mind-map/i18n/zh-cn.cjs.js.map +1 -1
- package/lib/modules/mind-map/icons.cjs.js.map +1 -1
- package/lib/modules/mind-map/index.cjs.js.map +1 -1
- package/lib/modules/mind-map/modules/context-menu.cjs.js.map +1 -1
- package/lib/modules/mind-map/modules/control-panel.cjs.js.map +1 -1
- package/lib/modules/mind-map/modules/custom-resize-action.cjs.js.map +1 -1
- package/lib/modules/syntax.cjs.js.map +1 -1
- package/lib/modules/toolbar/better-picker.cjs.js.map +1 -1
- package/lib/themes/snow.cjs.js.map +1 -1
- package/lib/tools/screenshot.cjs.js.map +1 -1
- package/lib/ui/icons.cjs.js.map +1 -1
- package/lib/ui/icons.config.cjs.js.map +1 -1
- package/lib/utils/debounce.cjs.js.map +1 -1
- package/lib/utils/merge.cjs.js.map +1 -1
- package/lib/utils/method.cjs.js.map +1 -1
- package/package.json +1 -1
- package/patches/quill@2.0.3.patch +33 -33
- package/scripts/apply-patches.cjs +248 -248
- package/style.css +1 -1
- package/types/attributors/font-size.d.ts +1 -1
- package/types/attributors/font-style.d.ts +1 -1
- package/types/attributors/index.d.ts +4 -4
- package/types/attributors/line-height.d.ts +1 -1
- package/types/attributors/text-indent.d.ts +1 -1
- package/types/config/base64-image.d.ts +2 -2
- package/types/config/editor.config.d.ts +55 -11
- package/types/config/editor.utils.d.ts +40 -40
- package/types/config/i18n/en-us.d.ts +125 -125
- package/types/config/i18n/zh-cn.d.ts +125 -125
- package/types/config/index.d.ts +7 -7
- package/types/config/types/editor-config.interface.d.ts +11 -12
- package/types/config/types/editor-modules.interface.d.ts +38 -39
- package/types/config/types/index.d.ts +3 -3
- package/types/config/types/type.d.ts +2 -2
- package/types/core/fluent-editor.d.ts +10 -11
- package/types/fluent-editor.d.ts +1 -2
- package/types/formats/emoji.d.ts +7 -8
- package/types/formats/index.d.ts +4 -4
- package/types/formats/soft-break.d.ts +11 -12
- package/types/formats/strike.d.ts +7 -8
- package/types/formats/video.d.ts +12 -13
- package/types/index.d.ts +7 -8
- package/types/modules/ai/constants.d.ts +30 -30
- package/types/modules/ai/icons.d.ts +21 -21
- package/types/modules/ai/index.d.ts +93 -94
- package/types/modules/ai/types.d.ts +16 -16
- package/types/modules/collaborative-editing/awareness/awareness.d.ts +25 -26
- package/types/modules/collaborative-editing/awareness/index.d.ts +2 -2
- package/types/modules/collaborative-editing/awareness/y-indexeddb.d.ts +2 -3
- package/types/modules/collaborative-editing/collaborative-editing.d.ts +20 -21
- package/types/modules/collaborative-editing/index.d.ts +2 -2
- package/types/modules/collaborative-editing/module.d.ts +10 -11
- package/types/modules/collaborative-editing/provider/index.d.ts +3 -3
- package/types/modules/collaborative-editing/provider/providerRegistry.d.ts +24 -25
- package/types/modules/collaborative-editing/provider/webrtc.d.ts +33 -34
- package/types/modules/collaborative-editing/provider/websocket.d.ts +37 -38
- package/types/modules/collaborative-editing/types.d.ts +45 -46
- package/types/modules/counter.d.ts +21 -22
- package/types/modules/custom-clipboard.d.ts +23 -24
- package/types/modules/custom-image/actions/{Action.d.ts → action.d.ts} +7 -8
- package/types/modules/custom-image/actions/custom-resize-action.d.ts +22 -23
- package/types/modules/custom-image/actions/delete-action.d.ts +5 -6
- package/types/modules/custom-image/actions/image-toolbar-buttons.d.ts +15 -16
- package/types/modules/custom-image/actions/index.d.ts +6 -6
- package/types/modules/custom-image/actions/toolbar-action.d.ts +7 -8
- package/types/modules/custom-image/actions/toolbar.d.ts +16 -17
- package/types/modules/custom-image/blot-formatter.d.ts +19 -20
- package/types/modules/custom-image/image.d.ts +26 -27
- package/types/modules/custom-image/index.d.ts +4 -4
- package/types/modules/custom-image/{Options.d.ts → options.d.ts} +45 -46
- package/types/modules/custom-image/specs/blot-spec.d.ts +10 -11
- package/types/modules/custom-image/specs/custom-image-spec.d.ts +15 -16
- package/types/modules/custom-image/specs/image-spec.d.ts +7 -8
- package/types/modules/custom-image/specs/index.d.ts +3 -3
- package/types/modules/custom-uploader.d.ts +37 -38
- package/types/modules/divider.d.ts +7 -8
- package/types/modules/emoji.d.ts +35 -36
- package/types/modules/file/formats/file.d.ts +17 -18
- package/types/modules/file/index.d.ts +3 -3
- package/types/modules/file/modules/file-bar.d.ts +14 -14
- package/types/modules/file/modules/file-module.d.ts +7 -8
- package/types/modules/flow-chart/config-utils.d.ts +9 -10
- package/types/modules/flow-chart/formats/flow-chart-blot.d.ts +40 -41
- package/types/modules/flow-chart/i18n/en-us.d.ts +26 -26
- package/types/modules/flow-chart/i18n/index.d.ts +1 -1
- package/types/modules/flow-chart/i18n/zh-cn.d.ts +26 -26
- package/types/modules/flow-chart/icons.d.ts +12 -12
- package/types/modules/flow-chart/index.d.ts +8 -9
- package/types/modules/flow-chart/modules/context-menu.d.ts +1 -2
- package/types/modules/flow-chart/modules/control-panel.d.ts +1 -2
- package/types/modules/flow-chart/modules/custom-resize-action.d.ts +22 -22
- package/types/modules/flow-chart/options.d.ts +29 -29
- package/types/modules/i18n.d.ts +13 -14
- package/types/modules/index.d.ts +18 -18
- package/types/modules/link/formats/link.d.ts +14 -15
- package/types/modules/link/index.d.ts +2 -2
- package/types/modules/link/modules/tooltip.d.ts +25 -26
- package/types/modules/mathlive/formats.d.ts +20 -21
- package/types/modules/mathlive/index.d.ts +3 -3
- package/types/modules/mathlive/module.d.ts +7 -8
- package/types/modules/mathlive/tooltip.d.ts +14 -15
- package/types/modules/mention/constants.d.ts +3 -3
- package/types/modules/mention/index.d.ts +2 -2
- package/types/modules/mention/mention-link.d.ts +14 -15
- package/types/modules/mention/{Mention.d.ts → mention.d.ts} +52 -53
- package/types/modules/mind-map/config-utils.d.ts +11 -12
- package/types/modules/mind-map/formats/mind-map-blot.d.ts +41 -42
- package/types/modules/mind-map/i18n/en-us.d.ts +25 -25
- package/types/modules/mind-map/i18n/index.d.ts +1 -1
- package/types/modules/mind-map/i18n/zh-cn.d.ts +25 -25
- package/types/modules/mind-map/icons.d.ts +21 -21
- package/types/modules/mind-map/index.d.ts +8 -9
- package/types/modules/mind-map/modules/context-menu.d.ts +1 -2
- package/types/modules/mind-map/modules/control-panel.d.ts +1 -2
- package/types/modules/mind-map/modules/custom-resize-action.d.ts +23 -23
- package/types/modules/mind-map/options.d.ts +27 -27
- package/types/modules/shortcut-key/index.d.ts +67 -68
- package/types/modules/syntax.d.ts +12 -13
- package/types/modules/table-up/index.d.ts +32 -33
- package/types/modules/toolbar/better-picker.d.ts +13 -14
- package/types/modules/toolbar/better-toolbar.d.ts +6 -7
- package/types/modules/toolbar/index.d.ts +3 -3
- package/types/modules/toolbar/toolbar-tip.d.ts +7 -8
- package/types/themes/snow.d.ts +9 -10
- package/types/tools/format-painter.d.ts +12 -13
- package/types/tools/fullscreen.d.ts +4 -5
- package/types/tools/screenshot.d.ts +17 -18
- package/types/ui/icons.config.d.ts +40 -40
- package/types/ui/icons.d.ts +6 -6
- package/types/utils/debounce.d.ts +6 -6
- package/types/utils/image.d.ts +1 -1
- package/types/utils/is.d.ts +6 -6
- package/types/utils/merge.d.ts +7 -7
- package/types/utils/method.d.ts +6 -6
- package/types/utils/scroll-lock.d.ts +6 -6
- package/types/config/types/additional-toolbar-item.interface.d.ts +0 -8
- package/types/config/types/content-change.interface.d.ts +0 -13
- package/types/config/types/content-save.interface.d.ts +0 -6
- package/types/config/types/counter-option.interface.d.ts +0 -9
- package/types/config/types/editor-toolbar.interface.d.ts +0 -6
- package/types/config/types/file-operation.interface.d.ts +0 -12
- package/types/config/types/focus-change.interface.d.ts +0 -4
- package/types/config/types/fullscreen-module.interface.d.ts +0 -4
- package/types/config/types/help-panel-item.interface.d.ts +0 -5
- package/types/config/types/help-panel-option.interface.d.ts +0 -7
- package/types/config/types/image-module.interface.d.ts +0 -3
- package/types/config/types/image-upload.interface.d.ts +0 -7
- package/types/config/types/load-on-demand-module.interface.d.ts +0 -5
- package/types/config/types/mention-module.interface.d.ts +0 -8
- package/types/config/types/paste-change.interface.d.ts +0 -6
- package/types/config/types/quick-menu-module.interface.d.ts +0 -3
- package/types/config/types/range.interface.d.ts +0 -4
- package/types/config/types/registry-options.interface.d.ts +0 -5
- package/types/config/types/selection-change.interface.d.ts +0 -8
- package/types/config/types/toolbar-item.interface.d.ts +0 -13
- package/types/config/types/validate-error.interface.d.ts +0 -13
- package/types/modules/custom-image/BlotFormatter.d.ts +0 -29
- package/types/modules/custom-image/actions/CustomResizeAction.d.ts +0 -24
- package/types/modules/custom-image/actions/DeleteAction.d.ts +0 -7
- package/types/modules/custom-image/image-bar.d.ts +0 -15
- package/types/modules/custom-image/specs/BlotSpec.d.ts +0 -13
- package/types/modules/custom-image/specs/CustomImageSpec.d.ts +0 -21
- package/types/modules/custom-image/specs/ImageSpec.d.ts +0 -10
- package/types/modules/emoji/emoji-list/index.d.ts +0 -1
- package/types/modules/emoji/emoji-list/people.d.ts +0 -1
- package/types/modules/emoji/emoji-list.d.ts +0 -2
- package/types/modules/emoji/emoji-map.d.ts +0 -2
- package/types/modules/emoji/emoji-sprite.d.ts +0 -1
- package/types/modules/emoji/formats/emoji-blot.d.ts +0 -13
- package/types/modules/emoji/index.d.ts +0 -10
- package/types/modules/emoji/modules/emoji.d.ts +0 -38
- package/types/modules/emoji/modules/toolbar-emoji.d.ts +0 -8
- package/types/modules/emoji/utils.d.ts +0 -1
- package/types/modules/global-link/constants.d.ts +0 -3
- package/types/modules/global-link/formats/customer-widget-link.d.ts +0 -14
- package/types/modules/global-link/formats/doc-link.d.ts +0 -17
- package/types/modules/global-link/formats/wiki-link.d.ts +0 -16
- package/types/modules/global-link/formats/work-item-link.d.ts +0 -16
- package/types/modules/global-link/global-link-panel.d.ts +0 -19
- package/types/modules/global-link/index.d.ts +0 -18
- package/types/modules/global-link/utils/createTable.d.ts +0 -1
- package/types/modules/mention/MentionLink.d.ts +0 -16
- package/types/modules/quick-menu.d.ts +0 -22
- package/types/modules/table/better-table.d.ts +0 -35
- package/types/modules/table/formats/header.d.ts +0 -23
- package/types/modules/table/formats/list.d.ts +0 -34
- package/types/modules/table/formats/table.d.ts +0 -147
- package/types/modules/table/modules/table-column-tool.d.ts +0 -23
- package/types/modules/table/modules/table-operation-menu.d.ts +0 -38
- package/types/modules/table/modules/table-scroll-bar.d.ts +0 -33
- package/types/modules/table/modules/table-selection.d.ts +0 -37
- package/types/modules/table/modules/table-selector.d.ts +0 -22
- package/types/modules/table/table-config.d.ts +0 -38
- package/types/modules/table/utils/index.d.ts +0 -17
- package/types/modules/table/utils/node-matchers.d.ts +0 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"awareness.es.js","sources":["../../../../../src/modules/collaborative-editing/awareness/awareness.ts"],"sourcesContent":["import type QuillCursors from 'quill-cursors'\
|
|
1
|
+
{"version":3,"file":"awareness.es.js","sources":["../../../../../src/modules/collaborative-editing/awareness/awareness.ts"],"sourcesContent":["import type QuillCursors from 'quill-cursors'\nimport type { Awareness } from 'y-protocols/awareness'\nimport type * as Y from 'yjs'\nimport type FluentEditor from '../../../core/fluent-editor'\n\nexport interface AwarenessState {\n name?: string\n color?: string\n}\n\nexport interface AwarenessEvents {\n change?: (changes: { added: number[], updated: number[], removed: number[] }, transactionOrigin: any) => void\n update?: ({ added, updated, removed }: { added: number[], updated: number[], removed: number[] }, origin: any) => void\n destroy?: () => void\n}\n\nexport interface AwarenessOptions {\n state?: AwarenessState\n events?: AwarenessEvents\n timeout?: number | undefined\n}\n\nexport function setupAwareness(options?: AwarenessOptions, defaultAwareness?: Awareness): Awareness | null {\n if (!defaultAwareness) return null\n\n const awareness = defaultAwareness\n\n if (options?.state) {\n awareness.setLocalStateField('user', options.state)\n }\n\n return awareness\n}\n\nexport function bindAwarenessToCursors(\n awareness: Awareness,\n cursorsModule: QuillCursors,\n quill: FluentEditor,\n yText: Y.Text,\n Yjs: typeof Y,\n): (() => void) | void {\n if (!cursorsModule || !awareness) return\n\n const doc = yText.doc!\n\n const updateCursor = (clientId: number, state: any) => {\n try {\n if (state?.cursor && clientId !== awareness.clientID) {\n const user = state.user || {}\n const color = user.color || '#ff6b6b'\n const name = user.name || `User ${clientId}`\n\n cursorsModule.createCursor(clientId.toString(), name, color)\n\n const anchor = Yjs.createAbsolutePositionFromRelativePosition(Yjs.createRelativePositionFromJSON(state.cursor.anchor), doc)\n const head = Yjs.createAbsolutePositionFromRelativePosition(Yjs.createRelativePositionFromJSON(state.cursor.head), doc)\n\n if (anchor && head && anchor.type === yText && clientId) {\n setTimeout(() => {\n cursorsModule.moveCursor(clientId.toString(), {\n index: anchor.index,\n length: head.index - anchor.index,\n })\n }, 0)\n }\n }\n else {\n cursorsModule.removeCursor(clientId.toString())\n }\n }\n catch (err) {\n console.error('Cursor update failed:', err)\n }\n }\n\n const selectionChangeHandler = (range: { index: number, length: number } | null) => {\n setTimeout(() => {\n if (range) {\n const anchor = Yjs.createRelativePositionFromTypeIndex(yText, range.index)\n const head = Yjs.createRelativePositionFromTypeIndex(yText, range.index + range.length)\n\n const currentState = awareness.getLocalState()\n if (!currentState?.cursor\n || !Yjs.compareRelativePositions(anchor, currentState.cursor.anchor)\n || !Yjs.compareRelativePositions(head, currentState.cursor.head)) {\n awareness.setLocalStateField('cursor', { anchor, head })\n }\n }\n else {\n if (awareness.getLocalState()?.cursor !== null) {\n awareness.setLocalStateField('cursor', null)\n }\n }\n }, 0)\n }\n\n const changeHandler = ({ added, updated, removed }: {\n added: number[]\n updated: number[]\n removed: number[]\n }) => {\n if (quill.composition.isComposing) return\n const states = awareness.getStates()\n\n added.forEach((id) => {\n updateCursor(id, states.get(id))\n })\n\n updated.forEach((id) => {\n updateCursor(id, states.get(id))\n })\n\n removed.forEach((id) => {\n cursorsModule.removeCursor(id.toString())\n })\n }\n\n awareness.on('change', changeHandler)\n quill.on('editor-change', (eventName, ...args) => {\n if (quill.composition.isComposing) return\n if (eventName === 'text-change') {\n if (args[2] === 'user') {\n const range = quill.getSelection()\n selectionChangeHandler(range)\n }\n }\n else if (eventName === 'selection-change') {\n if (args[2] === 'user') {\n selectionChangeHandler(args[0] as { index: number, length: number } | null)\n }\n }\n })\n\n awareness.getStates().forEach((state, clientId) => {\n updateCursor(clientId, state)\n })\n\n return () => {\n awareness.off('change', changeHandler)\n quill.off('editor-change', selectionChangeHandler)\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"y-indexeddb.es.js","sources":["../../../../../src/modules/collaborative-editing/awareness/y-indexeddb.ts"],"sourcesContent":["import type { IndexeddbPersistence } from 'y-indexeddb'\
|
|
1
|
+
{"version":3,"file":"y-indexeddb.es.js","sources":["../../../../../src/modules/collaborative-editing/awareness/y-indexeddb.ts"],"sourcesContent":["import type { IndexeddbPersistence } from 'y-indexeddb'\nimport type * as Y from 'yjs'\n\nexport function setupIndexedDB(doc: Y.Doc, IndexeddbPersistenceClass?: typeof IndexeddbPersistence): () => void {\n if (!IndexeddbPersistenceClass) {\n console.warn('[yjs] IndexeddbPersistence not provided, offline support disabled')\n return () => {}\n }\n\n const fullDbName = `tiny-editor-${doc.guid}`\n\n new IndexeddbPersistenceClass(fullDbName, doc)\n\n return (): void => {\n indexedDB.deleteDatabase(fullDbName)\n }\n}\n"],"names":[],"mappings":"AAGO,SAAS,eAAe,KAAY,2BAAqE;AAC9G,MAAI,CAAC,2BAA2B;AAC9B,YAAQ,KAAK,mEAAmE;AAChF,WAAO,MAAM;AAAA,IAAC;AAAA,EAChB;AAEA,QAAM,aAAa,eAAe,IAAI,IAAI;AAE1C,MAAI,0BAA0B,YAAY,GAAG;AAE7C,SAAO,MAAY;AACjB,cAAU,eAAe,UAAU;AAAA,EACrC;AACF;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collaborative-editing.es.js","sources":["../../../../src/modules/collaborative-editing/collaborative-editing.ts"],"sourcesContent":["import type QuillCursors from 'quill-cursors'\
|
|
1
|
+
{"version":3,"file":"collaborative-editing.es.js","sources":["../../../../src/modules/collaborative-editing/collaborative-editing.ts"],"sourcesContent":["import type QuillCursors from 'quill-cursors'\nimport type { Awareness } from 'y-protocols/awareness'\nimport type * as Y from 'yjs'\nimport type FluentEditor from '../../fluent-editor'\nimport type { UnifiedProvider } from './provider/providerRegistry'\nimport type { CollaborativeEditingDeps, YjsOptions } from './types'\nimport { bindAwarenessToCursors, setupAwareness } from './awareness'\nimport { setupIndexedDB } from './awareness/y-indexeddb'\nimport { createProvider } from './provider/providerRegistry'\n\nexport class CollaborativeEditor {\n private ydoc: Y.Doc\n private provider: UnifiedProvider\n private awareness: Awareness\n private cursors: QuillCursors | null\n private cleanupBindings: (() => void) | null = null\n private clearIndexedDB: (() => void) | null = null\n private deps: CollaborativeEditingDeps\n\n constructor(\n public quill: FluentEditor,\n public options: YjsOptions,\n ) {\n this.deps = this.options.deps || (window as any)\n const { Y, Awareness, QuillBinding, QuillCursors } = this.deps\n\n if (!Y || !Awareness || !QuillBinding || !QuillCursors) {\n throw new Error(\n 'Missing required dependencies for collaborative editing. '\n + 'Please provide Y, Awareness, QuillBinding, and QuillCursors in the deps option.',\n )\n }\n\n this.ydoc = this.options.ydoc || new Y.Doc()\n\n if (this.options.cursors !== false) {\n const cursorsOptions = typeof this.options.cursors === 'object' ? this.options.cursors : {}\n this.cursors = new QuillCursors(quill, cursorsOptions)\n }\n\n if (this.options.awareness) {\n const awareness = setupAwareness(this.options.awareness, new Awareness(this.ydoc))\n if (!awareness) {\n throw new Error('Failed to initialize awareness')\n }\n this.awareness = awareness\n }\n else {\n this.awareness = new Awareness(this.ydoc)\n }\n\n if (this.options.provider) {\n const providerConfig = this.options.provider\n try {\n const provider = createProvider({\n doc: this.ydoc,\n options: providerConfig.options,\n type: providerConfig.type,\n awareness: this.awareness,\n onConnect: this.options.onConnect,\n onDisconnect: this.options.onDisconnect,\n onError: this.options.onError,\n onSyncChange: this.options.onSyncChange,\n deps: this.deps,\n })\n this.provider = provider\n }\n catch (error) {\n console.warn(\n `[yjs] Error creating provider of type ${providerConfig.type}:`,\n error,\n )\n }\n }\n\n if (this.provider) {\n const ytext = this.ydoc.getText('tiny-editor')\n this.cleanupBindings = bindAwarenessToCursors(this.awareness, this.cursors, quill, ytext, Y) || null\n new QuillBinding(\n ytext,\n this.quill,\n this.awareness,\n )\n }\n else {\n console.error('Failed to initialize collaborative editor: no valid provider configured')\n }\n\n if (this.options.offline !== false) {\n this.clearIndexedDB = setupIndexedDB(this.ydoc, this.deps.IndexeddbPersistence)\n }\n }\n\n public getAwareness() {\n return this.awareness\n }\n\n public getProvider() {\n return this.provider\n }\n\n public getYDoc() {\n return this.ydoc\n }\n\n get isConnected() {\n return this.provider?.isConnected ?? false\n }\n\n get isSynced() {\n return this.provider?.isSynced ?? false\n }\n\n public getCursors() {\n return this.cursors\n }\n\n public async destroy() {\n this.cleanupBindings?.()\n this.provider?.destroy?.()\n this.cursors?.clearCursors()\n this.awareness?.destroy?.()\n this.clearIndexedDB?.()\n this.ydoc?.destroy?.()\n }\n}\n"],"names":[],"mappings":";;;;;;;AAUO,MAAM,oBAAoB;AAAA,EAS/B,YACS,OACA,SACP;AAXM;AACA;AACA;AACA;AACA,2CAAuC;AACvC,0CAAsC;AACtC;AAGC,SAAA,QAAA;AACA,SAAA,UAAA;AAEP,SAAK,OAAO,KAAK,QAAQ,QAAS;AAClC,UAAM,EAAE,GAAG,WAAW,cAAc,aAAA,IAAiB,KAAK;AAE1D,QAAI,CAAC,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,cAAc;AACtD,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAGJ;AAEA,SAAK,OAAO,KAAK,QAAQ,QAAQ,IAAI,EAAE,IAAA;AAEvC,QAAI,KAAK,QAAQ,YAAY,OAAO;AAClC,YAAM,iBAAiB,OAAO,KAAK,QAAQ,YAAY,WAAW,KAAK,QAAQ,UAAU,CAAA;AACzF,WAAK,UAAU,IAAI,aAAa,OAAO,cAAc;AAAA,IACvD;AAEA,QAAI,KAAK,QAAQ,WAAW;AAC1B,YAAM,YAAY,eAAe,KAAK,QAAQ,WAAW,IAAI,UAAU,KAAK,IAAI,CAAC;AACjF,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,gCAAgC;AAAA,MAClD;AACA,WAAK,YAAY;AAAA,IACnB,OACK;AACH,WAAK,YAAY,IAAI,UAAU,KAAK,IAAI;AAAA,IAC1C;AAEA,QAAI,KAAK,QAAQ,UAAU;AACzB,YAAM,iBAAiB,KAAK,QAAQ;AACpC,UAAI;AACF,cAAM,WAAW,eAAe;AAAA,UAC9B,KAAK,KAAK;AAAA,UACV,SAAS,eAAe;AAAA,UACxB,MAAM,eAAe;AAAA,UACrB,WAAW,KAAK;AAAA,UAChB,WAAW,KAAK,QAAQ;AAAA,UACxB,cAAc,KAAK,QAAQ;AAAA,UAC3B,SAAS,KAAK,QAAQ;AAAA,UACtB,cAAc,KAAK,QAAQ;AAAA,UAC3B,MAAM,KAAK;AAAA,QAAA,CACZ;AACD,aAAK,WAAW;AAAA,MAClB,SACO,OAAO;AACZ,gBAAQ;AAAA,UACN,yCAAyC,eAAe,IAAI;AAAA,UAC5D;AAAA,QAAA;AAAA,MAEJ;AAAA,IACF;AAEA,QAAI,KAAK,UAAU;AACjB,YAAM,QAAQ,KAAK,KAAK,QAAQ,aAAa;AAC7C,WAAK,kBAAkB,uBAAuB,KAAK,WAAW,KAAK,SAAS,OAAO,OAAO,CAAC,KAAK;AAChG,UAAI;AAAA,QACF;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MAAA;AAAA,IAET,OACK;AACH,cAAQ,MAAM,yEAAyE;AAAA,IACzF;AAEA,QAAI,KAAK,QAAQ,YAAY,OAAO;AAClC,WAAK,iBAAiB,eAAe,KAAK,MAAM,KAAK,KAAK,oBAAoB;AAAA,IAChF;AAAA,EACF;AAAA,EAEO,eAAe;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,cAAc;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,UAAU;AACf,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,cAAc;;AAChB,aAAO,UAAK,aAAL,mBAAe,gBAAe;AAAA,EACvC;AAAA,EAEA,IAAI,WAAW;;AACb,aAAO,UAAK,aAAL,mBAAe,aAAY;AAAA,EACpC;AAAA,EAEO,aAAa;AAClB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAa,UAAU;;AACrB,eAAK,oBAAL;AACA,qBAAK,aAAL,mBAAe,YAAf;AACA,eAAK,YAAL,mBAAc;AACd,qBAAK,cAAL,mBAAgB,YAAhB;AACA,eAAK,mBAAL;AACA,qBAAK,SAAL,mBAAW,YAAX;AAAA,EACF;AACF;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.es.js","sources":["../../../../src/modules/collaborative-editing/module.ts"],"sourcesContent":["import type FluentEditor from '../../fluent-editor'\
|
|
1
|
+
{"version":3,"file":"module.es.js","sources":["../../../../src/modules/collaborative-editing/module.ts"],"sourcesContent":["import type FluentEditor from '../../fluent-editor'\nimport { CollaborativeEditor } from './collaborative-editing'\n\nexport class CollaborationModule {\n private collaborativeEditor: CollaborativeEditor\n\n constructor(public quill: FluentEditor, public options: any) {\n this.collaborativeEditor = new CollaborativeEditor(quill, options)\n\n window.addEventListener(\n 'beforeunload',\n () => { void this.collaborativeEditor.destroy().catch(err => console.warn('[yjs] destroy failed:', err)) },\n { once: true },\n )\n }\n\n public getCursors() {\n return this.collaborativeEditor.getCursors()\n }\n\n public getAwareness() {\n return this.collaborativeEditor.getAwareness()\n }\n\n public getProvider() {\n return this.collaborativeEditor.getProvider()\n }\n\n public async destroy() {\n await this.collaborativeEditor.destroy()\n }\n}\n"],"names":[],"mappings":";;;;AAGO,MAAM,oBAAoB;AAAA,EAG/B,YAAmB,OAA4B,SAAc;AAFrD;AAEW,SAAA,QAAA;AAA4B,SAAA,UAAA;AAC7C,SAAK,sBAAsB,IAAI,oBAAoB,OAAO,OAAO;AAEjE,WAAO;AAAA,MACL;AAAA,MACA,MAAM;AAAE,aAAK,KAAK,oBAAoB,QAAA,EAAU,MAAM,SAAO,QAAQ,KAAK,yBAAyB,GAAG,CAAC;AAAA,MAAE;AAAA,MACzG,EAAE,MAAM,KAAA;AAAA,IAAK;AAAA,EAEjB;AAAA,EAEO,aAAa;AAClB,WAAO,KAAK,oBAAoB,WAAA;AAAA,EAClC;AAAA,EAEO,eAAe;AACpB,WAAO,KAAK,oBAAoB,aAAA;AAAA,EAClC;AAAA,EAEO,cAAc;AACnB,WAAO,KAAK,oBAAoB,YAAA;AAAA,EAClC;AAAA,EAEA,MAAa,UAAU;AACrB,UAAM,KAAK,oBAAoB,QAAA;AAAA,EACjC;AACF;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providerRegistry.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/providerRegistry.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\
|
|
1
|
+
{"version":3,"file":"providerRegistry.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/providerRegistry.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\nimport type * as Y from 'yjs'\nimport type { CollaborativeEditingDeps, ProviderEventHandlers } from '../types'\nimport { WebRTCProviderWrapper } from './webrtc'\nimport { WebsocketProviderWrapper } from './websocket'\n\nexport type ProviderRegistry = Record<string, ProviderConstructor>\n\nexport type ProviderConstructor<T = any> = new (\n props: ProviderConstructorProps<T>\n) => UnifiedProvider\n\nexport type ProviderConstructorProps<T = any> = {\n options: T\n awareness?: Awareness\n doc?: Y.Doc\n deps?: CollaborativeEditingDeps\n} & ProviderEventHandlers\n\nexport interface UnifiedProvider extends ProviderEventHandlers {\n awareness: Awareness\n document: Y.Doc\n type: 'webrtc' | 'websocket' | string\n connect: () => void\n destroy: () => void\n disconnect: () => void\n isConnected: boolean\n isSynced: boolean\n}\n\nconst providerRegistry: ProviderRegistry = {\n websocket: WebsocketProviderWrapper,\n webrtc: WebRTCProviderWrapper,\n}\n\nexport function registerProviderType<T>(type: string, providerClass: ProviderConstructor<T>) {\n providerRegistry[type as string]\n = providerClass as ProviderConstructor\n}\n\nexport function getProviderClass(type: string): ProviderConstructor | undefined {\n return providerRegistry[type]\n}\n\nexport function createProvider({\n type,\n ...props\n}: ProviderConstructorProps & {\n type: string\n}) {\n const ProviderClass = getProviderClass(type)\n\n if (!ProviderClass) {\n throw new Error(`Provider type \"${type}\" not found in registry`)\n }\n\n return new ProviderClass(props)\n}\n"],"names":[],"mappings":";;AA8BA,MAAM,mBAAqC;AAAA,EACzC,WAAW;AAAA,EACX,QAAQ;AACV;AAEO,SAAS,qBAAwB,MAAc,eAAuC;AAC3F,mBAAiB,IAAc,IAC3B;AACN;AAEO,SAAS,iBAAiB,MAA+C;AAC9E,SAAO,iBAAiB,IAAI;AAC9B;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA,GAAG;AACL,GAEG;AACD,QAAM,gBAAgB,iBAAiB,IAAI;AAE3C,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,kBAAkB,IAAI,yBAAyB;AAAA,EACjE;AAEA,SAAO,IAAI,cAAc,KAAK;AAChC;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webrtc.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/webrtc.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\
|
|
1
|
+
{"version":3,"file":"webrtc.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/webrtc.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\nimport type { WebrtcProvider } from 'y-webrtc'\nimport type * as Y from 'yjs'\nimport type { CollaborativeEditingDeps, ProviderEventHandlers } from '../types'\nimport type { UnifiedProvider } from './providerRegistry'\n\nexport interface WebRTCProviderOptions {\n roomName: string\n filterBcConns?: boolean\n maxConns?: number\n password?: string\n peerOpts?: Record<string, unknown>\n signaling?: string[]\n}\n\nexport class WebRTCProviderWrapper implements UnifiedProvider {\n private provider: WebrtcProvider\n private _isConnected = false\n private _isSynced = false\n\n onConnect?: () => void\n onDisconnect?: () => void\n onError?: (error: Error) => void\n onSyncChange?: (isSynced: boolean) => void\n\n document: Y.Doc\n awareness: Awareness\n type: 'webrtc'\n\n connect = () => {\n try {\n this.provider.connect()\n }\n catch (error) {\n console.warn('[yjs] Error connecting WebRTC provider:', error)\n }\n }\n\n destroy = () => {\n try {\n this.provider.destroy()\n }\n catch (error) {\n console.warn('[yjs] Error destroying WebRTC provider:', error)\n }\n }\n\n disconnect = () => {\n try {\n this.provider.disconnect()\n this._isConnected = false\n this._isSynced = false\n }\n catch (error) {\n console.warn('[yjs] Error disconnecting WebRTC provider:', error)\n }\n }\n\n constructor({\n awareness,\n doc,\n options,\n onConnect,\n onDisconnect,\n onError,\n onSyncChange,\n deps,\n }: {\n options: WebRTCProviderOptions\n awareness?: Awareness\n doc?: Y.Doc\n deps?: CollaborativeEditingDeps\n } & ProviderEventHandlers) {\n this.onConnect = onConnect\n this.onDisconnect = onDisconnect\n this.onError = onError\n this.onSyncChange = onSyncChange\n\n const { Y, Awareness, WebrtcProvider } = deps || (window as any)\n\n if (!WebrtcProvider) {\n throw new Error('WebrtcProvider dependency not provided')\n }\n\n this.document = doc || new Y.Doc()\n this.awareness = awareness ?? new Awareness(this.document)\n try {\n this.provider = new WebrtcProvider(options.roomName, this.document, {\n awareness: this.awareness,\n ...options,\n })\n\n this.provider.on('status', (status: { connected: boolean }) => {\n const wasConnected = this._isConnected\n this._isConnected = status.connected\n if (status.connected) {\n if (!wasConnected) {\n this.onConnect?.()\n }\n if (!this._isSynced) {\n this._isSynced = true\n this.onSyncChange?.(true)\n }\n }\n else {\n if (wasConnected) {\n this.onDisconnect?.()\n\n if (this._isSynced) {\n this._isSynced = false\n this.onSyncChange?.(false)\n }\n }\n }\n })\n }\n catch (error) {\n console.warn('[yjs] Error creating WebRTC provider:', error)\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n get isConnected() {\n return this._isConnected\n }\n\n get isSynced() {\n return this._isSynced\n }\n\n getProvider() {\n return this.provider\n }\n}\n"],"names":[],"mappings":";;;AAeO,MAAM,sBAAiD;AAAA,EA2C5D,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,GAMyB;AAxDnB;AACA,wCAAe;AACf,qCAAY;AAEpB;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA,mCAAU,MAAM;AACd,UAAI;AACF,aAAK,SAAS,QAAA;AAAA,MAChB,SACO,OAAO;AACZ,gBAAQ,KAAK,2CAA2C,KAAK;AAAA,MAC/D;AAAA,IACF;AAEA,mCAAU,MAAM;AACd,UAAI;AACF,aAAK,SAAS,QAAA;AAAA,MAChB,SACO,OAAO;AACZ,gBAAQ,KAAK,2CAA2C,KAAK;AAAA,MAC/D;AAAA,IACF;AAEA,sCAAa,MAAM;AACjB,UAAI;AACF,aAAK,SAAS,WAAA;AACd,aAAK,eAAe;AACpB,aAAK,YAAY;AAAA,MACnB,SACO,OAAO;AACZ,gBAAQ,KAAK,8CAA8C,KAAK;AAAA,MAClE;AAAA,IACF;AAiBE,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,UAAU;AACf,SAAK,eAAe;AAEpB,UAAM,EAAE,GAAG,WAAW,eAAA,IAAmB,QAAS;AAElD,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AAEA,SAAK,WAAW,OAAO,IAAI,EAAE,IAAA;AAC7B,SAAK,YAAY,aAAa,IAAI,UAAU,KAAK,QAAQ;AACzD,QAAI;AACF,WAAK,WAAW,IAAI,eAAe,QAAQ,UAAU,KAAK,UAAU;AAAA,QAClE,WAAW,KAAK;AAAA,QAChB,GAAG;AAAA,MAAA,CACJ;AAED,WAAK,SAAS,GAAG,UAAU,CAAC,WAAmC;AA7E9D;AA8EC,cAAM,eAAe,KAAK;AAC1B,aAAK,eAAe,OAAO;AAC3B,YAAI,OAAO,WAAW;AACpB,cAAI,CAAC,cAAc;AACjB,uBAAK,cAAL;AAAA,UACF;AACA,cAAI,CAAC,KAAK,WAAW;AACnB,iBAAK,YAAY;AACjB,uBAAK,iBAAL,8BAAoB;AAAA,UACtB;AAAA,QACF,OACK;AACH,cAAI,cAAc;AAChB,uBAAK,iBAAL;AAEA,gBAAI,KAAK,WAAW;AAClB,mBAAK,YAAY;AACjB,yBAAK,iBAAL,8BAAoB;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SACO,OAAO;AACZ,cAAQ,KAAK,yCAAyC,KAAK;AAC3D,yCAAU,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,IAAI,cAAc;AAChB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAW;AACb,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,cAAc;AACZ,WAAO,KAAK;AAAA,EACd;AACF;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/websocket.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\
|
|
1
|
+
{"version":3,"file":"websocket.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/websocket.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\nimport type { WebsocketProvider } from 'y-websocket'\nimport type * as Y from 'yjs'\nimport type { CollaborativeEditingDeps, ProviderEventHandlers } from '../types'\nimport type { UnifiedProvider } from './providerRegistry'\n\nexport interface WebsocketProviderOptions {\n serverUrl: string\n roomName: string\n connect?: boolean\n awareness?: Awareness\n params?: Record<string, string>\n protocols?: string[]\n WebSocketPolyfill?: typeof WebSocket\n resyncInterval?: number\n maxBackoffTime?: number\n disableBc?: boolean\n}\n\nexport class WebsocketProviderWrapper implements UnifiedProvider {\n private provider: WebsocketProvider\n\n private _isConnected = false\n private _isSynced = false\n\n onConnect?: () => void\n onDisconnect?: () => void\n onError?: (error: Error) => void\n onSyncChange?: (isSynced: boolean) => void\n\n document: Y.Doc\n awareness: Awareness\n type: 'websocket'\n\n connect = () => {\n try {\n this.provider.connect()\n }\n catch (error) {\n console.warn('[yjs] Error connecting WebSocket provider:', error)\n }\n }\n\n destroy = () => {\n try {\n this.provider.destroy()\n }\n catch (error) {\n console.warn('[yjs] Error destroying WebSocket provider:', error)\n }\n }\n\n disconnect = () => {\n try {\n this.provider.disconnect()\n const wasSynced = this._isSynced\n\n this._isConnected = false\n this._isSynced = false\n\n if (wasSynced) {\n this.onSyncChange?.(false)\n }\n }\n catch (error) {\n console.warn('[yjs] Error disconnecting WebSocket provider:', error)\n }\n }\n\n constructor({\n awareness,\n doc,\n options,\n onConnect,\n onDisconnect,\n onError,\n onSyncChange,\n deps,\n }: {\n options: WebsocketProviderOptions\n awareness?: Awareness\n doc?: Y.Doc\n deps?: CollaborativeEditingDeps\n } & ProviderEventHandlers) {\n this.onConnect = onConnect\n this.onDisconnect = onDisconnect\n this.onError = onError\n this.onSyncChange = onSyncChange\n\n const { Y, Awareness, WebsocketProvider } = deps || (window as any)\n\n if (!WebsocketProvider) {\n throw new Error('WebsocketProvider dependency not provided')\n }\n\n this.document = doc || new Y.Doc()\n this.awareness = awareness ?? new Awareness(this.document)\n try {\n this.provider = new WebsocketProvider(\n options.serverUrl,\n options.roomName,\n this.document,\n {\n awareness: this.awareness,\n ...options,\n },\n )\n\n this.provider.on('status', (event: { status: 'connected' | 'disconnected' | 'connecting' }) => {\n const wasConnected = this._isConnected\n this._isConnected = event.status === 'connected'\n\n if (event.status === 'connected') {\n if (!wasConnected) {\n this.onConnect?.()\n }\n if (!this._isSynced) {\n this._isSynced = true\n this.onSyncChange?.(true)\n }\n }\n else if (event.status === 'disconnected') {\n if (wasConnected) {\n this.onDisconnect?.()\n if (this._isSynced) {\n this._isSynced = false\n this.onSyncChange?.(false)\n }\n }\n }\n })\n }\n catch (error) {\n console.warn('[yjs] Error creating WebSocket provider:', error)\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n get isConnected() {\n return this._isConnected\n }\n\n get isSynced() {\n return this._isSynced\n }\n\n getProvider() {\n return this.provider\n }\n}\n"],"names":[],"mappings":";;;AAmBO,MAAM,yBAAoD;AAAA,EAkD/D,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,GAMyB;AA/DnB;AAEA,wCAAe;AACf,qCAAY;AAEpB;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA,mCAAU,MAAM;AACd,UAAI;AACF,aAAK,SAAS,QAAA;AAAA,MAChB,SACO,OAAO;AACZ,gBAAQ,KAAK,8CAA8C,KAAK;AAAA,MAClE;AAAA,IACF;AAEA,mCAAU,MAAM;AACd,UAAI;AACF,aAAK,SAAS,QAAA;AAAA,MAChB,SACO,OAAO;AACZ,gBAAQ,KAAK,8CAA8C,KAAK;AAAA,MAClE;AAAA,IACF;AAEA,sCAAa,MAAM;AAjCd;AAkCH,UAAI;AACF,aAAK,SAAS,WAAA;AACd,cAAM,YAAY,KAAK;AAEvB,aAAK,eAAe;AACpB,aAAK,YAAY;AAEjB,YAAI,WAAW;AACb,qBAAK,iBAAL,8BAAoB;AAAA,QACtB;AAAA,MACF,SACO,OAAO;AACZ,gBAAQ,KAAK,iDAAiD,KAAK;AAAA,MACrE;AAAA,IACF;AAiBE,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,UAAU;AACf,SAAK,eAAe;AAEpB,UAAM,EAAE,GAAG,WAAW,kBAAA,IAAsB,QAAS;AAErD,QAAI,CAAC,mBAAmB;AACtB,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AAEA,SAAK,WAAW,OAAO,IAAI,EAAE,IAAA;AAC7B,SAAK,YAAY,aAAa,IAAI,UAAU,KAAK,QAAQ;AACzD,QAAI;AACF,WAAK,WAAW,IAAI;AAAA,QAClB,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,KAAK;AAAA,QACL;AAAA,UACE,WAAW,KAAK;AAAA,UAChB,GAAG;AAAA,QAAA;AAAA,MACL;AAGF,WAAK,SAAS,GAAG,UAAU,CAAC,UAAmE;AAzF9F;AA0FC,cAAM,eAAe,KAAK;AAC1B,aAAK,eAAe,MAAM,WAAW;AAErC,YAAI,MAAM,WAAW,aAAa;AAChC,cAAI,CAAC,cAAc;AACjB,uBAAK,cAAL;AAAA,UACF;AACA,cAAI,CAAC,KAAK,WAAW;AACnB,iBAAK,YAAY;AACjB,uBAAK,iBAAL,8BAAoB;AAAA,UACtB;AAAA,QACF,WACS,MAAM,WAAW,gBAAgB;AACxC,cAAI,cAAc;AAChB,uBAAK,iBAAL;AACA,gBAAI,KAAK,WAAW;AAClB,mBAAK,YAAY;AACjB,yBAAK,iBAAL,8BAAoB;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SACO,OAAO;AACZ,cAAQ,KAAK,4CAA4C,KAAK;AAC9D,yCAAU,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,IAAI,cAAc;AAChB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAW;AACb,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,cAAc;AACZ,WAAO,KAAK;AAAA,EACd;AACF;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"counter.es.js","sources":["../../../src/modules/counter.ts"],"sourcesContent":["import type { AnyFunction } from '../config'\
|
|
1
|
+
{"version":3,"file":"counter.es.js","sources":["../../../src/modules/counter.ts"],"sourcesContent":["import type { AnyFunction } from '../config'\nimport type FluentEditor from '../fluent-editor'\nimport Quill from 'quill'\nimport { CHANGE_LANGUAGE_EVENT } from '../config'\n\nexport interface ICounterOption {\n format?: 'text' | 'html'\n unit?: 'word' | 'char'\n count?: number\n template?: string | AnyFunction\n errorTemplate?: string | AnyFunction\n}\n\nexport default class Counter {\n container: HTMLDivElement\n options: ICounterOption\n\n constructor(public quill: FluentEditor, options: ICounterOption) {\n this.options = this.resolveOptions(options)\n this.container = quill.addContainer('ql-counter')\n quill.on(Quill.events.TEXT_CHANGE, this.renderCount)\n this.quill.emitter.on(CHANGE_LANGUAGE_EVENT, () => {\n this.options = this.resolveOptions(options)\n this.renderCount()\n })\n this.renderCount()\n }\n\n resolveOptions(options: ICounterOption) {\n return Object.assign({\n format: 'text',\n unit: 'char',\n template: this.quill.getLangText('counter-template'),\n count: 500,\n }, options)\n }\n\n renderCount = () => {\n setTimeout(() => {\n // @ts-ignore\n const { format, count: totalCount, unit, template: counterTemplate, errorTemplate } = this.options\n const count = this.getContentLength(format)\n const restCount = totalCount - count\n const countUnit = unit === 'char' ? this.quill.getLangText('char') : this.quill.getLangText('word')\n let template: any = counterTemplate\n if (typeof template === 'function') {\n template = template(count, restCount)\n }\n const desc = template.replace('{{count}}', count)\n .replace('{{totalCount}}', String(totalCount))\n .replace('{{restCount}}', String(restCount))\n .replace(/{{countUnit}}/g, countUnit)\n\n let limitTemplate: any = errorTemplate || this.quill.getLangText('counter-limit-tips')\n if (typeof limitTemplate === 'function') {\n limitTemplate = limitTemplate(count, restCount)\n }\n const limitTips = limitTemplate.replace('{{countUnit}}', countUnit)\n if (restCount < 0) {\n this.container.innerHTML = errorTemplate ? limitTips : `<span style=\"color:red\">${limitTips}</span>`\n }\n else {\n this.container.innerHTML = desc\n }\n })\n }\n\n getContentLength(format) {\n let content = this.quill.getText()\n if (format === 'html') {\n let html = this.quill.root.innerHTML\n // 编辑器初始时\n if (html === '<p><br></p>' || html === '<div><br><div>') {\n html = ''\n }\n content = html\n }\n const text = content.replace(/\\s/g, '').trim()\n if (this.options.unit === 'word') {\n return !content.trim() ? 0 : content.trim().split(/\\s+/).length\n }\n return text.length\n }\n}\n"],"names":[],"mappings":";;;;;;AAaA,MAAqB,QAAQ;AAAA,EAI3B,YAAmB,OAAqB,SAAyB;AAHjE;AACA;AAsBA,uCAAc,MAAM;AAClB,iBAAW,MAAM;AAEf,cAAM,EAAE,QAAQ,OAAO,YAAY,MAAM,UAAU,iBAAiB,kBAAkB,KAAK;AAC3F,cAAM,QAAQ,KAAK,iBAAiB,MAAM;AAC1C,cAAM,YAAY,aAAa;AAC/B,cAAM,YAAY,SAAS,SAAS,KAAK,MAAM,YAAY,MAAM,IAAI,KAAK,MAAM,YAAY,MAAM;AAClG,YAAI,WAAgB;AACpB,YAAI,OAAO,aAAa,YAAY;AAClC,qBAAW,SAAS,OAAO,SAAS;AAAA,QACtC;AACA,cAAM,OAAO,SAAS,QAAQ,aAAa,KAAK,EAC7C,QAAQ,kBAAkB,OAAO,UAAU,CAAC,EAC5C,QAAQ,iBAAiB,OAAO,SAAS,CAAC,EAC1C,QAAQ,kBAAkB,SAAS;AAEtC,YAAI,gBAAqB,iBAAiB,KAAK,MAAM,YAAY,oBAAoB;AACrF,YAAI,OAAO,kBAAkB,YAAY;AACvC,0BAAgB,cAAc,OAAO,SAAS;AAAA,QAChD;AACA,cAAM,YAAY,cAAc,QAAQ,iBAAiB,SAAS;AAClE,YAAI,YAAY,GAAG;AACjB,eAAK,UAAU,YAAY,gBAAgB,YAAY,2BAA2B,SAAS;AAAA,QAC7F,OACK;AACH,eAAK,UAAU,YAAY;AAAA,QAC7B;AAAA,MACF,CAAC;AAAA,IACH;AAhDmB,SAAA,QAAA;AACjB,SAAK,UAAU,KAAK,eAAe,OAAO;AAC1C,SAAK,YAAY,MAAM,aAAa,YAAY;AAChD,UAAM,GAAG,MAAM,OAAO,aAAa,KAAK,WAAW;AACnD,SAAK,MAAM,QAAQ,GAAG,uBAAuB,MAAM;AACjD,WAAK,UAAU,KAAK,eAAe,OAAO;AAC1C,WAAK,YAAA;AAAA,IACP,CAAC;AACD,SAAK,YAAA;AAAA,EACP;AAAA,EAEA,eAAe,SAAyB;AACtC,WAAO,OAAO,OAAO;AAAA,MACnB,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,UAAU,KAAK,MAAM,YAAY,kBAAkB;AAAA,MACnD,OAAO;AAAA,IAAA,GACN,OAAO;AAAA,EACZ;AAAA,EAgCA,iBAAiB,QAAQ;AACvB,QAAI,UAAU,KAAK,MAAM,QAAA;AACzB,QAAI,WAAW,QAAQ;AACrB,UAAI,OAAO,KAAK,MAAM,KAAK;AAE3B,UAAI,SAAS,iBAAiB,SAAS,kBAAkB;AACvD,eAAO;AAAA,MACT;AACA,gBAAU;AAAA,IACZ;AACA,UAAM,OAAO,QAAQ,QAAQ,OAAO,EAAE,EAAE,KAAA;AACxC,QAAI,KAAK,QAAQ,SAAS,QAAQ;AAChC,aAAO,CAAC,QAAQ,KAAA,IAAS,IAAI,QAAQ,OAAO,MAAM,KAAK,EAAE;AAAA,IAC3D;AACA,WAAO,KAAK;AAAA,EACd;AACF;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-clipboard.es.js","sources":["../../../src/modules/custom-clipboard.ts"],"sourcesContent":["import type TypeClipboard from 'quill/modules/clipboard'\r\nimport type FluentEditor from '../fluent-editor'\r\nimport Quill from 'quill'\r\nimport {\r\n ERROR_IMAGE_PLACEHOLDER_CN,\r\n ERROR_IMAGE_PLACEHOLDER_EN,\r\n} from '../config/base64-image'\r\nimport { BIG_DELTA_LIMIT } from '../config/editor.config'\r\nimport {\r\n hexToRgbA,\r\n imageUrlToFile,\r\n isNullOrUndefined,\r\n omit,\r\n replaceDeltaImage,\r\n splitWithBreak,\r\n} from '../config/editor.utils'\r\nimport { isString } from '../utils/is'\r\n\r\nconst Clipboard = Quill.import('modules/clipboard') as typeof TypeClipboard\r\nconst Delta = Quill.import('delta')\r\n\r\nexport class CustomClipboard extends Clipboard {\r\n declare quill: FluentEditor\r\n\r\n prepareMatching(container: HTMLElement, nodeMatches) {\r\n const elementMatchers = []\r\n const textMatchers = []\r\n this.matchers.forEach((pair) => {\r\n const [selector, matcher] = pair\r\n if (selector === Node.TEXT_NODE) {\r\n textMatchers.push(matcher)\r\n }\r\n else if (selector === Node.ELEMENT_NODE) {\r\n elementMatchers.push(matcher)\r\n }\r\n else if (isString(selector)) {\r\n // word 的 v:shape 系列标签只能通过 getElementsByTagName 获取\r\n const vRegex = /v:(.+)/\r\n const nodeList = Array.from(\r\n vRegex.test(selector)\r\n ? container.getElementsByTagName(selector)\r\n : container.querySelectorAll(selector),\r\n )\r\n nodeList.forEach((node) => {\r\n if (nodeMatches.has(node)) {\r\n const matches = nodeMatches.get(node)\r\n matches.push(matcher)\r\n }\r\n else {\r\n nodeMatches.set(node, [matcher])\r\n }\r\n })\r\n }\r\n })\r\n return [elementMatchers, textMatchers]\r\n }\r\n\r\n onCaptureCopy(e, isCut = false) {\r\n if (e.defaultPrevented) {\r\n return\r\n }\r\n e.preventDefault()\r\n const [range] = this.quill.selection.getRange()\r\n if (isNullOrUndefined(range)) {\r\n return\r\n }\r\n const { html, text } = this.onCopy(range, isCut)\r\n\r\n // 兼容IE11浏览器`\r\n if (!e.clipboardData) {\r\n e.clipboardData = {\r\n types: 'text/plain',\r\n setData: (_type, value) => {\r\n // @ts-ignore\r\n return window.clipboardData.setData('Text', value)\r\n },\r\n }\r\n }\r\n\r\n // 复制代码时移除utf8中产生的不间断空格\\u00A0\r\n let plainText = text\r\n if (html.startsWith('<pre>')) {\r\n plainText = text.replace(/\\u00A0/g, ' ')\r\n }\r\n\r\n e.clipboardData.setData('text/html', html)\r\n e.clipboardData.setData('text/plain', plainText)\r\n if (isCut) {\r\n this.quill.deleteText(range, Quill.sources.USER)\r\n }\r\n }\r\n\r\n onCapturePaste(e: ClipboardEvent) {\r\n if (e.defaultPrevented || !this.quill.isEnabled()) {\r\n return\r\n }\r\n e.preventDefault()\r\n const range = this.quill.getSelection(true)\r\n if (isNullOrUndefined(range)) {\r\n return\r\n }\r\n\r\n // 兼容IE11浏览器\r\n if (!e.clipboardData) {\r\n // @ts-ignore\r\n e.clipboardData = {\r\n types: 'text/plain',\r\n getData: () => {\r\n // @ts-ignore\r\n return window.clipboardData.getData('Text')\r\n },\r\n }\r\n }\r\n\r\n const html = e.clipboardData.getData('text/html')\r\n const text = e.clipboardData.getData('text/plain')\r\n const files = Array.from(e.clipboardData.files || [])\r\n const msExcelCheck = /<meta.*?Microsoft Excel\\s[\\d].*?>/\r\n\r\n if (html.search(msExcelCheck) === -1 && files.length > 0) {\r\n this.quill.uploader.upload(range, files)\r\n }\r\n else {\r\n const msWordCheck1\r\n = /<meta\\s*name=\"?generator\"?\\s*content=\"?microsoft\\s*word\\s*\\d+\"?\\/?>/i\r\n const msWordCheck2 = /xmlns:o=\"urn:schemas-microsoft-com/i\r\n const result = { html, text, files, rtf: null }\r\n if (html.search(msExcelCheck) !== -1) {\r\n result.html = renderStyles(html)\r\n }\r\n if (msWordCheck1.test(html) || msWordCheck2.test(html)) {\r\n // TODO: 当word文档包含heading时text/rtf读取为空,无法获取hex图片,待修复。可参考ckeditor5/issues/2493\r\n result.rtf = e.clipboardData.getData('text/rtf')\r\n }\r\n this.onPaste(range, result)\r\n }\r\n }\r\n\r\n onPaste(range, { html, text, files: clipboardFiles, rtf }) {\r\n const hexImages = this.extractImageDataFromRtf(rtf)\r\n const rootBgColor = getComputedStyle(this.quill.root).backgroundColor\r\n const formats = this.quill.getFormat(range.index)\r\n let pastedDelta = this.convert({ text, html }, formats)\r\n pastedDelta = replaceDeltaWhiteSpace(pastedDelta, rootBgColor)\r\n const deltaLength = pastedDelta.ops.length\r\n\r\n let loadingTipsContainer\r\n if (deltaLength > BIG_DELTA_LIMIT) {\r\n loadingTipsContainer = this.quill.addContainer('ql-loading-tips')\r\n loadingTipsContainer.innerHTML = this.quill.getLangText('pasting')\r\n }\r\n\r\n const linePos = { index: range.index, length: range.length, fix: 0 }\r\n const [line, offset] = this.quill.getLine(range.index)\r\n\r\n const handlePasteContent = (content: any) => {\r\n const pastedContent = content\r\n\r\n const oldDelta = new Delta().retain(linePos.index).delete(linePos.length)\r\n const delta = oldDelta.concat(pastedContent)\r\n\r\n setTimeout(() => {\r\n this.quill.updateContents(delta, Quill.sources.USER)\r\n this.quill.setSelection(\r\n delta.length() - linePos.length - linePos.fix,\r\n Quill.sources.SILENT,\r\n )\r\n this.quill.scrollSelectionIntoView()\r\n if (loadingTipsContainer) {\r\n loadingTipsContainer.remove()\r\n }\r\n })\r\n }\r\n\r\n ;(async () => {\r\n try {\r\n const [files, placeholders, originalUrls, imageIndexs] = this.flipFilesArray(\r\n await this.extractFilesFromDelta(\r\n pastedDelta,\r\n clipboardFiles,\r\n hexImages,\r\n ),\r\n )\r\n\r\n if (files.length === 0) {\r\n handlePasteContent(pastedDelta)\r\n }\r\n else {\r\n if (this.quill.options.editorPaste && this.quill.options.editorPaste.observers.length !== 0) {\r\n // 设置editorPaste回调的情况\r\n this.quill.options.editorPaste.emit({\r\n files,\r\n callback: ({ code, message, data }) => {\r\n if (code === 0) {\r\n const { imageUrls } = data\r\n pastedDelta = replaceDeltaImage(\r\n pastedDelta,\r\n imageUrls,\r\n placeholders,\r\n )\r\n handlePasteContent(pastedDelta)\r\n }\r\n else {\r\n console.error('error message:', message)\r\n }\r\n },\r\n })\r\n }\r\n else {\r\n // 没有originalUrls 也没有文件粘贴\r\n if (files[0] !== undefined || originalUrls.length === 0) {\r\n // 没有设置editorPaste回调的情况下,File格式的占位图需要手动转换成url格式,插入到编辑器中\r\n const imageUrls = await this.files2urls(\r\n files,\r\n placeholders,\r\n originalUrls,\r\n pastedDelta,\r\n imageIndexs,\r\n )\r\n pastedDelta = replaceDeltaImage(\r\n pastedDelta,\r\n imageUrls,\r\n placeholders,\r\n )\r\n }\r\n handlePasteContent(pastedDelta)\r\n }\r\n }\r\n }\r\n catch (_e) {\r\n throw new Error('Paste failed.')\r\n }\r\n })()\r\n }\r\n\r\n files2urls(files: File[], placeholders, originalUrls, pastedDelta, imageIndexs) {\r\n return Promise.all(\r\n files.map(async (imageFile, index) => {\r\n const netImgExp = /^((http|https)\\:)?\\/\\/([\\s\\S]+)$/\r\n if (\r\n !placeholders[index]\r\n && originalUrls[index]\r\n && netImgExp.test(originalUrls[index])\r\n ) {\r\n // 不是占位图的普通url图片直接返回url\r\n return new Promise((resolve) => {\r\n resolve(originalUrls[index])\r\n })\r\n }\r\n else {\r\n const range = this.getImgSelection(pastedDelta, imageIndexs[index])\r\n this.quill.uploader.upload(range, [imageFile])\r\n }\r\n }),\r\n )\r\n }\r\n\r\n flipFilesArray(filesArr) {\r\n const files = []\r\n const placeholders = []\r\n const originalUrls = []\r\n const imageIndexs = []\r\n filesArr.forEach((item: any) => {\r\n if (item) {\r\n const [file, placeholder, originalUrl, imageIndex] = item\r\n files.push(file)\r\n placeholders.push(placeholder)\r\n originalUrls.push(originalUrl)\r\n if (imageIndex === 0 || imageIndex) {\r\n imageIndexs.push(imageIndex)\r\n }\r\n }\r\n })\r\n return [files, placeholders, originalUrls, imageIndexs]\r\n }\r\n\r\n // 将图片从hex转为base64\r\n convertHexToBase64(hexString) {\r\n return btoa(\r\n hexString\r\n .match(/\\w{2}/g)\r\n .map((char) => {\r\n return String.fromCharCode(Number.parseInt(char, 16))\r\n })\r\n .join(''),\r\n )\r\n }\r\n\r\n // 匹配rtf中的图片,存储为{hex, type}对象数组\r\n extractImageDataFromRtf(rtfData) {\r\n if (!rtfData) {\r\n return []\r\n }\r\n\r\n const regexPictureHeader\r\n = /{\\\\pict[\\s\\S]+?\\\\bliptag-?\\d+(\\\\blipupi-?\\d+)?({\\\\\\*\\\\blipuid\\s?[\\da-fA-F]+)?[\\s}]*?/\r\n const regexPicture = new RegExp(\r\n `(?:(${regexPictureHeader.source}))([\\\\da-fA-F\\\\s]+)\\\\}`,\r\n 'g',\r\n )\r\n const images = rtfData.match(regexPicture)\r\n const result = []\r\n\r\n if (images) {\r\n for (const image of images) {\r\n let imageType = ''\r\n\r\n if (image.includes('\\\\pngblip')) {\r\n imageType = 'image/png'\r\n }\r\n else if (image.includes('\\\\jpegblip')) {\r\n imageType = 'image/jpeg'\r\n }\r\n\r\n if (imageType) {\r\n result.push({\r\n hex: image\r\n .replace(regexPictureHeader, '')\r\n .replace(/[^\\da-fA-F]/g, ''),\r\n type: imageType,\r\n })\r\n }\r\n }\r\n }\r\n\r\n return result\r\n }\r\n\r\n extractFilesFromDelta(delta, clipboardFiles, hexImages?) {\r\n let index = -1\r\n return Promise.all(\r\n delta.map(async (op) => {\r\n index++\r\n const image = op.insert.image\r\n if (!image || image.hasExisted) {\r\n return\r\n }\r\n\r\n let file\r\n let isPlaceholderImage = false\r\n let imageIndex\r\n try {\r\n // hex 图片存在则为 file:/// 协议本地图片,使用 hex 图片转为 base64 读取\r\n const hexImage = hexImages.length && hexImages.shift()\r\n const newImage\r\n = hexImage\r\n && `data:${hexImage.type};base64,${this.convertHexToBase64(\r\n hexImage.hex,\r\n )}`\r\n imageIndex = index\r\n file = await imageUrlToFile(newImage || image.src || image)\r\n }\r\n catch (_err) {\r\n if (clipboardFiles.length !== 0) {\r\n // 跨域获取图片失败时从剪切板获取图片\r\n const clipboardFile = clipboardFiles[0]\r\n const imageType\r\n = clipboardFile.type?.indexOf('image') === -1\r\n ? 'image/png'\r\n : clipboardFile.type\r\n const blob = clipboardFile.slice(0, clipboardFile.size, imageType)\r\n file = new File([blob], `image-CORS-${new Date().getTime()}.png`, {\r\n type: imageType,\r\n })\r\n }\r\n else if (image.src.startsWith('http')) {\r\n // 什么都不做\r\n }\r\n else {\r\n // 剪切板中无图片,用失败占位图替换\r\n const errorImagePlaceholderJpg\r\n = this.quill.getLangText('img-error') === 'Image Copy Error'\r\n ? ERROR_IMAGE_PLACEHOLDER_EN\r\n : ERROR_IMAGE_PLACEHOLDER_CN\r\n file = await imageUrlToFile(errorImagePlaceholderJpg, true)\r\n isPlaceholderImage = true\r\n }\r\n }\r\n\r\n return [file, isPlaceholderImage, image, imageIndex]\r\n }),\r\n )\r\n }\r\n\r\n getImgSelection(delta, imageIndex) {\r\n let length = 0\r\n delta.ops.every((op, index) => {\r\n if (index === imageIndex) {\r\n return false\r\n }\r\n if (typeof op.insert === 'string') {\r\n length += op.insert.length\r\n }\r\n return true\r\n })\r\n const range = {\r\n index: length,\r\n length: 0,\r\n }\r\n return range\r\n }\r\n}\r\n\r\nfunction rebuildDelta(delta, cellLine) {\r\n const { cell: cellId, colspan, row: rowId, rowspan } = cellLine\r\n const buildedDelta = delta.reduce((newDelta, op) => {\r\n if (op.insert && typeof op.insert === 'string') {\r\n const lines = splitWithBreak(op.insert)\r\n\r\n lines.forEach((text) => {\r\n if (text === '\\n') {\r\n // 对换行增加 table-cell-line 格式,以避免表格断开\r\n newDelta.insert('\\n', {\r\n ...op.attributes,\r\n 'table-cell-line': { row: rowId, cell: cellId, rowspan, colspan },\r\n })\r\n }\r\n else {\r\n text = text.endsWith('\\r') ? text.slice(0, -1) : text\r\n newDelta.insert(\r\n text,\r\n omit(op.attributes, ['table', 'table-cell-line']),\r\n )\r\n }\r\n })\r\n }\r\n else {\r\n newDelta.insert(op.insert, op.attributes)\r\n }\r\n\r\n return newDelta\r\n }, new Delta())\r\n\r\n return buildedDelta\r\n}\r\n\r\nfunction replaceStrWhiteSpace(str) {\r\n const isWhiteSpace = value => /^(\\u3000|\\u0020){1}$/.test(value) // 空白字符\r\n let textWithWhiteSpace = ''\r\n let beginHasChar = false\r\n for (const char of str) {\r\n if (isWhiteSpace(char) && !beginHasChar) {\r\n textWithWhiteSpace += '\\u00A0'\r\n }\r\n else {\r\n textWithWhiteSpace += char\r\n beginHasChar = true\r\n }\r\n }\r\n return textWithWhiteSpace\r\n}\r\n\r\nfunction replaceDeltaWhiteSpace(delta, rootBgColor?) {\r\n return delta.reduce((newDelta, op) => {\r\n // fix: 当粘贴文字颜色和编辑器背景色一致且自身无背景色的情况下移除文字颜色样式,避免误导用户粘贴无效\r\n if (\r\n rootBgColor\r\n && op.attributes\r\n && op.attributes.color\r\n && !op.attributes.background\r\n ) {\r\n const originColor = op.attributes.color\r\n const fontColor\r\n = originColor.indexOf('#') === 0 ? hexToRgbA(originColor) : originColor\r\n if (\r\n fontColor === rootBgColor\r\n || (fontColor === 'rgba(255,255,255,1)'\r\n && rootBgColor === 'rgba(0, 0, 0, 0)')\r\n ) {\r\n delete op.attributes.color\r\n }\r\n }\r\n if (op.insert && typeof op.insert === 'string') {\r\n const lines = splitWithBreak(op.insert)\r\n let insertWithWhiteSpace = ''\r\n lines.forEach((text) => {\r\n insertWithWhiteSpace += replaceStrWhiteSpace(text)\r\n })\r\n newDelta.insert(insertWithWhiteSpace, op.attributes)\r\n }\r\n else {\r\n newDelta.insert(op.insert, op.attributes)\r\n }\r\n return newDelta\r\n }, new Delta())\r\n}\r\n\r\nfunction renderStyles(html) {\r\n let htmlString = html\r\n // Trim unnecessary parts.\r\n htmlString = htmlString.substring(\r\n htmlString.indexOf('<html '),\r\n htmlString.length,\r\n )\r\n htmlString = htmlString.substring(\r\n 0,\r\n htmlString.lastIndexOf('</html>') + '</html>'.length,\r\n )\r\n\r\n // Add temporary iframe.\r\n const iframe = document.createElement('iframe')\r\n iframe.style.display = 'none'\r\n document.body.appendChild(iframe)\r\n\r\n const iframeDoc = iframe.contentDocument || iframe.contentWindow.document\r\n iframeDoc.open()\r\n iframeDoc.write(htmlString)\r\n iframeDoc.close()\r\n\r\n let collection\r\n let pointer\r\n const rules\r\n = iframeDoc.styleSheets[iframeDoc.styleSheets.length - 1].cssRules\r\n\r\n // Convert internal styles to inline style of respective node.\r\n for (let idx = 0; idx < rules.length; idx++) {\r\n if ((rules[idx] as CSSStyleRule).selectorText === '') {\r\n continue\r\n }\r\n collection = iframeDoc.body.querySelectorAll(\r\n (rules[idx] as CSSStyleRule).selectorText,\r\n )\r\n\r\n for (pointer = 0; pointer < collection.length; pointer++) {\r\n collection[pointer].style.cssText += (\r\n rules[idx] as CSSStyleRule\r\n ).style.cssText\r\n }\r\n }\r\n\r\n // @ts-ignore\r\n const convertedString = iframeDoc.firstChild.outerHTML\r\n // Remove temporary iframe.\r\n iframe.parentNode.removeChild(iframe)\r\n\r\n return convertedString\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"custom-clipboard.es.js","sources":["../../../src/modules/custom-clipboard.ts"],"sourcesContent":["import type TypeClipboard from 'quill/modules/clipboard'\nimport type FluentEditor from '../fluent-editor'\nimport Quill from 'quill'\nimport {\n ERROR_IMAGE_PLACEHOLDER_CN,\n ERROR_IMAGE_PLACEHOLDER_EN,\n} from '../config/base64-image'\nimport { BIG_DELTA_LIMIT } from '../config/editor.config'\nimport {\n hexToRgbA,\n imageUrlToFile,\n isNullOrUndefined,\n omit,\n replaceDeltaImage,\n splitWithBreak,\n} from '../config/editor.utils'\nimport { isString } from '../utils/is'\n\nconst Clipboard = Quill.import('modules/clipboard') as typeof TypeClipboard\nconst Delta = Quill.import('delta')\n\nexport class CustomClipboard extends Clipboard {\n declare quill: FluentEditor\n\n prepareMatching(container: HTMLElement, nodeMatches) {\n const elementMatchers = []\n const textMatchers = []\n this.matchers.forEach((pair) => {\n const [selector, matcher] = pair\n if (selector === Node.TEXT_NODE) {\n textMatchers.push(matcher)\n }\n else if (selector === Node.ELEMENT_NODE) {\n elementMatchers.push(matcher)\n }\n else if (isString(selector)) {\n // word 的 v:shape 系列标签只能通过 getElementsByTagName 获取\n const vRegex = /v:(.+)/\n const nodeList = Array.from(\n vRegex.test(selector)\n ? container.getElementsByTagName(selector)\n : container.querySelectorAll(selector),\n )\n nodeList.forEach((node) => {\n if (nodeMatches.has(node)) {\n const matches = nodeMatches.get(node)\n matches.push(matcher)\n }\n else {\n nodeMatches.set(node, [matcher])\n }\n })\n }\n })\n return [elementMatchers, textMatchers]\n }\n\n onCaptureCopy(e, isCut = false) {\n if (e.defaultPrevented) {\n return\n }\n e.preventDefault()\n const [range] = this.quill.selection.getRange()\n if (isNullOrUndefined(range)) {\n return\n }\n const { html, text } = this.onCopy(range, isCut)\n\n // 兼容IE11浏览器`\n if (!e.clipboardData) {\n e.clipboardData = {\n types: 'text/plain',\n setData: (_type, value) => {\n // @ts-ignore\n return window.clipboardData.setData('Text', value)\n },\n }\n }\n\n // 复制代码时移除utf8中产生的不间断空格\\u00A0\n let plainText = text\n if (html.startsWith('<pre>')) {\n plainText = text.replace(/\\u00A0/g, ' ')\n }\n\n e.clipboardData.setData('text/html', html)\n e.clipboardData.setData('text/plain', plainText)\n if (isCut) {\n this.quill.deleteText(range, Quill.sources.USER)\n }\n }\n\n onCapturePaste(e: ClipboardEvent) {\n if (e.defaultPrevented || !this.quill.isEnabled()) {\n return\n }\n e.preventDefault()\n const range = this.quill.getSelection(true)\n if (isNullOrUndefined(range)) {\n return\n }\n\n // 兼容IE11浏览器\n if (!e.clipboardData) {\n // @ts-ignore\n e.clipboardData = {\n types: 'text/plain',\n getData: () => {\n // @ts-ignore\n return window.clipboardData.getData('Text')\n },\n }\n }\n\n const html = e.clipboardData.getData('text/html')\n const text = e.clipboardData.getData('text/plain')\n const files = Array.from(e.clipboardData.files || [])\n const msExcelCheck = /<meta.*?Microsoft Excel\\s[\\d].*?>/\n\n if (html.search(msExcelCheck) === -1 && files.length > 0) {\n this.quill.uploader.upload(range, files)\n }\n else {\n const msWordCheck1\n = /<meta\\s*name=\"?generator\"?\\s*content=\"?microsoft\\s*word\\s*\\d+\"?\\/?>/i\n const msWordCheck2 = /xmlns:o=\"urn:schemas-microsoft-com/i\n const result = { html, text, files, rtf: null }\n if (html.search(msExcelCheck) !== -1) {\n result.html = renderStyles(html)\n }\n if (msWordCheck1.test(html) || msWordCheck2.test(html)) {\n // TODO: 当word文档包含heading时text/rtf读取为空,无法获取hex图片,待修复。可参考ckeditor5/issues/2493\n result.rtf = e.clipboardData.getData('text/rtf')\n }\n this.onPaste(range, result)\n }\n }\n\n onPaste(range, { html, text, files: clipboardFiles, rtf }) {\n const hexImages = this.extractImageDataFromRtf(rtf)\n const rootBgColor = getComputedStyle(this.quill.root).backgroundColor\n const formats = this.quill.getFormat(range.index)\n let pastedDelta = this.convert({ text, html }, formats)\n pastedDelta = replaceDeltaWhiteSpace(pastedDelta, rootBgColor)\n const deltaLength = pastedDelta.ops.length\n\n let loadingTipsContainer\n if (deltaLength > BIG_DELTA_LIMIT) {\n loadingTipsContainer = this.quill.addContainer('ql-loading-tips')\n loadingTipsContainer.innerHTML = this.quill.getLangText('pasting')\n }\n\n const linePos = { index: range.index, length: range.length, fix: 0 }\n const [line, offset] = this.quill.getLine(range.index)\n\n const handlePasteContent = (content: any) => {\n const pastedContent = content\n\n const oldDelta = new Delta().retain(linePos.index).delete(linePos.length)\n const delta = oldDelta.concat(pastedContent)\n\n setTimeout(() => {\n this.quill.updateContents(delta, Quill.sources.USER)\n this.quill.setSelection(\n delta.length() - linePos.length - linePos.fix,\n Quill.sources.SILENT,\n )\n this.quill.scrollSelectionIntoView()\n if (loadingTipsContainer) {\n loadingTipsContainer.remove()\n }\n })\n }\n\n ;(async () => {\n try {\n const [files, placeholders, originalUrls, imageIndexs] = this.flipFilesArray(\n await this.extractFilesFromDelta(\n pastedDelta,\n clipboardFiles,\n hexImages,\n ),\n )\n\n if (files.length === 0) {\n handlePasteContent(pastedDelta)\n }\n else {\n if (this.quill.options.editorPaste && this.quill.options.editorPaste.observers.length !== 0) {\n // 设置editorPaste回调的情况\n this.quill.options.editorPaste.emit({\n files,\n callback: ({ code, message, data }) => {\n if (code === 0) {\n const { imageUrls } = data\n pastedDelta = replaceDeltaImage(\n pastedDelta,\n imageUrls,\n placeholders,\n )\n handlePasteContent(pastedDelta)\n }\n else {\n console.error('error message:', message)\n }\n },\n })\n }\n else {\n // 没有originalUrls 也没有文件粘贴\n if (files[0] !== undefined || originalUrls.length === 0) {\n // 没有设置editorPaste回调的情况下,File格式的占位图需要手动转换成url格式,插入到编辑器中\n const imageUrls = await this.files2urls(\n files,\n placeholders,\n originalUrls,\n pastedDelta,\n imageIndexs,\n )\n pastedDelta = replaceDeltaImage(\n pastedDelta,\n imageUrls,\n placeholders,\n )\n }\n handlePasteContent(pastedDelta)\n }\n }\n }\n catch (_e) {\n throw new Error('Paste failed.')\n }\n })()\n }\n\n files2urls(files: File[], placeholders, originalUrls, pastedDelta, imageIndexs) {\n return Promise.all(\n files.map(async (imageFile, index) => {\n const netImgExp = /^((http|https)\\:)?\\/\\/([\\s\\S]+)$/\n if (\n !placeholders[index]\n && originalUrls[index]\n && netImgExp.test(originalUrls[index])\n ) {\n // 不是占位图的普通url图片直接返回url\n return new Promise((resolve) => {\n resolve(originalUrls[index])\n })\n }\n else {\n const range = this.getImgSelection(pastedDelta, imageIndexs[index])\n this.quill.uploader.upload(range, [imageFile])\n }\n }),\n )\n }\n\n flipFilesArray(filesArr) {\n const files = []\n const placeholders = []\n const originalUrls = []\n const imageIndexs = []\n filesArr.forEach((item: any) => {\n if (item) {\n const [file, placeholder, originalUrl, imageIndex] = item\n files.push(file)\n placeholders.push(placeholder)\n originalUrls.push(originalUrl)\n if (imageIndex === 0 || imageIndex) {\n imageIndexs.push(imageIndex)\n }\n }\n })\n return [files, placeholders, originalUrls, imageIndexs]\n }\n\n // 将图片从hex转为base64\n convertHexToBase64(hexString) {\n return btoa(\n hexString\n .match(/\\w{2}/g)\n .map((char) => {\n return String.fromCharCode(Number.parseInt(char, 16))\n })\n .join(''),\n )\n }\n\n // 匹配rtf中的图片,存储为{hex, type}对象数组\n extractImageDataFromRtf(rtfData) {\n if (!rtfData) {\n return []\n }\n\n const regexPictureHeader\n = /{\\\\pict[\\s\\S]+?\\\\bliptag-?\\d+(\\\\blipupi-?\\d+)?({\\\\\\*\\\\blipuid\\s?[\\da-fA-F]+)?[\\s}]*?/\n const regexPicture = new RegExp(\n `(?:(${regexPictureHeader.source}))([\\\\da-fA-F\\\\s]+)\\\\}`,\n 'g',\n )\n const images = rtfData.match(regexPicture)\n const result = []\n\n if (images) {\n for (const image of images) {\n let imageType = ''\n\n if (image.includes('\\\\pngblip')) {\n imageType = 'image/png'\n }\n else if (image.includes('\\\\jpegblip')) {\n imageType = 'image/jpeg'\n }\n\n if (imageType) {\n result.push({\n hex: image\n .replace(regexPictureHeader, '')\n .replace(/[^\\da-fA-F]/g, ''),\n type: imageType,\n })\n }\n }\n }\n\n return result\n }\n\n extractFilesFromDelta(delta, clipboardFiles, hexImages?) {\n let index = -1\n return Promise.all(\n delta.map(async (op) => {\n index++\n const image = op.insert.image\n if (!image || image.hasExisted) {\n return\n }\n\n let file\n let isPlaceholderImage = false\n let imageIndex\n try {\n // hex 图片存在则为 file:/// 协议本地图片,使用 hex 图片转为 base64 读取\n const hexImage = hexImages.length && hexImages.shift()\n const newImage\n = hexImage\n && `data:${hexImage.type};base64,${this.convertHexToBase64(\n hexImage.hex,\n )}`\n imageIndex = index\n file = await imageUrlToFile(newImage || image.src || image)\n }\n catch (_err) {\n if (clipboardFiles.length !== 0) {\n // 跨域获取图片失败时从剪切板获取图片\n const clipboardFile = clipboardFiles[0]\n const imageType\n = clipboardFile.type?.indexOf('image') === -1\n ? 'image/png'\n : clipboardFile.type\n const blob = clipboardFile.slice(0, clipboardFile.size, imageType)\n file = new File([blob], `image-CORS-${new Date().getTime()}.png`, {\n type: imageType,\n })\n }\n else if (image.src.startsWith('http')) {\n // 什么都不做\n }\n else {\n // 剪切板中无图片,用失败占位图替换\n const errorImagePlaceholderJpg\n = this.quill.getLangText('img-error') === 'Image Copy Error'\n ? ERROR_IMAGE_PLACEHOLDER_EN\n : ERROR_IMAGE_PLACEHOLDER_CN\n file = await imageUrlToFile(errorImagePlaceholderJpg, true)\n isPlaceholderImage = true\n }\n }\n\n return [file, isPlaceholderImage, image, imageIndex]\n }),\n )\n }\n\n getImgSelection(delta, imageIndex) {\n let length = 0\n delta.ops.every((op, index) => {\n if (index === imageIndex) {\n return false\n }\n if (typeof op.insert === 'string') {\n length += op.insert.length\n }\n return true\n })\n const range = {\n index: length,\n length: 0,\n }\n return range\n }\n}\n\nfunction rebuildDelta(delta, cellLine) {\n const { cell: cellId, colspan, row: rowId, rowspan } = cellLine\n const buildedDelta = delta.reduce((newDelta, op) => {\n if (op.insert && typeof op.insert === 'string') {\n const lines = splitWithBreak(op.insert)\n\n lines.forEach((text) => {\n if (text === '\\n') {\n // 对换行增加 table-cell-line 格式,以避免表格断开\n newDelta.insert('\\n', {\n ...op.attributes,\n 'table-cell-line': { row: rowId, cell: cellId, rowspan, colspan },\n })\n }\n else {\n text = text.endsWith('\\r') ? text.slice(0, -1) : text\n newDelta.insert(\n text,\n omit(op.attributes, ['table', 'table-cell-line']),\n )\n }\n })\n }\n else {\n newDelta.insert(op.insert, op.attributes)\n }\n\n return newDelta\n }, new Delta())\n\n return buildedDelta\n}\n\nfunction replaceStrWhiteSpace(str) {\n const isWhiteSpace = value => /^(\\u3000|\\u0020){1}$/.test(value) // 空白字符\n let textWithWhiteSpace = ''\n let beginHasChar = false\n for (const char of str) {\n if (isWhiteSpace(char) && !beginHasChar) {\n textWithWhiteSpace += '\\u00A0'\n }\n else {\n textWithWhiteSpace += char\n beginHasChar = true\n }\n }\n return textWithWhiteSpace\n}\n\nfunction replaceDeltaWhiteSpace(delta, rootBgColor?) {\n return delta.reduce((newDelta, op) => {\n // fix: 当粘贴文字颜色和编辑器背景色一致且自身无背景色的情况下移除文字颜色样式,避免误导用户粘贴无效\n if (\n rootBgColor\n && op.attributes\n && op.attributes.color\n && !op.attributes.background\n ) {\n const originColor = op.attributes.color\n const fontColor\n = originColor.indexOf('#') === 0 ? hexToRgbA(originColor) : originColor\n if (\n fontColor === rootBgColor\n || (fontColor === 'rgba(255,255,255,1)'\n && rootBgColor === 'rgba(0, 0, 0, 0)')\n ) {\n delete op.attributes.color\n }\n }\n if (op.insert && typeof op.insert === 'string') {\n const lines = splitWithBreak(op.insert)\n let insertWithWhiteSpace = ''\n lines.forEach((text) => {\n insertWithWhiteSpace += replaceStrWhiteSpace(text)\n })\n newDelta.insert(insertWithWhiteSpace, op.attributes)\n }\n else {\n newDelta.insert(op.insert, op.attributes)\n }\n return newDelta\n }, new Delta())\n}\n\nfunction renderStyles(html) {\n let htmlString = html\n // Trim unnecessary parts.\n htmlString = htmlString.substring(\n htmlString.indexOf('<html '),\n htmlString.length,\n )\n htmlString = htmlString.substring(\n 0,\n htmlString.lastIndexOf('</html>') + '</html>'.length,\n )\n\n // Add temporary iframe.\n const iframe = document.createElement('iframe')\n iframe.style.display = 'none'\n document.body.appendChild(iframe)\n\n const iframeDoc = iframe.contentDocument || iframe.contentWindow.document\n iframeDoc.open()\n iframeDoc.write(htmlString)\n iframeDoc.close()\n\n let collection\n let pointer\n const rules\n = iframeDoc.styleSheets[iframeDoc.styleSheets.length - 1].cssRules\n\n // Convert internal styles to inline style of respective node.\n for (let idx = 0; idx < rules.length; idx++) {\n if ((rules[idx] as CSSStyleRule).selectorText === '') {\n continue\n }\n collection = iframeDoc.body.querySelectorAll(\n (rules[idx] as CSSStyleRule).selectorText,\n )\n\n for (pointer = 0; pointer < collection.length; pointer++) {\n collection[pointer].style.cssText += (\n rules[idx] as CSSStyleRule\n ).style.cssText\n }\n }\n\n // @ts-ignore\n const convertedString = iframeDoc.firstChild.outerHTML\n // Remove temporary iframe.\n iframe.parentNode.removeChild(iframe)\n\n return convertedString\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.es.js","sources":["../../../../../src/modules/custom-image/actions/action.ts"],"sourcesContent":["import type { BlotFormatter } from '../blot-formatter'\
|
|
1
|
+
{"version":3,"file":"action.es.js","sources":["../../../../../src/modules/custom-image/actions/action.ts"],"sourcesContent":["import type { BlotFormatter } from '../blot-formatter'\n\nexport class Action {\n formatter: BlotFormatter\n\n constructor(formatter: BlotFormatter) {\n this.formatter = formatter\n }\n\n onCreate() {}\n\n onDestroy() {}\n\n onUpdate() {}\n}\n"],"names":[],"mappings":";;;AAEO,MAAM,OAAO;AAAA,EAGlB,YAAY,WAA0B;AAFtC;AAGE,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,WAAW;AAAA,EAAC;AAAA,EAEZ,YAAY;AAAA,EAAC;AAAA,EAEb,WAAW;AAAA,EAAC;AACd;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-resize-action.es.js","sources":["../../../../../src/modules/custom-image/actions/custom-resize-action.ts"],"sourcesContent":["import { Action } from './action'\r\n\r\nconst MIN_WIDTH = 40\r\n\r\nfunction getElementStyle(element) {\r\n return element.currentStyle\r\n ? element.currentStyle\r\n : window.getComputedStyle(element, null)\r\n}\r\nexport class CustomResizeAction extends Action {\r\n topLeftHandle: HTMLElement\r\n topRightHandle: HTMLElement\r\n bottomRightHandle: HTMLElement\r\n bottomLeftHandle: HTMLElement\r\n dragHandle: HTMLElement\r\n dragStartX: number\r\n preDragWidth: number\r\n targetRatio: number\r\n maxWidth: number\r\n minWidth: number\r\n\r\n constructor(formatter) {\r\n super(formatter)\r\n this.topLeftHandle = this.createHandle('top-left', 'nwse-resize')\r\n this.topRightHandle = this.createHandle('top-right', 'nesw-resize')\r\n this.bottomRightHandle = this.createHandle('bottom-right', 'nwse-resize')\r\n this.bottomLeftHandle = this.createHandle('bottom-left', 'nesw-resize')\r\n this.dragHandle = null\r\n this.dragStartX = 0\r\n this.preDragWidth = 0\r\n this.targetRatio = 0\r\n this.maxWidth = 0\r\n this.minWidth = MIN_WIDTH\r\n }\r\n\r\n onCreate() {\r\n const target: any = this.formatter.currentSpec.getTargetElement()\r\n this.formatter.overlay.setAttribute('data-image', target.src)\r\n this.formatter.overlay.appendChild(this.topLeftHandle)\r\n this.formatter.overlay.appendChild(this.topRightHandle)\r\n this.formatter.overlay.appendChild(this.bottomRightHandle)\r\n this.formatter.overlay.appendChild(this.bottomLeftHandle)\r\n this.repositionHandles(this.formatter.options.resize.handleStyle)\r\n }\r\n\r\n onDestroy() {\r\n this.setCursor('')\r\n this.formatter.overlay.removeChild(this.topLeftHandle)\r\n this.formatter.overlay.removeChild(this.topRightHandle)\r\n this.formatter.overlay.removeChild(this.bottomRightHandle)\r\n this.formatter.overlay.removeChild(this.bottomLeftHandle)\r\n }\r\n\r\n createHandle(position: string, cursor: string): HTMLElement {\r\n const box = document.createElement('div')\r\n box.classList.add(this.formatter.options.resize.handleClassName)\r\n box.setAttribute('data-position', position)\r\n box.style.cursor = cursor\r\n\r\n if (this.formatter.options.resize.handleStyle) {\r\n Object.assign(box.style, this.formatter.options.resize.handleStyle)\r\n }\r\n\r\n box.addEventListener('mousedown', this.onMouseDown)\r\n return box\r\n }\r\n\r\n repositionHandles(handleStyle: any) {\r\n let handleXOffset = '0px'\r\n let handleYOffset = '0px'\r\n if (handleStyle) {\r\n if (handleStyle.width) {\r\n handleXOffset = `${-Number.parseFloat(handleStyle.width) / 2}px`\r\n }\r\n if (handleStyle.height) {\r\n handleYOffset = `${-Number.parseFloat(handleStyle.height) / 2}px`\r\n }\r\n }\r\n\r\n Object.assign(this.topLeftHandle.style, { left: handleXOffset, top: handleYOffset })\r\n Object.assign(this.topRightHandle.style, { right: handleXOffset, top: handleYOffset })\r\n Object.assign(this.bottomRightHandle.style, { right: handleXOffset, bottom: handleYOffset })\r\n Object.assign(this.bottomLeftHandle.style, { left: handleXOffset, bottom: handleYOffset })\r\n }\r\n\r\n setCursor(value: string) {\r\n if (document.body) {\r\n document.body.style.cursor = value\r\n }\r\n\r\n if (this.formatter.currentSpec) {\r\n const target = this.formatter.currentSpec.getOverlayElement()\r\n if (target) {\r\n target.style.cursor = value\r\n }\r\n }\r\n }\r\n\r\n onMouseDown = (event: MouseEvent) => {\r\n if (!(event.target instanceof HTMLElement)) {\r\n return\r\n }\r\n\r\n this.dragHandle = event.target\r\n this.setCursor(this.dragHandle.style.cursor)\r\n\r\n if (!this.formatter.currentSpec) {\r\n return\r\n }\r\n\r\n const target = this.formatter.currentSpec.getTargetElement()\r\n if (!target) {\r\n return\r\n }\r\n event.preventDefault()\r\n const rect = target.getBoundingClientRect()\r\n\r\n this.dragStartX = event.clientX\r\n this.preDragWidth = rect.width\r\n this.targetRatio = rect.height / rect.width\r\n\r\n let root: HTMLElement\r\n let rootStyle: any\r\n const tdWrap = this.findTd(target, 0)\r\n if (tdWrap) {\r\n root = tdWrap\r\n rootStyle = getElementStyle(tdWrap)\r\n }\r\n else {\r\n root = this.formatter.quill.root\r\n rootStyle = getElementStyle(root)\r\n }\r\n this.maxWidth = root.clientWidth\r\n - Number.parseFloat(rootStyle.paddingRight)\r\n - Number.parseFloat(rootStyle.paddingLeft)\r\n\r\n document.addEventListener('mousemove', this.onDrag)\r\n document.addEventListener('mouseup', this.onMouseUp)\r\n }\r\n\r\n findTd = (node: HTMLElement, level: number) => {\r\n if (level > 3) {\r\n return null\r\n }\r\n\r\n const tagName = node.tagName.toUpperCase()\r\n if (tagName === 'TD') {\r\n return node\r\n }\r\n else {\r\n const parentNode = node.parentElement\r\n if (parentNode) {\r\n return (this.findTd(parentNode, level += 1))\r\n }\r\n else {\r\n return null\r\n }\r\n }\r\n }\r\n\r\n onDrag = (event: MouseEvent) => {\r\n if (!this.formatter.currentSpec) {\r\n return\r\n }\r\n\r\n const target = this.formatter.currentSpec.getTargetElement()\r\n if (!target) {\r\n return\r\n }\r\n\r\n const deltaX = event.clientX - this.dragStartX\r\n let newWidth = 0\r\n\r\n if (this.dragHandle === this.topLeftHandle || this.dragHandle === this.bottomLeftHandle) {\r\n newWidth = Math.round(this.preDragWidth - deltaX)\r\n }\r\n else {\r\n newWidth = Math.round(this.preDragWidth + deltaX)\r\n }\r\n\r\n let minWidth = this.minWidth\r\n\r\n if (this.maxWidth < minWidth) {\r\n minWidth = this.maxWidth\r\n }\r\n\r\n if (newWidth > this.maxWidth) {\r\n newWidth = this.maxWidth\r\n }\r\n else if (newWidth < minWidth) {\r\n newWidth = minWidth\r\n }\r\n\r\n const newHeight = this.targetRatio * newWidth\r\n\r\n target.setAttribute('width', `${newWidth}`)\r\n target.setAttribute('height', `${newHeight}`)\r\n\r\n this.formatter.update()\r\n }\r\n\r\n onMouseUp = () => {\r\n this.setCursor('')\r\n document.removeEventListener('mousemove', this.onDrag)\r\n document.removeEventListener('mouseup', this.onMouseUp)\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"custom-resize-action.es.js","sources":["../../../../../src/modules/custom-image/actions/custom-resize-action.ts"],"sourcesContent":["import { Action } from './action'\n\nconst MIN_WIDTH = 40\n\nfunction getElementStyle(element) {\n return element.currentStyle\n ? element.currentStyle\n : window.getComputedStyle(element, null)\n}\nexport class CustomResizeAction extends Action {\n topLeftHandle: HTMLElement\n topRightHandle: HTMLElement\n bottomRightHandle: HTMLElement\n bottomLeftHandle: HTMLElement\n dragHandle: HTMLElement\n dragStartX: number\n preDragWidth: number\n targetRatio: number\n maxWidth: number\n minWidth: number\n\n constructor(formatter) {\n super(formatter)\n this.topLeftHandle = this.createHandle('top-left', 'nwse-resize')\n this.topRightHandle = this.createHandle('top-right', 'nesw-resize')\n this.bottomRightHandle = this.createHandle('bottom-right', 'nwse-resize')\n this.bottomLeftHandle = this.createHandle('bottom-left', 'nesw-resize')\n this.dragHandle = null\n this.dragStartX = 0\n this.preDragWidth = 0\n this.targetRatio = 0\n this.maxWidth = 0\n this.minWidth = MIN_WIDTH\n }\n\n onCreate() {\n const target: any = this.formatter.currentSpec.getTargetElement()\n this.formatter.overlay.setAttribute('data-image', target.src)\n this.formatter.overlay.appendChild(this.topLeftHandle)\n this.formatter.overlay.appendChild(this.topRightHandle)\n this.formatter.overlay.appendChild(this.bottomRightHandle)\n this.formatter.overlay.appendChild(this.bottomLeftHandle)\n this.repositionHandles(this.formatter.options.resize.handleStyle)\n }\n\n onDestroy() {\n this.setCursor('')\n this.formatter.overlay.removeChild(this.topLeftHandle)\n this.formatter.overlay.removeChild(this.topRightHandle)\n this.formatter.overlay.removeChild(this.bottomRightHandle)\n this.formatter.overlay.removeChild(this.bottomLeftHandle)\n }\n\n createHandle(position: string, cursor: string): HTMLElement {\n const box = document.createElement('div')\n box.classList.add(this.formatter.options.resize.handleClassName)\n box.setAttribute('data-position', position)\n box.style.cursor = cursor\n\n if (this.formatter.options.resize.handleStyle) {\n Object.assign(box.style, this.formatter.options.resize.handleStyle)\n }\n\n box.addEventListener('mousedown', this.onMouseDown)\n return box\n }\n\n repositionHandles(handleStyle: any) {\n let handleXOffset = '0px'\n let handleYOffset = '0px'\n if (handleStyle) {\n if (handleStyle.width) {\n handleXOffset = `${-Number.parseFloat(handleStyle.width) / 2}px`\n }\n if (handleStyle.height) {\n handleYOffset = `${-Number.parseFloat(handleStyle.height) / 2}px`\n }\n }\n\n Object.assign(this.topLeftHandle.style, { left: handleXOffset, top: handleYOffset })\n Object.assign(this.topRightHandle.style, { right: handleXOffset, top: handleYOffset })\n Object.assign(this.bottomRightHandle.style, { right: handleXOffset, bottom: handleYOffset })\n Object.assign(this.bottomLeftHandle.style, { left: handleXOffset, bottom: handleYOffset })\n }\n\n setCursor(value: string) {\n if (document.body) {\n document.body.style.cursor = value\n }\n\n if (this.formatter.currentSpec) {\n const target = this.formatter.currentSpec.getOverlayElement()\n if (target) {\n target.style.cursor = value\n }\n }\n }\n\n onMouseDown = (event: MouseEvent) => {\n if (!(event.target instanceof HTMLElement)) {\n return\n }\n\n this.dragHandle = event.target\n this.setCursor(this.dragHandle.style.cursor)\n\n if (!this.formatter.currentSpec) {\n return\n }\n\n const target = this.formatter.currentSpec.getTargetElement()\n if (!target) {\n return\n }\n event.preventDefault()\n const rect = target.getBoundingClientRect()\n\n this.dragStartX = event.clientX\n this.preDragWidth = rect.width\n this.targetRatio = rect.height / rect.width\n\n let root: HTMLElement\n let rootStyle: any\n const tdWrap = this.findTd(target, 0)\n if (tdWrap) {\n root = tdWrap\n rootStyle = getElementStyle(tdWrap)\n }\n else {\n root = this.formatter.quill.root\n rootStyle = getElementStyle(root)\n }\n this.maxWidth = root.clientWidth\n - Number.parseFloat(rootStyle.paddingRight)\n - Number.parseFloat(rootStyle.paddingLeft)\n\n document.addEventListener('mousemove', this.onDrag)\n document.addEventListener('mouseup', this.onMouseUp)\n }\n\n findTd = (node: HTMLElement, level: number) => {\n if (level > 3) {\n return null\n }\n\n const tagName = node.tagName.toUpperCase()\n if (tagName === 'TD') {\n return node\n }\n else {\n const parentNode = node.parentElement\n if (parentNode) {\n return (this.findTd(parentNode, level += 1))\n }\n else {\n return null\n }\n }\n }\n\n onDrag = (event: MouseEvent) => {\n if (!this.formatter.currentSpec) {\n return\n }\n\n const target = this.formatter.currentSpec.getTargetElement()\n if (!target) {\n return\n }\n\n const deltaX = event.clientX - this.dragStartX\n let newWidth = 0\n\n if (this.dragHandle === this.topLeftHandle || this.dragHandle === this.bottomLeftHandle) {\n newWidth = Math.round(this.preDragWidth - deltaX)\n }\n else {\n newWidth = Math.round(this.preDragWidth + deltaX)\n }\n\n let minWidth = this.minWidth\n\n if (this.maxWidth < minWidth) {\n minWidth = this.maxWidth\n }\n\n if (newWidth > this.maxWidth) {\n newWidth = this.maxWidth\n }\n else if (newWidth < minWidth) {\n newWidth = minWidth\n }\n\n const newHeight = this.targetRatio * newWidth\n\n target.setAttribute('width', `${newWidth}`)\n target.setAttribute('height', `${newHeight}`)\n\n this.formatter.update()\n }\n\n onMouseUp = () => {\n this.setCursor('')\n document.removeEventListener('mousemove', this.onDrag)\n document.removeEventListener('mouseup', this.onMouseUp)\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete-action.es.js","sources":["../../../../../src/modules/custom-image/actions/delete-action.ts"],"sourcesContent":["import type { Parchment as TypeParchment } from 'quill'\
|
|
1
|
+
{"version":3,"file":"delete-action.es.js","sources":["../../../../../src/modules/custom-image/actions/delete-action.ts"],"sourcesContent":["import type { Parchment as TypeParchment } from 'quill'\nimport Quill from 'quill'\nimport { Action } from './action'\n\nexport class DeleteAction extends Action {\n onCreate() {\n document.addEventListener('keyup', this.onKeyUp, true)\n this.formatter.quill.root.addEventListener('input', this.onKeyUp, true)\n }\n\n onDestroy() {\n document.removeEventListener('keyup', this.onKeyUp)\n this.formatter.quill.root.removeEventListener('input', this.onKeyUp)\n }\n\n onKeyUp = (event: any) => {\n if (!this.formatter.currentSpec) {\n return\n }\n\n // delete or backspace\n if (event.keyCode === 46 || event.keyCode === 8) {\n const blot = Quill.find(this.formatter.currentSpec.getTargetElement()) as TypeParchment.Blot\n if (blot) {\n // TODO: fix later\n // @ts-ignore\n blot.deleteAt(0)\n }\n this.formatter.hide()\n }\n }\n}\n"],"names":[],"mappings":";;;;;AAIO,MAAM,qBAAqB,OAAO;AAAA,EAAlC;AAAA;AAWL,mCAAU,CAAC,UAAe;AACxB,UAAI,CAAC,KAAK,UAAU,aAAa;AAC/B;AAAA,MACF;AAGA,UAAI,MAAM,YAAY,MAAM,MAAM,YAAY,GAAG;AAC/C,cAAM,OAAO,MAAM,KAAK,KAAK,UAAU,YAAY,kBAAkB;AACrE,YAAI,MAAM;AAGR,eAAK,SAAS,CAAC;AAAA,QACjB;AACA,aAAK,UAAU,KAAA;AAAA,MACjB;AAAA,IACF;AAAA;AAAA,EAzBA,WAAW;AACT,aAAS,iBAAiB,SAAS,KAAK,SAAS,IAAI;AACrD,SAAK,UAAU,MAAM,KAAK,iBAAiB,SAAS,KAAK,SAAS,IAAI;AAAA,EACxE;AAAA,EAEA,YAAY;AACV,aAAS,oBAAoB,SAAS,KAAK,OAAO;AAClD,SAAK,UAAU,MAAM,KAAK,oBAAoB,SAAS,KAAK,OAAO;AAAA,EACrE;AAkBF;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blot-formatter.es.js","sources":["../../../../src/modules/custom-image/blot-formatter.ts"],"sourcesContent":["import type FluentEditor from '../../core/fluent-editor'\
|
|
1
|
+
{"version":3,"file":"blot-formatter.es.js","sources":["../../../../src/modules/custom-image/blot-formatter.ts"],"sourcesContent":["import type FluentEditor from '../../core/fluent-editor'\nimport type { Action } from './actions'\nimport type { BlotFormatterOptions } from './options'\nimport type { BlotSpec } from './specs'\nimport Quill from 'quill'\nimport { merge as deepmerge } from '../../utils/merge'\nimport { CustomImage } from './image'\nimport DefaultOptions from './options'\nimport { CustomImageSpec } from './specs'\n\nconst dontMerge = (_destination: Array<any>, source: Array<any>) => source\n\nexport class BlotFormatter {\n options: BlotFormatterOptions\n currentSpec: BlotSpec\n specs: BlotSpec[]\n overlay: HTMLElement\n actions: Action[]\n observer: MutationObserver\n\n static register() {\n Quill.register({\n 'formats/image': CustomImage,\n 'modules/image-spec': CustomImageSpec,\n }, true)\n }\n\n constructor(public quill: FluentEditor, options: Partial<BlotFormatterOptions> = {}) {\n this.options = deepmerge({}, DefaultOptions, options, { arrayMerge: dontMerge })\n if (options.allowInvalidUrl !== undefined) {\n this.options.allowInvalidUrl = options.allowInvalidUrl\n }\n CustomImage.setOptions(this.options.allowInvalidUrl)\n this.currentSpec = null\n this.actions = []\n this.overlay = document.createElement('div')\n this.overlay.classList.add(this.options.overlay.className)\n if (this.options.overlay.style) {\n Object.assign(this.overlay.style, this.options.overlay.style)\n }\n\n // disable native image resizing on firefox\n document.execCommand('enableObjectResizing', false, 'false') // eslint-disable-next-line-line no-undef\n this.quill.root.addEventListener('click', this.onClick)\n this.specs = this.options.specs.map((SpecClass: any) => new SpecClass(this))\n this.specs.forEach(spec => spec.init())\n }\n\n show(spec: BlotSpec) {\n this.currentSpec = spec\n this.currentSpec.setSelection()\n this.setUserSelect('none')\n this.quill.root.parentNode.appendChild(this.overlay)\n this.repositionOverlay()\n this.createActions(spec)\n\n // fix: 图片对齐之后,虚线外框应该跟随移动\n const imageDom = spec.getTargetElement()\n const win: any = window\n const MutationObserver: typeof window.MutationObserver = win.MutationObserver || win.WebKitMutationObserver || win.MozMutationObserver\n const element = imageDom.parentNode\n this.observer = new MutationObserver((mutationList) => {\n for (const mutation of mutationList) {\n const target = mutation.target as HTMLElement\n const image = target.querySelector('img')\n if (image) {\n this.repositionOverlay()\n }\n }\n })\n this.observer.observe(element, {\n attributes: true,\n attributeFilter: ['class'],\n attributeOldValue: true,\n subtree: true,\n })\n }\n\n hide() {\n if (!this.currentSpec) {\n return\n }\n\n const imgDom = this.currentSpec.getTargetElement()\n if (imgDom) {\n imgDom.classList.remove('current-select-img')\n }\n\n this.currentSpec.onHide()\n this.currentSpec = null\n this.quill.root.parentNode.removeChild(this.overlay)\n this.overlay.style.setProperty('display', 'none')\n this.setUserSelect('')\n this.destroyActions()\n }\n\n update() {\n this.repositionOverlay()\n this.actions.forEach(action => action.onUpdate())\n }\n\n createActions(spec: BlotSpec) {\n this.actions = spec.getActions().map((ActionClass: any) => {\n const action: Action = new ActionClass(this)\n action.onCreate()\n return action\n })\n }\n\n destroyActions() {\n this.actions.forEach((action: Action) => action.onDestroy())\n this.actions = []\n }\n\n repositionOverlay() {\n if (!this.currentSpec) {\n return\n }\n\n const overlayTarget = this.currentSpec.getOverlayElement()\n if (!overlayTarget) {\n return\n }\n\n const parent = this.quill.root.parentElement\n const specRect = overlayTarget.getBoundingClientRect()\n const parentRect = parent.getBoundingClientRect()\n\n Object.assign(this.overlay.style, {\n display: 'block',\n left: `${specRect.left - parentRect.left - 1 + parent.scrollLeft}px`,\n top: `${specRect.top - parentRect.top + parent.scrollTop}px`,\n width: `${specRect.width}px`,\n height: `${specRect.height}px`,\n })\n }\n\n setUserSelect(value: string) {\n const props: string[] = [\n 'userSelect',\n 'mozUserSelect',\n 'webkitUserSelect',\n 'msUserSelect',\n ]\n\n props.forEach((prop: string) => {\n // set on contenteditable element and <html>\n this.quill.root.style.setProperty(prop, value)\n if (document.documentElement) {\n document.documentElement.style.setProperty(prop, value)\n }\n })\n }\n\n onClick = () => {\n this.hide()\n }\n}\n"],"names":["deepmerge"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.es.js","sources":["../../../../src/modules/custom-image/image.ts"],"sourcesContent":["import type { Parchment as TypeParchment } from 'quill'\
|
|
1
|
+
{"version":3,"file":"image.es.js","sources":["../../../../src/modules/custom-image/image.ts"],"sourcesContent":["import type { Parchment as TypeParchment } from 'quill'\nimport type TypeEmbed from 'quill/blots/embed'\nimport Quill from 'quill'\nimport { isNullOrUndefined, sanitize } from '../../config/editor.utils'\nimport { isObject } from '../../utils/is'\nimport { ALIGN_ATTR, alignmentHandler } from './actions'\n\nconst Embed = Quill.import('blots/embed') as typeof TypeEmbed\nconst ATTRIBUTES = ['alt', 'height', 'width', 'image-id']\n\nexport type ImageValue = string | {\n src: string\n align?: string\n height?: number\n width?: number\n}\nexport class CustomImage extends Embed {\n static blotName = 'image'\n static tagName = 'IMG'\n static ID_SEED = 0\n static allowInvalidUrl: boolean = false\n declare domNode: HTMLElement\n\n static setOptions(allowInvalidUrl: boolean) {\n this.allowInvalidUrl = allowInvalidUrl\n }\n\n static create(value: ImageValue) {\n const node = super.create(value) as HTMLElement\n const url = typeof value === 'string' ? value : value.src\n if (url) {\n const imgURL = this.sanitize(url)\n if (!imgURL?.startsWith('data:image')) {\n node.dataset.src = imgURL\n }\n node.setAttribute('src', imgURL)\n }\n node.setAttribute('data-image-id', `img${CustomImage.ID_SEED++}`)\n node.style.verticalAlign = 'baseline'\n if (isObject(value)) {\n if (value.align && alignmentHandler[value.align]) {\n node.setAttribute(ALIGN_ATTR, value.align)\n alignmentHandler[value.align](node)\n }\n if (value.width) {\n node.setAttribute('width', String(value.width))\n }\n if (value.height) {\n node.setAttribute('height', String(value.height))\n }\n }\n return node\n }\n\n static formats(domNode: HTMLElement) {\n return ATTRIBUTES.reduce((formats, attribute) => {\n if (domNode.hasAttribute(attribute)) {\n formats[attribute] = domNode.getAttribute(attribute)\n }\n return formats\n }, {})\n }\n\n static match(url: string) {\n return /\\.(jpe?g|gif|png)$/.test(url) || /^data:image\\/.+;base64/.test(url)\n }\n\n static register() {\n if (/Firefox/i.test(navigator.userAgent)) {\n setTimeout(() => {\n // Disable image resizing in Firefox\n document.execCommand('enableObjectResizing', false, 'false')\n }, 1)\n }\n }\n\n static sanitize(url: string) {\n if (sanitize(url, ['http', 'https', 'blob', 'data']) || this.allowInvalidUrl) {\n return url\n }\n return '//:0'\n }\n\n static value(domNode: HTMLElement) {\n const formats: any = {}\n const imageSrc = domNode.getAttribute('src')\n formats.src = this.sanitize(imageSrc)\n formats.imageId = domNode.dataset.imageId\n if (domNode.dataset.align) {\n formats.align = domNode.dataset.align\n }\n if (domNode.hasAttribute('width')) {\n formats.width = domNode.getAttribute('width')\n }\n if (domNode.hasAttribute('height')) {\n formats.height = domNode.getAttribute('height')\n }\n return formats\n }\n\n format(name: string, value: any) {\n if (ATTRIBUTES.includes(name)) {\n if (value) {\n this.domNode.setAttribute(name, value)\n }\n else {\n this.domNode.removeAttribute(name)\n }\n }\n else {\n super.format(name, value)\n }\n }\n\n unWrap() {\n this.parent.replaceWith(this as TypeEmbed)\n }\n\n wrap(name: string, value?: any): TypeParchment.Parent\n wrap(wrapper: TypeParchment.Parent): TypeParchment.Parent\n wrap(name: string | TypeParchment.Parent, value?: any) {\n const wrapper = (typeof name === 'string' ? this.scroll.create(name, value) : name) as TypeParchment.Parent\n if (!isNullOrUndefined(this.parent)) {\n this.parent.insertBefore(wrapper, this.next || undefined)\n }\n if (typeof wrapper.appendChild !== 'function') {\n throw new TypeError(`Cannot wrap ${name}`)\n }\n wrapper.appendChild(this)\n return wrapper\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.es.js","sources":["../../../../src/modules/custom-image/options.ts"],"sourcesContent":["import type { ImageToolbar, ImageToolbarButtons } from './actions'\
|
|
1
|
+
{"version":3,"file":"options.es.js","sources":["../../../../src/modules/custom-image/options.ts"],"sourcesContent":["import type { ImageToolbar, ImageToolbarButtons } from './actions'\nimport type { BlotSpec } from './specs'\nimport { ImageSpec } from './specs'\n\nexport interface OverlayOptions {\n // classname applied to the overlay element\n className: string\n // style applied to overlay element, or null to prevent styles\n style: Record<string, string>\n}\n\nexport interface ResizeOptions {\n // class name applied to the resize handles\n handleClassName: string\n // style applied to resize handles, or null to prevent styles\n handleStyle: Record<string, string>\n}\n\nexport interface ToolButtonOption {\n name: string\n icon: string\n isActive?: (el: HTMLElement) => boolean\n apply: (this: ImageToolbar, el: HTMLImageElement, toolbarButtons: ImageToolbarButtons) => void\n}\n\nexport interface ToolbarButtonOptions {\n buttons: Record<string, ToolButtonOption | boolean>\n}\n\nexport interface ToolbarOptions extends ToolbarButtonOptions {\n // class name applied to the root toolbar element\n mainClassName: string\n // style applied to root toolbar element, or null to prevent styles\n mainStyle: Record<string, unknown>\n // class name applied to each button in the toolbar\n buttonClassName: string\n /* whether or not to add the selected style to the buttons.\n they'll always get the is-selected class */\n addButtonSelectStyle: boolean\n // style applied to buttons, or null to prevent styles\n buttonStyle: Record<string, unknown>\n // style applied to the svgs in the buttons\n svgStyle: Record<string, unknown>\n}\n\nexport interface BlotFormatterOptionsInput {\n specs: typeof BlotSpec[]\n overlay: Partial<OverlayOptions>\n resize: Partial<ResizeOptions>\n toolbar: Partial<ToolbarOptions>\n}\nexport interface BlotFormatterOptions {\n specs: typeof BlotSpec[]\n overlay: OverlayOptions\n resize: ResizeOptions\n toolbar: ToolbarOptions\n allowInvalidUrl: boolean\n}\n\nexport const LEFT_ALIGN = 'align-left'\nexport const CENTER_ALIGN = 'align-center'\nexport const RIGHT_ALIGN = 'align-right'\nexport const COPY = 'copy'\nexport const DOWNLOAD = 'download'\nconst DefaultOptions: BlotFormatterOptions = {\n // 默认情况下,`file://` 格式的本地文件路径在浏览器环境无法读取,因此会被转换成 `//:0`,但是在一些特殊的场景下(比如:Electron),需要获取到图片的原始路径,进行后续的上传处理\n // 注意:该选项一旦设置为 true,本地磁盘路径会暴露出去,这可能会带来安全风险,请确保你了解相关的安全隐患\n allowInvalidUrl: false,\n\n specs: [\n ImageSpec,\n ],\n overlay: {\n className: 'blot-formatter__overlay',\n style: {\n position: 'absolute',\n boxSizing: 'border-box',\n border: '1px dashed #444',\n },\n },\n toolbar: {\n mainClassName: 'blot-formatter__toolbar',\n mainStyle: {\n position: 'absolute',\n top: '-12px',\n right: '0',\n left: '0',\n height: '0',\n minWidth: '120px',\n font: '12px/1.0 Arial, Helvetica, sans-serif',\n textAlign: 'center',\n color: '#333',\n boxSizing: 'border-box',\n cursor: 'default',\n zIndex: '1',\n },\n buttonClassName: 'blot-formatter__toolbar-button',\n addButtonSelectStyle: true,\n buttonStyle: {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '24px',\n height: '24px',\n background: 'white',\n border: '1px solid #999',\n verticalAlign: 'middle',\n cursor: 'pointer',\n },\n svgStyle: {\n display: 'inline-block',\n width: '16px',\n height: '16px',\n background: 'white',\n verticalAlign: 'middle',\n },\n buttons: {\n [LEFT_ALIGN]: true,\n [CENTER_ALIGN]: true,\n [RIGHT_ALIGN]: true,\n [COPY]: true,\n [DOWNLOAD]: true,\n },\n },\n resize: {\n handleClassName: 'blot-formatter__resize-handle',\n handleStyle: {\n position: 'absolute',\n height: '12px',\n width: '12px',\n backgroundColor: 'white',\n border: '1px solid #777',\n boxSizing: 'border-box',\n opacity: '0.80',\n },\n },\n}\n\nexport default DefaultOptions\n"],"names":[],"mappings":";;AA2DO,MAAM,aAAa;AACnB,MAAM,eAAe;AACrB,MAAM,cAAc;AACpB,MAAM,OAAO;AACb,MAAM,WAAW;AACxB,MAAM,iBAAuC;AAAA;AAAA;AAAA,EAG3C,iBAAiB;AAAA,EAEjB,OAAO;AAAA,IACL;AAAA,EAAA;AAAA,EAEF,SAAS;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,MACX,QAAQ;AAAA,IAAA;AAAA,EACV;AAAA,EAEF,SAAS;AAAA,IACP,eAAe;AAAA,IACf,WAAW;AAAA,MACT,UAAU;AAAA,MACV,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,MAAM;AAAA,MACN,WAAW;AAAA,MACX,OAAO;AAAA,MACP,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,QAAQ;AAAA,IAAA;AAAA,IAEV,iBAAiB;AAAA,IACjB,sBAAsB;AAAA,IACtB,aAAa;AAAA,MACX,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,eAAe;AAAA,MACf,QAAQ;AAAA,IAAA;AAAA,IAEV,UAAU;AAAA,MACR,SAAS;AAAA,MACT,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,eAAe;AAAA,IAAA;AAAA,IAEjB,SAAS;AAAA,MACP,CAAC,UAAU,GAAG;AAAA,MACd,CAAC,YAAY,GAAG;AAAA,MAChB,CAAC,WAAW,GAAG;AAAA,MACf,CAAC,IAAI,GAAG;AAAA,MACR,CAAC,QAAQ,GAAG;AAAA,IAAA;AAAA,EACd;AAAA,EAEF,QAAQ;AAAA,IACN,iBAAiB;AAAA,IACjB,aAAa;AAAA,MACX,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blot-spec.es.js","sources":["../../../../../src/modules/custom-image/specs/blot-spec.ts"],"sourcesContent":["import type { BlotFormatter } from '../blot-formatter'\
|
|
1
|
+
{"version":3,"file":"blot-spec.es.js","sources":["../../../../../src/modules/custom-image/specs/blot-spec.ts"],"sourcesContent":["import type { BlotFormatter } from '../blot-formatter'\nimport { CustomResizeAction, DeleteAction, ImageToolbarAction } from '../actions'\n\nexport class BlotSpec {\n formatter: BlotFormatter\n\n constructor(formatter: BlotFormatter) {\n this.formatter = formatter\n }\n\n init(): void {}\n\n getActions() {\n return [ImageToolbarAction, CustomResizeAction, DeleteAction]\n }\n\n getTargetElement(): HTMLElement | null {\n return null\n }\n\n getOverlayElement() {\n return this.getTargetElement()\n }\n\n setSelection(): void {\n this.formatter.quill.setSelection(null)\n }\n\n onHide() {}\n}\n"],"names":[],"mappings":";;;;;;;AAGO,MAAM,SAAS;AAAA,EAGpB,YAAY,WAA0B;AAFtC;AAGE,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,OAAa;AAAA,EAAC;AAAA,EAEd,aAAa;AACX,WAAO,CAAC,oBAAoB,oBAAoB,YAAY;AAAA,EAC9D;AAAA,EAEA,mBAAuC;AACrC,WAAO;AAAA,EACT;AAAA,EAEA,oBAAoB;AAClB,WAAO,KAAK,iBAAA;AAAA,EACd;AAAA,EAEA,eAAqB;AACnB,SAAK,UAAU,MAAM,aAAa,IAAI;AAAA,EACxC;AAAA,EAEA,SAAS;AAAA,EAAC;AACZ;"}
|