@opentiny/fluent-editor 4.0.0-alpha.10 → 4.0.0-alpha.11
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/es/config/editor.utils.es.js.map +1 -1
- package/es/config/i18n/en-us.es.js +2 -0
- package/es/config/i18n/en-us.es.js.map +1 -1
- package/es/config/i18n/zh-cn.es.js +2 -0
- package/es/config/i18n/zh-cn.es.js.map +1 -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 +17 -13
- package/es/fluent-editor.es.js.map +1 -1
- package/es/formats/soft-break.es.js.map +1 -1
- package/es/formats/video.es.js.map +1 -1
- package/es/index.es.js +4 -0
- package/es/index.es.js.map +1 -1
- package/es/modules/ai/constants.es.js.map +1 -1
- package/es/modules/ai/index.es.js +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/actions/image-toolbar-buttons.es.js +1 -1
- package/es/modules/custom-image/actions/image-toolbar-buttons.es.js.map +1 -1
- package/es/modules/custom-image/actions/toolbar-action.es.js.map +1 -1
- package/es/modules/custom-image/actions/toolbar.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/custom-uploader.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 +102 -0
- package/es/modules/flow-chart/config-utils.es.js.map +1 -0
- package/es/modules/flow-chart/formats/flow-chart-blot.es.js +369 -0
- package/es/modules/flow-chart/formats/flow-chart-blot.es.js.map +1 -0
- package/es/modules/flow-chart/i18n/en-us.es.js +30 -0
- package/es/modules/flow-chart/i18n/en-us.es.js.map +1 -0
- package/es/modules/flow-chart/i18n/index.es.js +12 -0
- package/es/modules/flow-chart/i18n/index.es.js.map +1 -0
- package/es/modules/flow-chart/i18n/zh-cn.es.js +30 -0
- package/es/modules/flow-chart/i18n/zh-cn.es.js.map +1 -0
- package/es/modules/flow-chart/icons.es.js +27 -0
- package/es/modules/flow-chart/icons.es.js.map +1 -0
- package/es/modules/flow-chart/index.es.js +45 -0
- package/es/modules/flow-chart/index.es.js.map +1 -0
- package/es/modules/flow-chart/modules/context-menu.es.js +184 -0
- package/es/modules/flow-chart/modules/context-menu.es.js.map +1 -0
- package/es/modules/flow-chart/modules/control-panel.es.js +286 -0
- package/es/modules/flow-chart/modules/control-panel.es.js.map +1 -0
- package/es/modules/flow-chart/modules/custom-resize-action.es.js +150 -0
- package/es/modules/flow-chart/modules/custom-resize-action.es.js.map +1 -0
- package/es/modules/flow-chart/style/flow-chart.css +185 -0
- package/es/modules/i18n.es.js.map +1 -1
- package/es/modules/index.es.js +4 -0
- package/es/modules/index.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/module.es.js.map +1 -1
- package/es/modules/mathlive/tooltip.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 +108 -0
- package/es/modules/mind-map/config-utils.es.js.map +1 -0
- package/es/modules/mind-map/formats/mind-map-blot.es.js +356 -0
- package/es/modules/mind-map/formats/mind-map-blot.es.js.map +1 -0
- package/es/modules/mind-map/i18n/en-us.es.js +29 -0
- package/es/modules/mind-map/i18n/en-us.es.js.map +1 -0
- package/es/modules/mind-map/i18n/index.es.js +12 -0
- package/es/modules/mind-map/i18n/index.es.js.map +1 -0
- package/es/modules/mind-map/i18n/zh-cn.es.js +29 -0
- package/es/modules/mind-map/i18n/zh-cn.es.js.map +1 -0
- package/es/modules/mind-map/icons.es.js +45 -0
- package/es/modules/mind-map/icons.es.js.map +1 -0
- package/es/modules/mind-map/index.es.js +56 -0
- package/es/modules/mind-map/index.es.js.map +1 -0
- package/es/modules/mind-map/modules/context-menu.es.js +128 -0
- package/es/modules/mind-map/modules/context-menu.es.js.map +1 -0
- package/es/modules/mind-map/modules/control-panel.es.js +424 -0
- package/es/modules/mind-map/modules/control-panel.es.js.map +1 -0
- package/es/modules/mind-map/modules/custom-resize-action.es.js +161 -0
- package/es/modules/mind-map/modules/custom-resize-action.es.js.map +1 -0
- package/es/modules/mind-map/style/mind-map.css +224 -0
- package/es/modules/shortcut-key/index.es.js +16 -0
- package/es/modules/shortcut-key/index.es.js.map +1 -1
- package/es/modules/syntax.es.js.map +1 -1
- package/es/modules/table-up/index.es.js.map +1 -1
- package/es/modules/toolbar/better-picker.es.js.map +1 -1
- package/es/modules/toolbar/better-toolbar.es.js.map +1 -1
- package/es/modules/toolbar/toolbar-tip.es.js.map +1 -1
- package/es/themes/snow.es.js.map +1 -1
- package/es/tools/format-painter.es.js.map +1 -1
- package/es/tools/fullscreen.es.js.map +1 -1
- package/es/tools/screenshot.es.js.map +1 -1
- package/es/ui/icons.config.es.js +4 -0
- package/es/ui/icons.config.es.js.map +1 -1
- package/es/ui/icons.es.js +4 -2
- package/es/ui/icons.es.js.map +1 -1
- package/es/utils/debounce.es.js.map +1 -1
- package/es/utils/image.es.js.map +1 -1
- package/es/utils/is.es.js.map +1 -1
- package/es/utils/method.es.js.map +1 -1
- package/es/utils/scroll-lock.es.js.map +1 -1
- package/lib/config/editor.utils.cjs.js.map +1 -1
- package/lib/config/i18n/en-us.cjs.js +2 -0
- package/lib/config/i18n/en-us.cjs.js.map +1 -1
- package/lib/config/i18n/zh-cn.cjs.js +2 -0
- package/lib/config/i18n/zh-cn.cjs.js.map +1 -1
- 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 +23 -19
- package/lib/fluent-editor.cjs.js.map +1 -1
- package/lib/formats/soft-break.cjs.js.map +1 -1
- package/lib/formats/video.cjs.js.map +1 -1
- package/lib/index.cjs.js +9 -5
- package/lib/index.cjs.js.map +1 -1
- package/lib/modules/ai/constants.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/actions/image-toolbar-buttons.cjs.js.map +1 -1
- package/lib/modules/custom-image/actions/toolbar-action.cjs.js.map +1 -1
- package/lib/modules/custom-image/actions/toolbar.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/custom-uploader.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 +102 -0
- package/lib/modules/flow-chart/config-utils.cjs.js.map +1 -0
- package/lib/modules/flow-chart/formats/flow-chart-blot.cjs.js +369 -0
- package/lib/modules/flow-chart/formats/flow-chart-blot.cjs.js.map +1 -0
- package/lib/modules/flow-chart/i18n/en-us.cjs.js +30 -0
- package/lib/modules/flow-chart/i18n/en-us.cjs.js.map +1 -0
- package/lib/modules/flow-chart/i18n/index.cjs.js +12 -0
- package/lib/modules/flow-chart/i18n/index.cjs.js.map +1 -0
- package/lib/modules/flow-chart/i18n/zh-cn.cjs.js +30 -0
- package/lib/modules/flow-chart/i18n/zh-cn.cjs.js.map +1 -0
- package/lib/modules/flow-chart/icons.cjs.js +27 -0
- package/lib/modules/flow-chart/icons.cjs.js.map +1 -0
- package/lib/modules/flow-chart/index.cjs.js +45 -0
- package/lib/modules/flow-chart/index.cjs.js.map +1 -0
- package/lib/modules/flow-chart/modules/context-menu.cjs.js +184 -0
- package/lib/modules/flow-chart/modules/context-menu.cjs.js.map +1 -0
- package/lib/modules/flow-chart/modules/control-panel.cjs.js +286 -0
- package/lib/modules/flow-chart/modules/control-panel.cjs.js.map +1 -0
- package/lib/modules/flow-chart/modules/custom-resize-action.cjs.js +150 -0
- package/lib/modules/flow-chart/modules/custom-resize-action.cjs.js.map +1 -0
- package/lib/modules/flow-chart/style/flow-chart.css +185 -0
- package/lib/modules/i18n.cjs.js.map +1 -1
- package/lib/modules/index.cjs.js +9 -5
- package/lib/modules/index.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/module.cjs.js.map +1 -1
- package/lib/modules/mathlive/tooltip.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 +108 -0
- package/lib/modules/mind-map/config-utils.cjs.js.map +1 -0
- package/lib/modules/mind-map/formats/mind-map-blot.cjs.js +356 -0
- package/lib/modules/mind-map/formats/mind-map-blot.cjs.js.map +1 -0
- package/lib/modules/mind-map/i18n/en-us.cjs.js +29 -0
- package/lib/modules/mind-map/i18n/en-us.cjs.js.map +1 -0
- package/lib/modules/mind-map/i18n/index.cjs.js +12 -0
- package/lib/modules/mind-map/i18n/index.cjs.js.map +1 -0
- package/lib/modules/mind-map/i18n/zh-cn.cjs.js +29 -0
- package/lib/modules/mind-map/i18n/zh-cn.cjs.js.map +1 -0
- package/lib/modules/mind-map/icons.cjs.js +45 -0
- package/lib/modules/mind-map/icons.cjs.js.map +1 -0
- package/lib/modules/mind-map/index.cjs.js +56 -0
- package/lib/modules/mind-map/index.cjs.js.map +1 -0
- package/lib/modules/mind-map/modules/context-menu.cjs.js +128 -0
- package/lib/modules/mind-map/modules/context-menu.cjs.js.map +1 -0
- package/lib/modules/mind-map/modules/control-panel.cjs.js +424 -0
- package/lib/modules/mind-map/modules/control-panel.cjs.js.map +1 -0
- package/lib/modules/mind-map/modules/custom-resize-action.cjs.js +161 -0
- package/lib/modules/mind-map/modules/custom-resize-action.cjs.js.map +1 -0
- package/lib/modules/mind-map/style/mind-map.css +224 -0
- package/lib/modules/shortcut-key/index.cjs.js +16 -0
- package/lib/modules/shortcut-key/index.cjs.js.map +1 -1
- package/lib/modules/syntax.cjs.js.map +1 -1
- package/lib/modules/table-up/index.cjs.js.map +1 -1
- package/lib/modules/toolbar/better-picker.cjs.js.map +1 -1
- package/lib/modules/toolbar/better-toolbar.cjs.js.map +1 -1
- package/lib/modules/toolbar/toolbar-tip.cjs.js.map +1 -1
- package/lib/themes/snow.cjs.js.map +1 -1
- package/lib/tools/format-painter.cjs.js.map +1 -1
- package/lib/tools/fullscreen.cjs.js.map +1 -1
- package/lib/tools/screenshot.cjs.js.map +1 -1
- package/lib/ui/icons.cjs.js +3 -1
- package/lib/ui/icons.cjs.js.map +1 -1
- package/lib/ui/icons.config.cjs.js +4 -0
- package/lib/ui/icons.config.cjs.js.map +1 -1
- package/lib/utils/debounce.cjs.js.map +1 -1
- package/lib/utils/image.cjs.js.map +1 -1
- package/lib/utils/is.cjs.js.map +1 -1
- package/lib/utils/method.cjs.js.map +1 -1
- package/lib/utils/scroll-lock.cjs.js.map +1 -1
- package/package.json +5 -1
- package/style.css +3 -1
- package/types/config/i18n/en-us.d.ts +2 -0
- package/types/config/i18n/zh-cn.d.ts +2 -0
- package/types/config/types/editor-modules.interface.d.ts +4 -0
- package/types/modules/flow-chart/config-utils.d.ts +10 -0
- package/types/modules/flow-chart/formats/flow-chart-blot.d.ts +43 -0
- package/types/modules/flow-chart/i18n/en-us.d.ts +26 -0
- package/types/modules/flow-chart/i18n/index.d.ts +1 -0
- package/types/modules/flow-chart/i18n/zh-cn.d.ts +26 -0
- package/types/modules/flow-chart/icons.d.ts +12 -0
- package/types/modules/flow-chart/index.d.ts +10 -0
- package/types/modules/flow-chart/modules/context-menu.d.ts +3 -0
- package/types/modules/flow-chart/modules/control-panel.d.ts +3 -0
- package/types/modules/flow-chart/modules/custom-resize-action.d.ts +22 -0
- package/types/modules/flow-chart/options.d.ts +29 -0
- package/types/modules/index.d.ts +2 -0
- package/types/modules/mind-map/config-utils.d.ts +12 -0
- package/types/modules/mind-map/formats/mind-map-blot.d.ts +44 -0
- package/types/modules/mind-map/i18n/en-us.d.ts +25 -0
- package/types/modules/mind-map/i18n/index.d.ts +1 -0
- package/types/modules/mind-map/i18n/zh-cn.d.ts +25 -0
- package/types/modules/mind-map/icons.d.ts +21 -0
- package/types/modules/mind-map/index.d.ts +10 -0
- package/types/modules/mind-map/modules/context-menu.d.ts +3 -0
- package/types/modules/mind-map/modules/control-panel.d.ts +3 -0
- package/types/modules/mind-map/modules/custom-resize-action.d.ts +23 -0
- package/types/modules/mind-map/options.d.ts +26 -0
- package/types/ui/icons.config.d.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../../../../src/modules/ai/index.ts"],"sourcesContent":["import type TypeToolbar from 'quill/modules/toolbar'\nimport type FluentEditor from '../../core/fluent-editor'\nimport type { AIOptions, OperationMenuItem, ResultMenuItem } from './types'\nimport {\n CLOSE,\n INPUT_PLACEHOLDER,\n INSERT_SUB_CONTENT_TEXT,\n INSERT_TEXT,\n MENU_ID_MAP,\n MENU_TITLE_DATA,\n REGENERATE,\n REPLACE_SELECT,\n RESULT_HEADER_TEXT,\n SELECT_PLACEHOLDER,\n STOP_ANSWER,\n THINK_TEXT,\n} from './constants'\nimport {\n ADJUST_ICON,\n AI_ICON,\n CALL_ICON,\n CLOSE_ICON,\n COPY_ICON,\n EDITOR_ICON,\n INSERT_ICON,\n MENU_CLOSE_ICON,\n REBUILD_ICON,\n REFRESH_ICON,\n REPLACE_SELECT_ICON,\n RIGHT_ARROW_ICON,\n SEND_BTN_ICON,\n STOP_ICON,\n THINK_ICON,\n} from './icons'\n\nexport class AI {\n toolbar: TypeToolbar\n host: string\n apiKey: string\n model: string\n message: string\n isBreak: boolean = false // 打断标记\n textNumber: number // 文本字数限制\n private _isSelectRangeMode: boolean = false // 选择/点击模式\n private _charCount: number = 0 // 文本字数\n private _debounceTimer = null\n private _inputPlaceholder: string = ''\n private _showOperationMenu: boolean = false\n private _isThinking: boolean = false // 思考中\n private _showResultPopupEl: boolean = false // 结果弹窗\n selectedText: string = '' // 选择的文本\n inputValue: string = '' // 存储输入框的值\n resultMenuList: ResultMenuItem[] = []\n operationMenuList: OperationMenuItem[] = []\n private _operationMenuItemList: OperationMenuItem[] = []\n\n private alertEl: HTMLDivElement | null = null\n private alertTimer: number | null = null\n private selectionBubbleEl: HTMLDivElement | null = null\n private selectionRange: any = null\n private dialogContainerEl: HTMLDivElement | null = null\n private wrapContainerEl: HTMLDivElement | null = null\n private aiIconEl: HTMLSpanElement | null = null\n private inputContainerEl: HTMLDivElement | null = null\n private inputEl: HTMLInputElement | null = null\n private menuContainerEl: HTMLDivElement | null = null\n private subMenuEl: HTMLDivElement | null = null\n private subMenuEditorEl: HTMLDivElement | null = null\n private subMenuToneEl: HTMLDivElement | null = null\n private subMenuAdjustEl: HTMLDivElement | null = null\n private inputRightEl: HTMLDivElement | null = null\n private inputSendBtnEl: HTMLSpanElement | null = null\n private inputCloseBtnEl: HTMLSpanElement | null = null\n private thinkContainerEl: HTMLDivElement | null = null // 思考元素\n private thinkBtnEl: HTMLDivElement | null = null\n private resultPopupEl: HTMLDivElement | null = null\n private resultPopupHeaderEl: HTMLDivElement | null = null\n private resultPopupContentEl: HTMLDivElement | null = null\n private resultPopupFooterEl: HTMLDivElement | null = null\n private resultPopupFooterTextEl: HTMLSpanElement | null = null\n private resultRefreshBtnEl: HTMLSpanElement | null = null\n private resultCopyBtnEl: HTMLSpanElement | null = null\n // 分享和朗读功能待放开\n // private resultShareBtnEl: HTMLSpanElement | null = null\n // private resultVoiceBtnEl: HTMLSpanElement | null = null\n private actionMenuEl: HTMLDivElement | null = null\n\n constructor(\n public quill: FluentEditor,\n public options: AIOptions,\n ) {\n this.quill = quill\n this.toolbar = quill.getModule('toolbar') as TypeToolbar\n // 添加AI按钮到工具栏\n if (typeof this.toolbar !== 'undefined') {\n this.toolbar.addHandler('ai', this.showAIInput.bind(this))\n }\n\n this.quill.on('selection-change', this.handleSelectionChange.bind(this))\n\n this.host = options.host || 'https://api.deepseek.com/v1'\n this.apiKey = options.apiKey\n this.model = options.model || 'deepseek-chat'\n this.textNumber = options.contentMaxLength || 5000\n\n this.resultMenuList = [\n { text: REPLACE_SELECT, icon: REPLACE_SELECT_ICON },\n { text: INSERT_TEXT, icon: INSERT_ICON, selectText: INSERT_SUB_CONTENT_TEXT },\n { text: REGENERATE, icon: REBUILD_ICON },\n { text: CLOSE, icon: MENU_CLOSE_ICON },\n ]\n\n this.operationMenuList = [\n { id: 'editor', text: '编辑调整内容', icon: EDITOR_ICON },\n { id: 'tone', text: '改写口吻', icon: CALL_ICON },\n { id: 'adjust', text: '整理选区内容', icon: ADJUST_ICON },\n ]\n }\n\n // 工具栏启动\n showAIInput() {\n // 创建输入框和结果弹窗\n this.create()\n\n this.selectionRange = this.quill.getSelection()\n if (this.selectionRange.length) {\n this.isSelectRangeMode = true\n }\n else {\n this.isSelectRangeMode = false\n }\n // 定位到编辑器焦点位置\n this.positionElements()\n\n // 添加ESC键监听\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n this.closeAIPanel()\n this.quill.container.removeEventListener('keydown', handleKeyDown)\n }\n }\n this.quill.container.addEventListener('keydown', handleKeyDown)\n }\n\n // 气泡启动\n private selectTextEvent() {\n if (!this.selectionRange) return\n this.create()\n // 定位到编辑器焦点位置\n this.positionElements()\n\n this.isSelectRangeMode = true\n }\n\n private create() {\n this.createResultElement()\n this.createOperationMenuElements()\n this.createInputBoxElements()\n\n // 创建事件监听\n this.addInputEvent()\n this.addResultEvent()\n this.handleActionMenuDisplay()\n // 添加到编辑器\n this.quill.container.appendChild(this.dialogContainerEl)\n }\n\n // 创建结果弹窗\n private createResultElement() {\n if (!this.resultPopupEl) {\n this.resultPopupEl = document.createElement('div')\n this.resultPopupEl.className = 'ql-ai-result'\n this.resultPopupHeaderEl = document.createElement('div')\n this.resultPopupHeaderEl.className = 'ql-ai-result-header'\n this.resultPopupHeaderEl.textContent = RESULT_HEADER_TEXT\n this.resultPopupContentEl = document.createElement('div')\n this.resultPopupContentEl.className = 'ql-ai-result-content'\n this.resultPopupFooterEl = document.createElement('div')\n this.resultPopupFooterEl.className = 'ql-ai-result-footer'\n this.resultPopupFooterTextEl = document.createElement('span')\n this.resultPopupFooterTextEl.className = 'ql-ai-result-footer-text'\n this.resultPopupFooterTextEl.textContent = `0`\n this.resultRefreshBtnEl = document.createElement('span')\n this.resultRefreshBtnEl.className = 'ql-ai-result-footer-refresh'\n this.resultRefreshBtnEl.innerHTML = REFRESH_ICON\n this.resultCopyBtnEl = document.createElement('span')\n this.resultCopyBtnEl.className = 'ql-ai-result-footer-copy'\n this.resultCopyBtnEl.innerHTML = COPY_ICON\n\n // 分享和朗读功能待放开\n // this.resultShareBtnEl = document.createElement('span')\n // this.resultShareBtnEl.className = 'ql-ai-result-footer-share'\n // this.resultShareBtnEl.innerHTML = SHARE_ICON\n // this.resultVoiceBtnEl = document.createElement('span')\n // this.resultVoiceBtnEl.className = 'ql-ai-result-footer-voice'\n // this.resultVoiceBtnEl.innerHTML = VOICE_ICON\n const resultFooterRightEl: HTMLDivElement = document.createElement('div')\n resultFooterRightEl.className = 'ql-ai-result-footer-right'\n resultFooterRightEl.appendChild(this.resultRefreshBtnEl)\n resultFooterRightEl.appendChild(this.resultCopyBtnEl)\n // 分享和朗读功能待放开\n // resultFooterRightEl.appendChild(this.resultShareBtnEl)\n // resultFooterRightEl.appendChild(this.resultVoiceBtnEl)\n this.resultPopupFooterEl.appendChild(this.resultPopupFooterTextEl)\n this.resultPopupFooterEl.appendChild(resultFooterRightEl)\n this.resultPopupEl.appendChild(this.resultPopupHeaderEl)\n this.resultPopupEl.appendChild(this.resultPopupContentEl)\n this.resultPopupEl.appendChild(this.resultPopupFooterEl)\n }\n this.showResultPopupEl = false\n }\n\n private createOperationMenuElements() {\n if (!this.menuContainerEl) {\n // 创建操作菜单容器\n this.menuContainerEl = document.createElement('div')\n this.menuContainerEl.className = 'ql-ai-menu-container'\n\n // 创建主菜单\n const mainMenu = document.createElement('div')\n mainMenu.className = 'ql-ai-main-menu'\n this.operationMenuList.forEach(({ text, icon, id }) => {\n const menuItem = document.createElement('div')\n menuItem.className = 'ql-ai-menu-item'\n menuItem.innerHTML = `${icon}<span>${text}</span>${RIGHT_ARROW_ICON}`\n menuItem.addEventListener('mouseenter', (e) => {\n e.stopPropagation()\n this.subMenuEl.style.display = 'block'\n this.subMenuEl.className = `ql-ai-sub-menu ${id}`\n this.createOperationMenuItem(id)\n })\n mainMenu.appendChild(menuItem)\n })\n if (!this.subMenuEl) {\n // 创建子菜单\n this.subMenuEl = document.createElement('div')\n this.subMenuEl.className = 'ql-ai-sub-menu'\n this.subMenuEl.style.display = 'none'\n }\n\n this.menuContainerEl.appendChild(mainMenu)\n this.menuContainerEl.appendChild(this.subMenuEl)\n }\n this.showOperationMenu = false\n }\n\n private createOperationMenuItem(id: string) {\n let menuItemBox = this[MENU_ID_MAP[id]]\n if (!menuItemBox) {\n menuItemBox = document.createElement('div')\n }\n // 清除子菜单容器中的所有子元素\n while (this.subMenuEl.firstChild) {\n this.subMenuEl.removeChild(this.subMenuEl.firstChild)\n }\n\n MENU_TITLE_DATA[id].forEach(({ text, icon, id }) => {\n const menuItem = document.createElement('div')\n menuItem.className = 'ql-ai-menu-item'\n menuItem.innerHTML = `${icon || ''}<span>${text}</span>`\n menuItem.addEventListener('click', (e) => {\n e.stopPropagation()\n this.handleOperationMenuItemClick(text, id)\n })\n menuItemBox.appendChild(menuItem)\n })\n this.subMenuEl.appendChild(menuItemBox)\n }\n\n private createInputBoxElements() {\n if (!this.dialogContainerEl) {\n this.dialogContainerEl = document.createElement('div')\n this.dialogContainerEl.className = 'ql-ai-dialog'\n this.wrapContainerEl = document.createElement('div')\n this.wrapContainerEl.className = 'ql-ai-wrapper'\n this.wrapContainerEl.style.width = `${this.quill.container.clientWidth - 30}px`\n\n // 添加AI图标\n this.createAIInputIcon()\n\n // 增加输入框\n this.inputEl = document.createElement('input')\n this.inputEl.type = 'text'\n this.inputPlaceholder = this._isSelectRangeMode ? SELECT_PLACEHOLDER : INPUT_PLACEHOLDER\n // 添加发送按钮\n this.inputSendBtnEl = document.createElement('span')\n this.inputSendBtnEl.className = 'ql-ai-input-right-send'\n this.inputSendBtnEl.innerHTML = SEND_BTN_ICON\n this.inputCloseBtnEl = document.createElement('span')\n this.inputCloseBtnEl.className = 'ql-ai-input-right-close'\n this.inputCloseBtnEl.innerHTML = CLOSE_ICON\n this.inputRightEl = document.createElement('div')\n this.inputRightEl.className = 'ql-ai-input-right'\n\n // 创建输入框\n this.inputContainerEl = document.createElement('div')\n this.inputContainerEl.className = 'ql-ai-input'\n this.inputContainerEl.appendChild(this.aiIconEl)\n this.inputContainerEl.appendChild(this.inputEl)\n this.inputRightEl.appendChild(this.inputSendBtnEl)\n this.inputRightEl.appendChild(this.inputCloseBtnEl)\n this.inputContainerEl.appendChild(this.inputRightEl) // 添加发送按钮\n this.wrapContainerEl.appendChild(this.resultPopupEl)\n this.wrapContainerEl.appendChild(this.inputContainerEl)\n this.wrapContainerEl.appendChild(this.menuContainerEl) // 添加菜单容器\n this.dialogContainerEl.appendChild(this.wrapContainerEl)\n }\n else {\n this.dialogContainerEl.style.display = 'block'\n }\n this.hiddenInputSendBtnEl()\n }\n\n private hiddenInputSendBtnEl(display = 'none') {\n if (this.inputEl && this.inputSendBtnEl) {\n this.inputSendBtnEl.style.display = display\n }\n }\n\n private copyResult() {\n if (!this.resultPopupContentEl) return\n\n try {\n const textToCopy = this.resultPopupContentEl.textContent || ''\n navigator.clipboard\n .writeText(textToCopy)\n .then(() => {\n this.showAlert('内容已复制到剪贴板')\n // 可以在这里添加复制成功的提示\n })\n .catch((err) => {\n this.showAlert(`复制失败:${err}`)\n })\n }\n catch (err) {\n this.showAlert(`复制失败:${err}`)\n // 兼容不支持clipboard API的浏览器\n const textarea = document.createElement('textarea')\n textarea.value = this.resultPopupContentEl.textContent || ''\n document.body.appendChild(textarea)\n textarea.select()\n document.execCommand('copy')\n document.body.removeChild(textarea)\n }\n }\n\n // 分享和朗读功能待放开\n // private shareResult() {\n // if (!this.resultPopupContentEl) return\n\n // const textToShare = this.resultPopupContentEl.textContent || ''\n // const title = 'AI生成内容分享'\n\n // if (navigator.share) {\n // navigator.share({\n // title,\n // text: textToShare,\n // })\n // .catch((err) => {\n // this.showAlert(`分享失败:${err}`)\n // })\n // }\n // else {\n // // 兼容不支持Web Share API的浏览器\n // const shareUrl = `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(textToShare)}`\n // window.open(shareUrl, '_blank')\n // }\n // }\n // private voiceResult() {\n // if (!this.resultPopupContentEl) return\n\n // const textToSpeak = this.resultPopupContentEl.textContent || ''\n\n // if ('speechSynthesis' in window) {\n // const utterance = new SpeechSynthesisUtterance(textToSpeak)\n // utterance.lang = 'zh-CN' // 设置中文语音\n // speechSynthesis.speak(utterance)\n // }\n // else {\n // this.showAlert('当前浏览器不支持语音合成API')\n // // 可以在这里添加不支持语音的提示\n // }\n // }\n\n private addResultEvent() {\n if (this.resultRefreshBtnEl) {\n this.resultRefreshBtnEl.addEventListener('click', () => {\n this.regenerateResponse()\n })\n }\n\n if (this.resultCopyBtnEl) {\n this.resultCopyBtnEl.addEventListener('click', () => {\n this.copyResult()\n })\n }\n\n // 分享和朗读功能待放开\n // if (this.resultShareBtnEl) {\n // this.resultShareBtnEl.addEventListener('click', () => {\n // this.shareResult()\n // })\n // }\n // if (this.resultVoiceBtnEl) {\n // this.resultVoiceBtnEl.addEventListener('click', () => {\n // this.voiceResult()\n // })\n // }\n }\n\n // 显示选中文本的气泡\n private showSelectionBubble() {\n if (!this.selectionBubbleEl) {\n this.selectionBubbleEl = document.createElement('div')\n this.selectionBubbleEl.className = 'ql-ai-selection-bubble'\n const icon = AI_ICON.replaceAll('paint_linear_2', 'paint_linear_bubble')\n this.selectionBubbleEl.innerHTML = `${icon}<span>AI 智能</span>`\n this.selectionBubbleEl.addEventListener('click', () => this.selectTextEvent())\n document.body.appendChild(this.selectionBubbleEl)\n }\n\n const { left, top } = this.quill.getBounds(this.selectionRange.index)\n const { left: endLeft } = this.quill.getBounds(this.selectionRange.index + this.selectionRange.length)\n const width = (endLeft - left) / 2\n const editorRect = this.quill.container.getBoundingClientRect()\n\n this.selectionBubbleEl.style.display = 'flex'\n this.selectionBubbleEl.style.left = `${left + editorRect.left + width - 45}px`\n this.selectionBubbleEl.style.top = `${top + editorRect.top - 40}px`\n }\n\n // 隐藏选中文本的气泡\n private hideSelectionBubble() {\n if (this.selectionBubbleEl) {\n this.selectionBubbleEl.style.display = 'none'\n }\n }\n\n // 处理文本选中变化\n private handleSelectionChange(range: any) {\n if (range && range.length > 0) {\n this.selectionRange = range\n this.showSelectionBubble()\n this.selectedText = this.quill.getText(range.index, range.length)\n }\n else {\n if (range && range.index !== null) {\n this.selectedText = ''\n this.closeAIPanel()\n }\n else {\n this.hideSelectionBubble()\n }\n }\n }\n\n private addInputEvent() {\n if (this.inputContainerEl) {\n this.inputContainerEl.addEventListener('click', () => {})\n }\n\n // 监听输入事件\n if (this.inputEl) {\n this.inputEl.addEventListener('input', () => {\n this.hiddenInputSendBtnEl(this.inputEl.value.trim() ? 'flex' : 'none')\n if (this.menuContainerEl && this._isSelectRangeMode) {\n this.showOperationMenu = !this.inputEl.value.trim() && !this._showResultPopupEl\n }\n })\n }\n\n // 给发送按钮添加点击事件\n if (this.inputSendBtnEl) {\n this.inputSendBtnEl.addEventListener('click', async () => {\n await this.queryAI()\n })\n }\n // 监听发送事件\n this.inputEl.addEventListener('keydown', async (e) => {\n if (e.key === 'Enter') {\n await this.queryAI()\n }\n })\n\n // 给关闭按钮添加点击事件\n if (this.inputCloseBtnEl) {\n this.inputCloseBtnEl.addEventListener('click', () => {\n this.closeAIPanel()\n })\n }\n }\n\n private positionElements() {\n if (!this.dialogContainerEl) return\n const range = this.selectionRange\n if (range) {\n const bounds = this.quill.getBounds(range.index)\n this.dialogContainerEl.style.position = 'absolute'\n this.dialogContainerEl.style.top = `${bounds.top + bounds.height + 20}px`\n }\n }\n\n // 添加创建alert元素的方法\n private createAlertElement() {\n if (!this.alertEl) {\n this.alertEl = document.createElement('div')\n this.alertEl.className = 'ql-ai-alert'\n this.alertEl.style.display = 'none'\n document.body.appendChild(this.alertEl)\n }\n }\n\n // 添加显示alert的方法\n private showAlert(message: string, duration: number = 3000) {\n this.createAlertElement()\n if (!this.alertEl) return\n\n // 清除之前的定时器\n if (this.alertTimer) {\n clearTimeout(this.alertTimer)\n this.alertTimer = null\n }\n\n this.alertEl.textContent = message\n this.alertEl.style.display = 'block'\n\n // 自动隐藏\n this.alertTimer = setTimeout(() => {\n if (this.alertEl) {\n this.alertEl.style.display = 'none'\n }\n this.alertTimer = null\n }, duration) as unknown as number\n }\n\n private createAIInputIcon() {\n if (!this.aiIconEl) {\n this.aiIconEl = document.createElement('span')\n this.aiIconEl.className = 'ql-ai-input-pre-icon'\n const icon = AI_ICON.replaceAll('paint_linear_2', 'paint_linear_ai_input')\n this.aiIconEl.innerHTML = icon\n }\n }\n\n // 添加处理子菜单点击的方法\n private handleOperationMenuItemClick(text: string, id: string = '') {\n let quetion = ''\n if (id.startsWith('1-') || id.startsWith('3-')) {\n quetion = `将目标文字${text},目标文字为:${this.selectedText}`\n }\n else if (id.startsWith('2-')) {\n quetion = `改写目标文字的口吻,让其变得${text},目标文字为:${this.selectedText}`\n }\n this.showOperationMenu = false\n this.queryAI(quetion)\n }\n\n private createActionMenu() {\n if (!this.actionMenuEl) {\n this.actionMenuEl = document.createElement('div')\n this.actionMenuEl.className = 'ql-ai-actions'\n\n this.resultMenuList.forEach(({ text, icon }) => {\n const menuItem = document.createElement('div')\n menuItem.className = 'ql-ai-action-item'\n menuItem.innerHTML = `${icon}<span class=\"ql-ai-result-menu-text\">${text}</span>`\n menuItem.addEventListener('click', () => this.handleAction(text))\n this.actionMenuEl.appendChild(menuItem)\n })\n\n this.wrapContainerEl.appendChild(this.actionMenuEl)\n }\n const secondMenuItemText = this.actionMenuEl.children[1].querySelector('.ql-ai-result-menu-text') as HTMLDivElement\n\n const firstChild = this.actionMenuEl.firstChild\n\n if (!this._isSelectRangeMode) {\n if (firstChild instanceof Element) {\n firstChild.classList.add('hidden')\n }\n\n secondMenuItemText.textContent = INSERT_TEXT\n }\n else {\n if (firstChild instanceof Element) {\n firstChild.classList.remove('hidden')\n }\n\n secondMenuItemText.textContent = INSERT_SUB_CONTENT_TEXT\n }\n\n this.isThinking = false\n }\n\n private handleActionMenuDisplay(value: string = 'none') {\n if (this.actionMenuEl) {\n this.actionMenuEl.style.display = value\n }\n }\n\n private switchInputEl(showInput = true) {\n if (this.inputContainerEl) {\n this.inputContainerEl.style.display = showInput ? 'flex' : 'none'\n }\n\n this.handleActionMenuDisplay(showInput ? 'block' : 'none')\n\n if (this.thinkContainerEl) {\n this.thinkContainerEl.style.display = showInput ? 'none' : 'flex'\n }\n }\n\n // 创建思考元素\n private createThinkElements() {\n if (!this.thinkContainerEl) {\n this.thinkContainerEl = document.createElement('div')\n this.thinkContainerEl.className = 'ql-ai-input'\n this.thinkContainerEl.innerHTML = `<span class=\"ql-ai-input-pre-icon ql-ai-think-icon\">${THINK_ICON}</span><span class=\"ql-ai-think-text\">${THINK_TEXT}</span>`\n this.thinkBtnEl = document.createElement('div')\n this.thinkBtnEl.className = 'ql-ai-think-btn'\n this.thinkBtnEl.innerHTML = `${STOP_ICON}<span>${STOP_ANSWER}</span>`\n this.thinkContainerEl.appendChild(this.thinkBtnEl)\n this.wrapContainerEl.appendChild(this.thinkContainerEl) // 添加发送按钮\n this.thinkBtnEl.addEventListener('click', () => {\n this.isBreak = true\n this.isThinking = false\n })\n }\n\n this.isThinking = true\n }\n\n // AI查询\n private async queryAI(question?: string): Promise<string> {\n this.createThinkElements()\n this.inputValue = question || this.inputEl.value\n if (this.inputValue.trim() === '') {\n return\n }\n\n // 有信息\n this.isBreak = false // 重置打断标记,防止重复打断ai\n // 这里实现实际的AI查询逻辑\n try {\n const response = await fetch(`${this.host}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n model: this.model,\n prompt: this.inputValue,\n stream: true,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`)\n }\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let content = ''\n\n while (true) {\n if (this.isBreak) {\n this.isBreak = false\n break\n }\n\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value)\n const lines = chunk.split('\\n').filter(line => line.trim() !== '')\n\n for (const line of lines) {\n try {\n const data = JSON.parse(line)\n content += data.response || ''\n this.showAIResponse(content)\n }\n catch (e) {\n console.error('解析错误:', e)\n }\n }\n }\n\n // 创建操作菜单\n this.createActionMenu()\n this.inputEl.value = '' // 清空输入框\n this.hiddenInputSendBtnEl()\n return content\n }\n catch (error) {\n console.error('AI查询失败:', error)\n return 'AI查询失败,请重试'\n }\n }\n\n private showAIResponse(response: string) {\n if (!this.resultPopupEl) return\n\n // 显示结果\n if (this._charCount <= this.textNumber) {\n this.resultPopupContentEl.innerHTML = response\n this.charCount = this.resultPopupContentEl.textContent.replace(/\\s+/g, '').length\n }\n else {\n this.isBreak = true\n this.charCount = 0\n }\n this.showResultPopupEl = true\n }\n\n private handleAction(action: string) {\n switch (action) {\n case REPLACE_SELECT:\n this.replaceSelectText()\n break\n case INSERT_TEXT:\n this.insertAIResponse()\n break\n case REGENERATE:\n this.regenerateResponse()\n break\n case CLOSE:\n this.closeAIPanel()\n break\n }\n }\n\n private replaceSelectText() {\n if (!this.resultPopupContentEl) return\n const range = this.quill.getSelection(true)\n if (range && range.length > 0) {\n // 删除选中内容\n this.quill.deleteText(range.index, range.length)\n // 插入AI生成的内容\n this.quill.clipboard.dangerouslyPasteHTML(range.index, this.resultPopupContentEl.innerHTML)\n }\n this.closeAIPanel()\n }\n\n private insertAIResponse() {\n if (!this.resultPopupContentEl) return\n const range = this.quill.getSelection(true)\n if (range) {\n this.quill.clipboard.dangerouslyPasteHTML(range.index + range.length, this.resultPopupContentEl.innerHTML)\n }\n this.closeAIPanel()\n }\n\n private async regenerateResponse() {\n await this.queryAI(this.inputValue)\n }\n\n private closeAIPanel() {\n this.isBreak = true // 停止查询\n\n if (this.dialogContainerEl) {\n this.dialogContainerEl.style.display = 'none'\n }\n\n if (this.actionMenuEl) {\n this.actionMenuEl.style.display = 'none'\n }\n\n this.showResultPopupEl = false\n\n if (this.inputEl && this.inputEl.value.trim() !== '') {\n this.inputEl.value = '' // 清空输入框\n }\n this.hideSelectionBubble()\n }\n\n set charCount(value: number) {\n // 清除之前的定时器\n if (this._debounceTimer) {\n clearTimeout(this._debounceTimer)\n }\n\n this._debounceTimer = setTimeout(() => {\n this._charCount = value\n if (this.resultPopupFooterTextEl) {\n this.resultPopupFooterTextEl.textContent = `${this._charCount}/${this.textNumber}`\n }\n clearTimeout(this._debounceTimer)\n this._debounceTimer = null\n }, 210)\n }\n\n get charCount() {\n return this._charCount\n }\n\n set inputPlaceholder(value: string) {\n this._inputPlaceholder = value\n if (this.inputEl) {\n this.inputEl.placeholder = value\n }\n }\n\n get inputPlaceholder() {\n return this._inputPlaceholder\n }\n\n set showOperationMenu(value: boolean) {\n this._showOperationMenu = value\n if (this.menuContainerEl) {\n this.menuContainerEl.style.display = value ? 'flex' : 'none'\n }\n }\n\n get showOperationMenu() {\n return this._showOperationMenu\n }\n\n set isSelectRangeMode(value: boolean) {\n this._isSelectRangeMode = value\n this.showOperationMenu = value\n this.inputPlaceholder = value ? SELECT_PLACEHOLDER : INPUT_PLACEHOLDER\n this.hideSelectionBubble()\n }\n\n get isSelectRangeMode() {\n return this._isSelectRangeMode\n }\n\n set isThinking(value: boolean) {\n this._isThinking = value\n this.switchInputEl(!value)\n }\n\n get isThinking() {\n return this._isThinking\n }\n\n set showResultPopupEl(value: boolean) {\n this._showResultPopupEl = value\n if (this.resultPopupEl) {\n this.resultPopupEl.style.display = value ? 'block' : 'none'\n }\n }\n\n get showResultPopupEl() {\n return this._showResultPopupEl\n }\n}\n"],"names":["REPLACE_SELECT","REPLACE_SELECT_ICON","INSERT_TEXT","INSERT_ICON","INSERT_SUB_CONTENT_TEXT","REGENERATE","REBUILD_ICON","CLOSE","MENU_CLOSE_ICON","EDITOR_ICON","CALL_ICON","ADJUST_ICON","RESULT_HEADER_TEXT","REFRESH_ICON","COPY_ICON","RIGHT_ARROW_ICON","MENU_ID_MAP","MENU_TITLE_DATA","id","SELECT_PLACEHOLDER","INPUT_PLACEHOLDER","SEND_BTN_ICON","CLOSE_ICON","AI_ICON","THINK_ICON","THINK_TEXT","STOP_ICON","STOP_ANSWER"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../../../../src/modules/ai/index.ts"],"sourcesContent":["import type TypeToolbar from 'quill/modules/toolbar'\nimport type FluentEditor from '../../core/fluent-editor'\nimport type { AIOptions, OperationMenuItem, ResultMenuItem } from './types'\nimport {\n CLOSE,\n INPUT_PLACEHOLDER,\n INSERT_SUB_CONTENT_TEXT,\n INSERT_TEXT,\n MENU_ID_MAP,\n MENU_TITLE_DATA,\n REGENERATE,\n REPLACE_SELECT,\n RESULT_HEADER_TEXT,\n SELECT_PLACEHOLDER,\n STOP_ANSWER,\n THINK_TEXT,\n} from './constants'\nimport {\n ADJUST_ICON,\n AI_ICON,\n CALL_ICON,\n CLOSE_ICON,\n COPY_ICON,\n EDITOR_ICON,\n INSERT_ICON,\n MENU_CLOSE_ICON,\n REBUILD_ICON,\n REFRESH_ICON,\n REPLACE_SELECT_ICON,\n RIGHT_ARROW_ICON,\n SEND_BTN_ICON,\n STOP_ICON,\n THINK_ICON,\n} from './icons'\n\nexport class AI {\n toolbar: TypeToolbar\n host: string\n apiKey: string\n model: string\n message: string\n isBreak: boolean = false // 打断标记\n textNumber: number // 文本字数限制\n private _isSelectRangeMode: boolean = false // 选择/点击模式\n private _charCount: number = 0 // 文本字数\n private _debounceTimer = null\n private _inputPlaceholder: string = ''\n private _showOperationMenu: boolean = false\n private _isThinking: boolean = false // 思考中\n private _showResultPopupEl: boolean = false // 结果弹窗\n selectedText: string = '' // 选择的文本\n inputValue: string = '' // 存储输入框的值\n resultMenuList: ResultMenuItem[] = []\n operationMenuList: OperationMenuItem[] = []\n private _operationMenuItemList: OperationMenuItem[] = []\n\n private alertEl: HTMLDivElement | null = null\n private alertTimer: number | null = null\n private selectionBubbleEl: HTMLDivElement | null = null\n private selectionRange: any = null\n private dialogContainerEl: HTMLDivElement | null = null\n private wrapContainerEl: HTMLDivElement | null = null\n private aiIconEl: HTMLSpanElement | null = null\n private inputContainerEl: HTMLDivElement | null = null\n private inputEl: HTMLInputElement | null = null\n private menuContainerEl: HTMLDivElement | null = null\n private subMenuEl: HTMLDivElement | null = null\n private subMenuEditorEl: HTMLDivElement | null = null\n private subMenuToneEl: HTMLDivElement | null = null\n private subMenuAdjustEl: HTMLDivElement | null = null\n private inputRightEl: HTMLDivElement | null = null\n private inputSendBtnEl: HTMLSpanElement | null = null\n private inputCloseBtnEl: HTMLSpanElement | null = null\n private thinkContainerEl: HTMLDivElement | null = null // 思考元素\n private thinkBtnEl: HTMLDivElement | null = null\n private resultPopupEl: HTMLDivElement | null = null\n private resultPopupHeaderEl: HTMLDivElement | null = null\n private resultPopupContentEl: HTMLDivElement | null = null\n private resultPopupFooterEl: HTMLDivElement | null = null\n private resultPopupFooterTextEl: HTMLSpanElement | null = null\n private resultRefreshBtnEl: HTMLSpanElement | null = null\n private resultCopyBtnEl: HTMLSpanElement | null = null\n // 分享和朗读功能待放开\n // private resultShareBtnEl: HTMLSpanElement | null = null\n // private resultVoiceBtnEl: HTMLSpanElement | null = null\n private actionMenuEl: HTMLDivElement | null = null\n\n constructor(\n public quill: FluentEditor,\n public options: AIOptions,\n ) {\n this.quill = quill\n this.toolbar = quill.getModule('toolbar') as TypeToolbar\n // 添加AI按钮到工具栏\n if (typeof this.toolbar !== 'undefined') {\n this.toolbar.addHandler('ai', this.showAIInput.bind(this))\n }\n\n this.quill.on('selection-change', this.handleSelectionChange.bind(this))\n\n this.host = options.host || 'https://api.deepseek.com/v1'\n this.apiKey = options.apiKey\n this.model = options.model || 'deepseek-chat'\n this.textNumber = options.contentMaxLength || 5000\n\n this.resultMenuList = [\n { text: REPLACE_SELECT, icon: REPLACE_SELECT_ICON },\n { text: INSERT_TEXT, icon: INSERT_ICON, selectText: INSERT_SUB_CONTENT_TEXT },\n { text: REGENERATE, icon: REBUILD_ICON },\n { text: CLOSE, icon: MENU_CLOSE_ICON },\n ]\n\n this.operationMenuList = [\n { id: 'editor', text: '编辑调整内容', icon: EDITOR_ICON },\n { id: 'tone', text: '改写口吻', icon: CALL_ICON },\n { id: 'adjust', text: '整理选区内容', icon: ADJUST_ICON },\n ]\n }\n\n // 工具栏启动\n showAIInput() {\n // 创建输入框和结果弹窗\n this.create()\n\n this.selectionRange = this.quill.getSelection()\n if (this.selectionRange.length) {\n this.isSelectRangeMode = true\n }\n else {\n this.isSelectRangeMode = false\n }\n // 定位到编辑器焦点位置\n this.positionElements()\n\n // 添加ESC键监听\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n this.closeAIPanel()\n this.quill.container.removeEventListener('keydown', handleKeyDown)\n }\n }\n this.quill.container.addEventListener('keydown', handleKeyDown)\n }\n\n // 气泡启动\n private selectTextEvent() {\n if (!this.selectionRange) return\n this.create()\n // 定位到编辑器焦点位置\n this.positionElements()\n\n this.isSelectRangeMode = true\n }\n\n private create() {\n this.createResultElement()\n this.createOperationMenuElements()\n this.createInputBoxElements()\n\n // 创建事件监听\n this.addInputEvent()\n this.addResultEvent()\n this.handleActionMenuDisplay()\n // 添加到编辑器\n this.quill.container.appendChild(this.dialogContainerEl)\n }\n\n // 创建结果弹窗\n private createResultElement() {\n if (!this.resultPopupEl) {\n this.resultPopupEl = document.createElement('div')\n this.resultPopupEl.className = 'ql-ai-result'\n this.resultPopupHeaderEl = document.createElement('div')\n this.resultPopupHeaderEl.className = 'ql-ai-result-header'\n this.resultPopupHeaderEl.textContent = RESULT_HEADER_TEXT\n this.resultPopupContentEl = document.createElement('div')\n this.resultPopupContentEl.className = 'ql-ai-result-content'\n this.resultPopupFooterEl = document.createElement('div')\n this.resultPopupFooterEl.className = 'ql-ai-result-footer'\n this.resultPopupFooterTextEl = document.createElement('span')\n this.resultPopupFooterTextEl.className = 'ql-ai-result-footer-text'\n this.resultPopupFooterTextEl.textContent = `0`\n this.resultRefreshBtnEl = document.createElement('span')\n this.resultRefreshBtnEl.className = 'ql-ai-result-footer-refresh'\n this.resultRefreshBtnEl.innerHTML = REFRESH_ICON\n this.resultCopyBtnEl = document.createElement('span')\n this.resultCopyBtnEl.className = 'ql-ai-result-footer-copy'\n this.resultCopyBtnEl.innerHTML = COPY_ICON\n\n // 分享和朗读功能待放开\n // this.resultShareBtnEl = document.createElement('span')\n // this.resultShareBtnEl.className = 'ql-ai-result-footer-share'\n // this.resultShareBtnEl.innerHTML = SHARE_ICON\n // this.resultVoiceBtnEl = document.createElement('span')\n // this.resultVoiceBtnEl.className = 'ql-ai-result-footer-voice'\n // this.resultVoiceBtnEl.innerHTML = VOICE_ICON\n const resultFooterRightEl: HTMLDivElement = document.createElement('div')\n resultFooterRightEl.className = 'ql-ai-result-footer-right'\n resultFooterRightEl.appendChild(this.resultRefreshBtnEl)\n resultFooterRightEl.appendChild(this.resultCopyBtnEl)\n // 分享和朗读功能待放开\n // resultFooterRightEl.appendChild(this.resultShareBtnEl)\n // resultFooterRightEl.appendChild(this.resultVoiceBtnEl)\n this.resultPopupFooterEl.appendChild(this.resultPopupFooterTextEl)\n this.resultPopupFooterEl.appendChild(resultFooterRightEl)\n this.resultPopupEl.appendChild(this.resultPopupHeaderEl)\n this.resultPopupEl.appendChild(this.resultPopupContentEl)\n this.resultPopupEl.appendChild(this.resultPopupFooterEl)\n }\n this.showResultPopupEl = false\n }\n\n private createOperationMenuElements() {\n if (!this.menuContainerEl) {\n // 创建操作菜单容器\n this.menuContainerEl = document.createElement('div')\n this.menuContainerEl.className = 'ql-ai-menu-container'\n\n // 创建主菜单\n const mainMenu = document.createElement('div')\n mainMenu.className = 'ql-ai-main-menu'\n this.operationMenuList.forEach(({ text, icon, id }) => {\n const menuItem = document.createElement('div')\n menuItem.className = 'ql-ai-menu-item'\n menuItem.innerHTML = `${icon}<span>${text}</span>${RIGHT_ARROW_ICON}`\n menuItem.addEventListener('mouseenter', (e) => {\n e.stopPropagation()\n this.subMenuEl.style.display = 'block'\n this.subMenuEl.className = `ql-ai-sub-menu ${id}`\n this.createOperationMenuItem(id)\n })\n mainMenu.appendChild(menuItem)\n })\n if (!this.subMenuEl) {\n // 创建子菜单\n this.subMenuEl = document.createElement('div')\n this.subMenuEl.className = 'ql-ai-sub-menu'\n this.subMenuEl.style.display = 'none'\n }\n\n this.menuContainerEl.appendChild(mainMenu)\n this.menuContainerEl.appendChild(this.subMenuEl)\n }\n this.showOperationMenu = false\n }\n\n private createOperationMenuItem(id: string) {\n let menuItemBox = this[MENU_ID_MAP[id]]\n if (!menuItemBox) {\n menuItemBox = document.createElement('div')\n }\n // 清除子菜单容器中的所有子元素\n while (this.subMenuEl.firstChild) {\n this.subMenuEl.removeChild(this.subMenuEl.firstChild)\n }\n\n MENU_TITLE_DATA[id].forEach(({ text, icon, id }) => {\n const menuItem = document.createElement('div')\n menuItem.className = 'ql-ai-menu-item'\n menuItem.innerHTML = `${icon || ''}<span>${text}</span>`\n menuItem.addEventListener('click', (e) => {\n e.stopPropagation()\n this.handleOperationMenuItemClick(text, id)\n })\n menuItemBox.appendChild(menuItem)\n })\n this.subMenuEl.appendChild(menuItemBox)\n }\n\n private createInputBoxElements() {\n if (!this.dialogContainerEl) {\n this.dialogContainerEl = document.createElement('div')\n this.dialogContainerEl.className = 'ql-ai-dialog'\n this.wrapContainerEl = document.createElement('div')\n this.wrapContainerEl.className = 'ql-ai-wrapper'\n this.wrapContainerEl.style.width = `${this.quill.container.clientWidth - 30}px`\n\n // 添加AI图标\n this.createAIInputIcon()\n\n // 增加输入框\n this.inputEl = document.createElement('input')\n this.inputEl.type = 'text'\n this.inputPlaceholder = this._isSelectRangeMode ? SELECT_PLACEHOLDER : INPUT_PLACEHOLDER\n // 添加发送按钮\n this.inputSendBtnEl = document.createElement('span')\n this.inputSendBtnEl.className = 'ql-ai-input-right-send'\n this.inputSendBtnEl.innerHTML = SEND_BTN_ICON\n this.inputCloseBtnEl = document.createElement('span')\n this.inputCloseBtnEl.className = 'ql-ai-input-right-close'\n this.inputCloseBtnEl.innerHTML = CLOSE_ICON\n this.inputRightEl = document.createElement('div')\n this.inputRightEl.className = 'ql-ai-input-right'\n\n // 创建输入框\n this.inputContainerEl = document.createElement('div')\n this.inputContainerEl.className = 'ql-ai-input'\n this.inputContainerEl.appendChild(this.aiIconEl)\n this.inputContainerEl.appendChild(this.inputEl)\n this.inputRightEl.appendChild(this.inputSendBtnEl)\n this.inputRightEl.appendChild(this.inputCloseBtnEl)\n this.inputContainerEl.appendChild(this.inputRightEl) // 添加发送按钮\n this.wrapContainerEl.appendChild(this.resultPopupEl)\n this.wrapContainerEl.appendChild(this.inputContainerEl)\n this.wrapContainerEl.appendChild(this.menuContainerEl) // 添加菜单容器\n this.dialogContainerEl.appendChild(this.wrapContainerEl)\n }\n else {\n this.dialogContainerEl.style.display = 'block'\n }\n this.hiddenInputSendBtnEl()\n }\n\n private hiddenInputSendBtnEl(display = 'none') {\n if (this.inputEl && this.inputSendBtnEl) {\n this.inputSendBtnEl.style.display = display\n }\n }\n\n private copyResult() {\n if (!this.resultPopupContentEl) return\n\n try {\n const textToCopy = this.resultPopupContentEl.textContent || ''\n navigator.clipboard\n .writeText(textToCopy)\n .then(() => {\n this.showAlert('内容已复制到剪贴板')\n // 可以在这里添加复制成功的提示\n })\n .catch((err) => {\n this.showAlert(`复制失败:${err}`)\n })\n }\n catch (err) {\n this.showAlert(`复制失败:${err}`)\n // 兼容不支持clipboard API的浏览器\n const textarea = document.createElement('textarea')\n textarea.value = this.resultPopupContentEl.textContent || ''\n document.body.appendChild(textarea)\n textarea.select()\n document.execCommand('copy')\n document.body.removeChild(textarea)\n }\n }\n\n // 分享和朗读功能待放开\n // private shareResult() {\n // if (!this.resultPopupContentEl) return\n\n // const textToShare = this.resultPopupContentEl.textContent || ''\n // const title = 'AI生成内容分享'\n\n // if (navigator.share) {\n // navigator.share({\n // title,\n // text: textToShare,\n // })\n // .catch((err) => {\n // this.showAlert(`分享失败:${err}`)\n // })\n // }\n // else {\n // // 兼容不支持Web Share API的浏览器\n // const shareUrl = `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(textToShare)}`\n // window.open(shareUrl, '_blank')\n // }\n // }\n // private voiceResult() {\n // if (!this.resultPopupContentEl) return\n\n // const textToSpeak = this.resultPopupContentEl.textContent || ''\n\n // if ('speechSynthesis' in window) {\n // const utterance = new SpeechSynthesisUtterance(textToSpeak)\n // utterance.lang = 'zh-CN' // 设置中文语音\n // speechSynthesis.speak(utterance)\n // }\n // else {\n // this.showAlert('当前浏览器不支持语音合成API')\n // // 可以在这里添加不支持语音的提示\n // }\n // }\n\n private addResultEvent() {\n if (this.resultRefreshBtnEl) {\n this.resultRefreshBtnEl.addEventListener('click', () => {\n this.regenerateResponse()\n })\n }\n\n if (this.resultCopyBtnEl) {\n this.resultCopyBtnEl.addEventListener('click', () => {\n this.copyResult()\n })\n }\n\n // 分享和朗读功能待放开\n // if (this.resultShareBtnEl) {\n // this.resultShareBtnEl.addEventListener('click', () => {\n // this.shareResult()\n // })\n // }\n // if (this.resultVoiceBtnEl) {\n // this.resultVoiceBtnEl.addEventListener('click', () => {\n // this.voiceResult()\n // })\n // }\n }\n\n // 显示选中文本的气泡\n private showSelectionBubble() {\n if (!this.selectionBubbleEl) {\n this.selectionBubbleEl = document.createElement('div')\n this.selectionBubbleEl.className = 'ql-ai-selection-bubble'\n const icon = AI_ICON.replaceAll('paint_linear_2', 'paint_linear_bubble')\n this.selectionBubbleEl.innerHTML = `${icon}<span>AI 智能</span>`\n this.selectionBubbleEl.addEventListener('click', () => this.selectTextEvent())\n document.body.appendChild(this.selectionBubbleEl)\n }\n\n const { left, top } = this.quill.getBounds(this.selectionRange.index)\n const { left: endLeft } = this.quill.getBounds(this.selectionRange.index + this.selectionRange.length)\n const width = (endLeft - left) / 2\n const editorRect = this.quill.container.getBoundingClientRect()\n\n this.selectionBubbleEl.style.display = 'flex'\n this.selectionBubbleEl.style.left = `${left + editorRect.left + width - 45}px`\n this.selectionBubbleEl.style.top = `${top + editorRect.top - 40}px`\n }\n\n // 隐藏选中文本的气泡\n private hideSelectionBubble() {\n if (this.selectionBubbleEl) {\n this.selectionBubbleEl.style.display = 'none'\n }\n }\n\n // 处理文本选中变化\n private handleSelectionChange(range: any) {\n if (range && range.length > 0) {\n this.selectionRange = range\n this.showSelectionBubble()\n this.selectedText = this.quill.getText(range.index, range.length)\n }\n else {\n if (range && range.index !== null) {\n this.selectedText = ''\n this.closeAIPanel()\n }\n else {\n this.hideSelectionBubble()\n }\n }\n }\n\n private addInputEvent() {\n if (this.inputContainerEl) {\n this.inputContainerEl.addEventListener('click', () => {})\n }\n\n // 监听输入事件\n if (this.inputEl) {\n this.inputEl.addEventListener('input', () => {\n this.hiddenInputSendBtnEl(this.inputEl.value.trim() ? 'flex' : 'none')\n if (this.menuContainerEl && this._isSelectRangeMode) {\n this.showOperationMenu = !this.inputEl.value.trim() && !this._showResultPopupEl\n }\n })\n }\n\n // 给发送按钮添加点击事件\n if (this.inputSendBtnEl) {\n this.inputSendBtnEl.addEventListener('click', async () => {\n await this.queryAI()\n })\n }\n // 监听发送事件\n this.inputEl.addEventListener('keydown', async (e) => {\n if (e.key === 'Enter') {\n await this.queryAI()\n }\n })\n\n // 给关闭按钮添加点击事件\n if (this.inputCloseBtnEl) {\n this.inputCloseBtnEl.addEventListener('click', () => {\n this.closeAIPanel()\n })\n }\n }\n\n private positionElements() {\n if (!this.dialogContainerEl) return\n const range = this.selectionRange\n if (range) {\n const bounds = this.quill.getBounds(range.index)\n this.dialogContainerEl.style.position = 'absolute'\n this.dialogContainerEl.style.top = `${bounds.top + bounds.height + 20}px`\n }\n }\n\n // 添加创建alert元素的方法\n private createAlertElement() {\n if (!this.alertEl) {\n this.alertEl = document.createElement('div')\n this.alertEl.className = 'ql-ai-alert'\n this.alertEl.style.display = 'none'\n document.body.appendChild(this.alertEl)\n }\n }\n\n // 添加显示alert的方法\n private showAlert(message: string, duration: number = 3000) {\n this.createAlertElement()\n if (!this.alertEl) return\n\n // 清除之前的定时器\n if (this.alertTimer) {\n clearTimeout(this.alertTimer)\n this.alertTimer = null\n }\n\n this.alertEl.textContent = message\n this.alertEl.style.display = 'block'\n\n // 自动隐藏\n this.alertTimer = setTimeout(() => {\n if (this.alertEl) {\n this.alertEl.style.display = 'none'\n }\n this.alertTimer = null\n }, duration) as unknown as number\n }\n\n private createAIInputIcon() {\n if (!this.aiIconEl) {\n this.aiIconEl = document.createElement('span')\n this.aiIconEl.className = 'ql-ai-input-pre-icon'\n const icon = AI_ICON.replaceAll('paint_linear_2', 'paint_linear_ai_input')\n this.aiIconEl.innerHTML = icon\n }\n }\n\n // 添加处理子菜单点击的方法\n private handleOperationMenuItemClick(text: string, id: string = '') {\n let quetion = ''\n if (id.startsWith('1-') || id.startsWith('3-')) {\n quetion = `将目标文字${text},目标文字为:${this.selectedText}`\n }\n else if (id.startsWith('2-')) {\n quetion = `改写目标文字的口吻,让其变得${text},目标文字为:${this.selectedText}`\n }\n this.showOperationMenu = false\n this.queryAI(quetion)\n }\n\n private createActionMenu() {\n if (!this.actionMenuEl) {\n this.actionMenuEl = document.createElement('div')\n this.actionMenuEl.className = 'ql-ai-actions'\n\n this.resultMenuList.forEach(({ text, icon }) => {\n const menuItem = document.createElement('div')\n menuItem.className = 'ql-ai-action-item'\n menuItem.innerHTML = `${icon}<span class=\"ql-ai-result-menu-text\">${text}</span>`\n menuItem.addEventListener('click', () => this.handleAction(text))\n this.actionMenuEl.appendChild(menuItem)\n })\n\n this.wrapContainerEl.appendChild(this.actionMenuEl)\n }\n const secondMenuItemText = this.actionMenuEl.children[1].querySelector('.ql-ai-result-menu-text') as HTMLDivElement\n\n const firstChild = this.actionMenuEl.firstChild\n\n if (!this._isSelectRangeMode) {\n if (firstChild instanceof Element) {\n firstChild.classList.add('hidden')\n }\n\n secondMenuItemText.textContent = INSERT_TEXT\n }\n else {\n if (firstChild instanceof Element) {\n firstChild.classList.remove('hidden')\n }\n\n secondMenuItemText.textContent = INSERT_SUB_CONTENT_TEXT\n }\n\n this.isThinking = false\n }\n\n private handleActionMenuDisplay(value: string = 'none') {\n if (this.actionMenuEl) {\n this.actionMenuEl.style.display = value\n }\n }\n\n private switchInputEl(showInput = true) {\n if (this.inputContainerEl) {\n this.inputContainerEl.style.display = showInput ? 'flex' : 'none'\n }\n\n this.handleActionMenuDisplay(showInput ? 'block' : 'none')\n\n if (this.thinkContainerEl) {\n this.thinkContainerEl.style.display = showInput ? 'none' : 'flex'\n }\n }\n\n // 创建思考元素\n private createThinkElements() {\n if (!this.thinkContainerEl) {\n this.thinkContainerEl = document.createElement('div')\n this.thinkContainerEl.className = 'ql-ai-input'\n this.thinkContainerEl.innerHTML = `<span class=\"ql-ai-input-pre-icon ql-ai-think-icon\">${THINK_ICON}</span><span class=\"ql-ai-think-text\">${THINK_TEXT}</span>`\n this.thinkBtnEl = document.createElement('div')\n this.thinkBtnEl.className = 'ql-ai-think-btn'\n this.thinkBtnEl.innerHTML = `${STOP_ICON}<span>${STOP_ANSWER}</span>`\n this.thinkContainerEl.appendChild(this.thinkBtnEl)\n this.wrapContainerEl.appendChild(this.thinkContainerEl) // 添加发送按钮\n this.thinkBtnEl.addEventListener('click', () => {\n this.isBreak = true\n this.isThinking = false\n })\n }\n\n this.isThinking = true\n }\n\n // AI查询\n private async queryAI(question?: string): Promise<string> {\n this.createThinkElements()\n this.inputValue = question || this.inputEl.value\n if (this.inputValue.trim() === '') {\n return\n }\n\n // 有信息\n this.isBreak = false // 重置打断标记,防止重复打断ai\n // 这里实现实际的AI查询逻辑\n try {\n const response = await fetch(`${this.host}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n model: this.model,\n prompt: this.inputValue,\n stream: true,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`)\n }\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let content = ''\n\n while (true) {\n if (this.isBreak) {\n this.isBreak = false\n break\n }\n\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value)\n const lines = chunk.split('\\n').filter(line => line.trim() !== '')\n\n for (const line of lines) {\n try {\n const data = JSON.parse(line)\n content += data.response || ''\n this.showAIResponse(content)\n }\n catch (e) {\n console.error('解析错误:', e)\n }\n }\n }\n\n // 创建操作菜单\n this.createActionMenu()\n this.inputEl.value = '' // 清空输入框\n this.hiddenInputSendBtnEl()\n return content\n }\n catch (error) {\n console.error('AI查询失败:', error)\n return 'AI查询失败,请重试'\n }\n }\n\n private showAIResponse(response: string) {\n if (!this.resultPopupEl) return\n\n // 显示结果\n if (this._charCount <= this.textNumber) {\n this.resultPopupContentEl.innerHTML = response\n this.charCount = this.resultPopupContentEl.textContent.replace(/\\s+/g, '').length\n }\n else {\n this.isBreak = true\n this.charCount = 0\n }\n this.showResultPopupEl = true\n }\n\n private handleAction(action: string) {\n switch (action) {\n case REPLACE_SELECT:\n this.replaceSelectText()\n break\n case INSERT_TEXT:\n this.insertAIResponse()\n break\n case REGENERATE:\n this.regenerateResponse()\n break\n case CLOSE:\n this.closeAIPanel()\n break\n }\n }\n\n private replaceSelectText() {\n if (!this.resultPopupContentEl) return\n const range = this.quill.getSelection(true)\n if (range && range.length > 0) {\n // 删除选中内容\n this.quill.deleteText(range.index, range.length)\n // 插入AI生成的内容\n this.quill.clipboard.dangerouslyPasteHTML(range.index, this.resultPopupContentEl.innerHTML)\n }\n this.closeAIPanel()\n }\n\n private insertAIResponse() {\n if (!this.resultPopupContentEl) return\n const range = this.quill.getSelection(true)\n if (range) {\n this.quill.clipboard.dangerouslyPasteHTML(range.index + range.length, this.resultPopupContentEl.innerHTML)\n }\n this.closeAIPanel()\n }\n\n private async regenerateResponse() {\n await this.queryAI(this.inputValue)\n }\n\n private closeAIPanel() {\n this.isBreak = true // 停止查询\n\n if (this.dialogContainerEl) {\n this.dialogContainerEl.style.display = 'none'\n }\n\n if (this.actionMenuEl) {\n this.actionMenuEl.style.display = 'none'\n }\n\n this.showResultPopupEl = false\n\n if (this.inputEl && this.inputEl.value.trim() !== '') {\n this.inputEl.value = '' // 清空输入框\n }\n this.hideSelectionBubble()\n }\n\n set charCount(value: number) {\n // 清除之前的定时器\n if (this._debounceTimer) {\n clearTimeout(this._debounceTimer)\n }\n\n this._debounceTimer = setTimeout(() => {\n this._charCount = value\n if (this.resultPopupFooterTextEl) {\n this.resultPopupFooterTextEl.textContent = `${this._charCount}/${this.textNumber}`\n }\n clearTimeout(this._debounceTimer)\n this._debounceTimer = null\n }, 210)\n }\n\n get charCount() {\n return this._charCount\n }\n\n set inputPlaceholder(value: string) {\n this._inputPlaceholder = value\n if (this.inputEl) {\n this.inputEl.placeholder = value\n }\n }\n\n get inputPlaceholder() {\n return this._inputPlaceholder\n }\n\n set showOperationMenu(value: boolean) {\n this._showOperationMenu = value\n if (this.menuContainerEl) {\n this.menuContainerEl.style.display = value ? 'flex' : 'none'\n }\n }\n\n get showOperationMenu() {\n return this._showOperationMenu\n }\n\n set isSelectRangeMode(value: boolean) {\n this._isSelectRangeMode = value\n this.showOperationMenu = value\n this.inputPlaceholder = value ? SELECT_PLACEHOLDER : INPUT_PLACEHOLDER\n this.hideSelectionBubble()\n }\n\n get isSelectRangeMode() {\n return this._isSelectRangeMode\n }\n\n set isThinking(value: boolean) {\n this._isThinking = value\n this.switchInputEl(!value)\n }\n\n get isThinking() {\n return this._isThinking\n }\n\n set showResultPopupEl(value: boolean) {\n this._showResultPopupEl = value\n if (this.resultPopupEl) {\n this.resultPopupEl.style.display = value ? 'block' : 'none'\n }\n }\n\n get showResultPopupEl() {\n return this._showResultPopupEl\n }\n}\n"],"names":["REPLACE_SELECT","REPLACE_SELECT_ICON","INSERT_TEXT","INSERT_ICON","INSERT_SUB_CONTENT_TEXT","REGENERATE","REBUILD_ICON","CLOSE","MENU_CLOSE_ICON","EDITOR_ICON","CALL_ICON","ADJUST_ICON","RESULT_HEADER_TEXT","REFRESH_ICON","COPY_ICON","RIGHT_ARROW_ICON","MENU_ID_MAP","MENU_TITLE_DATA","id","SELECT_PLACEHOLDER","INPUT_PLACEHOLDER","SEND_BTN_ICON","CLOSE_ICON","AI_ICON","THINK_ICON","THINK_TEXT","STOP_ICON","STOP_ANSWER"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"awareness.cjs.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 FluentEditor from '../../../core/fluent-editor'\nimport * as Y from 'yjs'\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): (() => 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 = Y.createAbsolutePositionFromRelativePosition(Y.createRelativePositionFromJSON(state.cursor.anchor), doc)\n const head = Y.createAbsolutePositionFromRelativePosition(Y.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 = Y.createRelativePositionFromTypeIndex(yText, range.index)\n const head = Y.createRelativePositionFromTypeIndex(yText, range.index + range.length)\n\n const currentState = awareness.getLocalState()\n if (!currentState?.cursor\n || !Y.compareRelativePositions(anchor, currentState.cursor.anchor)\n || !Y.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":["Y"],"mappings":";;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"awareness.cjs.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 FluentEditor from '../../../core/fluent-editor'\nimport * as Y from 'yjs'\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): (() => 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 = Y.createAbsolutePositionFromRelativePosition(Y.createRelativePositionFromJSON(state.cursor.anchor), doc)\n const head = Y.createAbsolutePositionFromRelativePosition(Y.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 = Y.createRelativePositionFromTypeIndex(yText, range.index)\n const head = Y.createRelativePositionFromTypeIndex(yText, range.index + range.length)\n\n const currentState = awareness.getLocalState()\n if (!currentState?.cursor\n || !Y.compareRelativePositions(anchor, currentState.cursor.anchor)\n || !Y.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":["Y"],"mappings":";;;;;;;;;;;;;;;;;;;;AAsBO,SAAS,eAAe,SAA4B,kBAAgD;AACzG,MAAI,CAAC,iBAAkB,QAAO;AAE9B,QAAM,YAAY;AAElB,MAAI,mCAAS,OAAO;AAClB,cAAU,mBAAmB,QAAQ,QAAQ,KAAK;AAAA,EACpD;AAEA,SAAO;AACT;AAEO,SAAS,uBACd,WACA,eACA,OACA,OACqB;AACrB,MAAI,CAAC,iBAAiB,CAAC,UAAW;AAElC,QAAM,MAAM,MAAM;AAElB,QAAM,eAAe,CAAC,UAAkB,UAAe;AACrD,QAAI;AACF,WAAI,+BAAO,WAAU,aAAa,UAAU,UAAU;AACpD,cAAM,OAAO,MAAM,QAAQ,CAAA;AAC3B,cAAM,QAAQ,KAAK,SAAS;AAC5B,cAAM,OAAO,KAAK,QAAQ,QAAQ,QAAQ;AAE1C,sBAAc,aAAa,SAAS,SAAA,GAAY,MAAM,KAAK;AAE3D,cAAM,SAASA,aAAE,2CAA2CA,aAAE,+BAA+B,MAAM,OAAO,MAAM,GAAG,GAAG;AACtH,cAAM,OAAOA,aAAE,2CAA2CA,aAAE,+BAA+B,MAAM,OAAO,IAAI,GAAG,GAAG;AAElH,YAAI,UAAU,QAAQ,OAAO,SAAS,SAAS,UAAU;AACvD,qBAAW,MAAM;AACf,0BAAc,WAAW,SAAS,YAAY;AAAA,cAC5C,OAAO,OAAO;AAAA,cACd,QAAQ,KAAK,QAAQ,OAAO;AAAA,YAAA,CAC7B;AAAA,UACH,GAAG,CAAC;AAAA,QACN;AAAA,MACF,OACK;AACH,sBAAc,aAAa,SAAS,UAAU;AAAA,MAChD;AAAA,IACF,SACO,KAAK;AACV,cAAQ,MAAM,yBAAyB,GAAG;AAAA,IAC5C;AAAA,EACF;AAEA,QAAM,yBAAyB,CAAC,UAAoD;AAClF,eAAW,MAAM;;AACf,UAAI,OAAO;AACT,cAAM,SAASA,aAAE,oCAAoC,OAAO,MAAM,KAAK;AACvE,cAAM,OAAOA,aAAE,oCAAoC,OAAO,MAAM,QAAQ,MAAM,MAAM;AAEpF,cAAM,eAAe,UAAU,cAAA;AAC/B,YAAI,EAAC,6CAAc,WACd,CAACA,aAAE,yBAAyB,QAAQ,aAAa,OAAO,MAAM,KAC9D,CAACA,aAAE,yBAAyB,MAAM,aAAa,OAAO,IAAI,GAAG;AAChE,oBAAU,mBAAmB,UAAU,EAAE,QAAQ,MAAM;AAAA,QACzD;AAAA,MACF,OACK;AACH,cAAI,eAAU,oBAAV,mBAA2B,YAAW,MAAM;AAC9C,oBAAU,mBAAmB,UAAU,IAAI;AAAA,QAC7C;AAAA,MACF;AAAA,IACF,GAAG,CAAC;AAAA,EACN;AAEA,QAAM,gBAAgB,CAAC,EAAE,OAAO,SAAS,cAInC;AACJ,QAAI,MAAM,YAAY,YAAa;AACnC,UAAM,SAAS,UAAU,UAAA;AAEzB,UAAM,QAAQ,CAAC,OAAO;AACpB,mBAAa,IAAI,OAAO,IAAI,EAAE,CAAC;AAAA,IACjC,CAAC;AAED,YAAQ,QAAQ,CAAC,OAAO;AACtB,mBAAa,IAAI,OAAO,IAAI,EAAE,CAAC;AAAA,IACjC,CAAC;AAED,YAAQ,QAAQ,CAAC,OAAO;AACtB,oBAAc,aAAa,GAAG,UAAU;AAAA,IAC1C,CAAC;AAAA,EACH;AAEA,YAAU,GAAG,UAAU,aAAa;AACpC,QAAM,GAAG,iBAAiB,CAAC,cAAc,SAAS;AAChD,QAAI,MAAM,YAAY,YAAa;AACnC,QAAI,cAAc,eAAe;AAC/B,UAAI,KAAK,CAAC,MAAM,QAAQ;AACtB,cAAM,QAAQ,MAAM,aAAA;AACpB,+BAAuB,KAAK;AAAA,MAC9B;AAAA,IACF,WACS,cAAc,oBAAoB;AACzC,UAAI,KAAK,CAAC,MAAM,QAAQ;AACtB,+BAAuB,KAAK,CAAC,CAA6C;AAAA,MAC5E;AAAA,IACF;AAAA,EACF,CAAC;AAED,YAAU,UAAA,EAAY,QAAQ,CAAC,OAAO,aAAa;AACjD,iBAAa,UAAU,KAAK;AAAA,EAC9B,CAAC;AAED,SAAO,MAAM;AACX,cAAU,IAAI,UAAU,aAAa;AACrC,UAAM,IAAI,iBAAiB,sBAAsB;AAAA,EACnD;AACF;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"y-indexeddb.cjs.js","sources":["../../../../../src/modules/collaborative-editing/awareness/y-indexeddb.ts"],"sourcesContent":["import type { Doc } from 'yjs'\nimport { IndexeddbPersistence } from 'y-indexeddb'\n\nexport function setupIndexedDB(doc: Doc): () => void {\n const fullDbName = `tiny-editor-${doc.guid}`\n\n new IndexeddbPersistence(fullDbName, doc)\n\n return (): void => {\n indexedDB.deleteDatabase(fullDbName)\n }\n}\n"],"names":["IndexeddbPersistence"],"mappings":";;;AAGO,SAAS,eAAe,KAAsB;
|
|
1
|
+
{"version":3,"file":"y-indexeddb.cjs.js","sources":["../../../../../src/modules/collaborative-editing/awareness/y-indexeddb.ts"],"sourcesContent":["import type { Doc } from 'yjs'\nimport { IndexeddbPersistence } from 'y-indexeddb'\n\nexport function setupIndexedDB(doc: Doc): () => void {\n const fullDbName = `tiny-editor-${doc.guid}`\n\n new IndexeddbPersistence(fullDbName, doc)\n\n return (): void => {\n indexedDB.deleteDatabase(fullDbName)\n }\n}\n"],"names":["IndexeddbPersistence"],"mappings":";;;AAGO,SAAS,eAAe,KAAsB;AACnD,QAAM,aAAa,eAAe,IAAI,IAAI;AAE1C,MAAIA,WAAAA,qBAAqB,YAAY,GAAG;AAExC,SAAO,MAAY;AACjB,cAAU,eAAe,UAAU;AAAA,EACrC;AACF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collaborative-editing.cjs.js","sources":["../../../../src/modules/collaborative-editing/collaborative-editing.ts"],"sourcesContent":["import type FluentEditor from '../../fluent-editor'\nimport type { UnifiedProvider } from './provider/providerRegistry'\nimport type { YjsOptions } from './types'\nimport QuillCursors from 'quill-cursors'\nimport { Awareness } from 'y-protocols/awareness'\nimport { QuillBinding } from 'y-quill'\nimport * as Y from 'yjs'\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 = new 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\n constructor(\n public quill: FluentEditor,\n public options: YjsOptions,\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 })\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) || 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)\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":["Y","awareness","setupAwareness","Awareness","createProvider","bindAwarenessToCursors","QuillBinding","setupIndexedDB"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWO,MAAM,oBAAoB;AAAA,EAQ/B,YACS,OACA,SACP;AAVM,gCAAc,IAAIA,aAAE,
|
|
1
|
+
{"version":3,"file":"collaborative-editing.cjs.js","sources":["../../../../src/modules/collaborative-editing/collaborative-editing.ts"],"sourcesContent":["import type FluentEditor from '../../fluent-editor'\nimport type { UnifiedProvider } from './provider/providerRegistry'\nimport type { YjsOptions } from './types'\nimport QuillCursors from 'quill-cursors'\nimport { Awareness } from 'y-protocols/awareness'\nimport { QuillBinding } from 'y-quill'\nimport * as Y from 'yjs'\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 = new 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\n constructor(\n public quill: FluentEditor,\n public options: YjsOptions,\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 })\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) || 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)\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":["Y","awareness","setupAwareness","Awareness","createProvider","bindAwarenessToCursors","QuillBinding","setupIndexedDB"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWO,MAAM,oBAAoB;AAAA,EAQ/B,YACS,OACA,SACP;AAVM,gCAAc,IAAIA,aAAE,IAAA;AACpB;AACA;AACA;AACA,2CAAuC;AACvC,0CAAsC;AAGrC,SAAA,QAAA;AACA,SAAA,UAAA;AAEP,SAAK,OAAO,KAAK,QAAQ,QAAQ,IAAIA,aAAE,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,YAAMC,cAAYC,yBAAe,KAAK,QAAQ,WAAW,IAAIC,YAAAA,UAAU,KAAK,IAAI,CAAC;AACjF,UAAI,CAACF,aAAW;AACd,cAAM,IAAI,MAAM,gCAAgC;AAAA,MAClD;AACA,WAAK,YAAYA;AAAAA,IACnB,OACK;AACH,WAAK,YAAY,IAAIE,sBAAU,KAAK,IAAI;AAAA,IAC1C;AAEA,QAAI,KAAK,QAAQ,UAAU;AACzB,YAAM,iBAAiB,KAAK,QAAQ;AACpC,UAAI;AACF,cAAM,WAAWC,iBAAAA,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,QAAA,CAC5B;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,kBAAkBC,UAAAA,uBAAuB,KAAK,WAAW,KAAK,SAAS,OAAO,KAAK,KAAK;AAC7F,UAAIC,OAAAA;AAAAA,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,iBAAiBC,0BAAe,KAAK,IAAI;AAAA,IAChD;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.cjs.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":["CollaborativeEditor"],"mappings":";;;;;;AAGO,MAAM,oBAAoB;AAAA,EAG/B,YAAmB,OAA4B,SAAc;AAFrD;AAEW,SAAA,QAAA;AAA4B,SAAA,UAAA;AAC7C,SAAK,sBAAsB,IAAIA,yCAAoB,OAAO,OAAO;
|
|
1
|
+
{"version":3,"file":"module.cjs.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":["CollaborativeEditor"],"mappings":";;;;;;AAGO,MAAM,oBAAoB;AAAA,EAG/B,YAAmB,OAA4B,SAAc;AAFrD;AAEW,SAAA,QAAA;AAA4B,SAAA,UAAA;AAC7C,SAAK,sBAAsB,IAAIA,yCAAoB,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.cjs.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 { 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} & 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":["WebsocketProviderWrapper","WebRTCProviderWrapper"],"mappings":";;;;AA6BA,MAAM,mBAAqC;AAAA,EACzC,WAAWA,
|
|
1
|
+
{"version":3,"file":"providerRegistry.cjs.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 { 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} & 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":["WebsocketProviderWrapper","WebRTCProviderWrapper"],"mappings":";;;;AA6BA,MAAM,mBAAqC;AAAA,EACzC,WAAWA,UAAAA;AAAAA,EACX,QAAQC,OAAAA;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.cjs.js","sources":["../../../../../src/modules/collaborative-editing/provider/webrtc.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\nimport type { ProviderEventHandlers } from '../types'\nimport type { UnifiedProvider } from './providerRegistry'\nimport { WebrtcProvider } from 'y-webrtc'\nimport * as Y from 'yjs'\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 }: {\n options: WebRTCProviderOptions\n awareness?: Awareness\n doc?: Y.Doc\n } & ProviderEventHandlers) {\n this.onConnect = onConnect\n this.onDisconnect = onDisconnect\n this.onError = onError\n this.onSyncChange = onSyncChange\n\n this.document = doc || new Y.Doc()\n try {\n this.provider = new WebrtcProvider(options.roomName, this.document, {\n 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":["Y","WebrtcProvider"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAeO,MAAM,sBAAiD;AAAA,EA2C5D,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,GAKyB;AAtDnB;AACA,wCAAe;AACf,qCAAY;AAEpB;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA,mCAAU,MAAM;
|
|
1
|
+
{"version":3,"file":"webrtc.cjs.js","sources":["../../../../../src/modules/collaborative-editing/provider/webrtc.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\nimport type { ProviderEventHandlers } from '../types'\nimport type { UnifiedProvider } from './providerRegistry'\nimport { WebrtcProvider } from 'y-webrtc'\nimport * as Y from 'yjs'\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 }: {\n options: WebRTCProviderOptions\n awareness?: Awareness\n doc?: Y.Doc\n } & ProviderEventHandlers) {\n this.onConnect = onConnect\n this.onDisconnect = onDisconnect\n this.onError = onError\n this.onSyncChange = onSyncChange\n\n this.document = doc || new Y.Doc()\n try {\n this.provider = new WebrtcProvider(options.roomName, this.document, {\n 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":["Y","WebrtcProvider"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAeO,MAAM,sBAAiD;AAAA,EA2C5D,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,GAKyB;AAtDnB;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;AAeE,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,UAAU;AACf,SAAK,eAAe;AAEpB,SAAK,WAAW,OAAO,IAAIA,aAAE,IAAA;AAC7B,QAAI;AACF,WAAK,WAAW,IAAIC,QAAAA,eAAe,QAAQ,UAAU,KAAK,UAAU;AAAA,QAClE;AAAA,QACA,GAAG;AAAA,MAAA,CACJ;AAED,WAAK,SAAS,GAAG,UAAU,CAAC,WAAmC;;AAC7D,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.cjs.js","sources":["../../../../../src/modules/collaborative-editing/provider/websocket.ts"],"sourcesContent":["import type { ProviderEventHandlers } from '../types'\nimport type { UnifiedProvider } from './providerRegistry'\nimport { Awareness } from 'y-protocols/awareness'\nimport { WebsocketProvider } from 'y-websocket'\nimport * as Y from 'yjs'\n\nexport interface WebsocketProviderOptions {\n serverUrl: string\n roomName: string\n connect?: boolean\n awareness?: any\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 }: {\n options: WebsocketProviderOptions\n awareness?: Awareness\n doc?: Y.Doc\n } & ProviderEventHandlers) {\n this.onConnect = onConnect\n this.onDisconnect = onDisconnect\n this.onError = onError\n this.onSyncChange = onSyncChange\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":["awareness","Y","Awareness","WebsocketProvider"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAmBO,MAAM,yBAAoD;AAAA,EAkD/D,YAAY;AAAA,IAAA,WACVA;AAAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,GAKyB;AA7DnB;AAEA,wCAAe;AACf,qCAAY;AAEpB;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA,mCAAU,MAAM;
|
|
1
|
+
{"version":3,"file":"websocket.cjs.js","sources":["../../../../../src/modules/collaborative-editing/provider/websocket.ts"],"sourcesContent":["import type { ProviderEventHandlers } from '../types'\nimport type { UnifiedProvider } from './providerRegistry'\nimport { Awareness } from 'y-protocols/awareness'\nimport { WebsocketProvider } from 'y-websocket'\nimport * as Y from 'yjs'\n\nexport interface WebsocketProviderOptions {\n serverUrl: string\n roomName: string\n connect?: boolean\n awareness?: any\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 }: {\n options: WebsocketProviderOptions\n awareness?: Awareness\n doc?: Y.Doc\n } & ProviderEventHandlers) {\n this.onConnect = onConnect\n this.onDisconnect = onDisconnect\n this.onError = onError\n this.onSyncChange = onSyncChange\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":["awareness","Y","Awareness","WebsocketProvider"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAmBO,MAAM,yBAAoD;AAAA,EAkD/D,YAAY;AAAA,IAAA,WACVA;AAAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,GAKyB;AA7DnB;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;;AACjB,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;AAeE,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,UAAU;AACf,SAAK,eAAe;AAEpB,SAAK,WAAW,OAAO,IAAIC,aAAE,IAAA;AAC7B,SAAK,YAAYD,eAAa,IAAIE,UAAAA,UAAU,KAAK,QAAQ;AACzD,QAAI;AACF,WAAK,WAAW,IAAIC,WAAAA;AAAAA,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;;AAC7F,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.cjs.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":["CHANGE_LANGUAGE_EVENT"],"mappings":";;;;;;;;AAaA,MAAqB,QAAQ;AAAA,EAI3B,YAAmB,OAAqB,SAAyB;AAHjE;AACA;AAsBA,uCAAc,MAAM;AAClB,iBAAW,MAAM;
|
|
1
|
+
{"version":3,"file":"counter.cjs.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":["CHANGE_LANGUAGE_EVENT"],"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,GAAGA,cAAAA,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.cjs.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":["isString","isNullOrUndefined","BIG_DELTA_LIMIT","replaceDeltaImage","imageUrlToFile","ERROR_IMAGE_PLACEHOLDER_EN","ERROR_IMAGE_PLACEHOLDER_CN","splitWithBreak","omit","hexToRgbA"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"custom-clipboard.cjs.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":["isString","isNullOrUndefined","BIG_DELTA_LIMIT","replaceDeltaImage","imageUrlToFile","ERROR_IMAGE_PLACEHOLDER_EN","ERROR_IMAGE_PLACEHOLDER_CN","splitWithBreak","omit","hexToRgbA"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.cjs.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,
|
|
1
|
+
{"version":3,"file":"action.cjs.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;;"}
|