@opentiny/fluent-editor 4.0.0-alpha.10 → 4.0.0-alpha.12
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 +6 -7
- package/es/modules/collaborative-editing/awareness/awareness.es.js.map +1 -1
- package/es/modules/collaborative-editing/awareness/y-indexeddb.es.js +7 -3
- package/es/modules/collaborative-editing/awareness/y-indexeddb.es.js.map +1 -1
- package/es/modules/collaborative-editing/collaborative-editing.es.js +13 -8
- 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 +8 -4
- package/es/modules/collaborative-editing/provider/webrtc.es.js.map +1 -1
- package/es/modules/collaborative-editing/provider/websocket.es.js +6 -4
- 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/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 +425 -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/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/flow-chart.css +185 -0
- 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 +6 -24
- package/lib/modules/collaborative-editing/awareness/awareness.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/awareness/y-indexeddb.cjs.js +7 -3
- package/lib/modules/collaborative-editing/awareness/y-indexeddb.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/collaborative-editing.cjs.js +19 -31
- 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 +10 -23
- package/lib/modules/collaborative-editing/provider/webrtc.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/provider/websocket.cjs.js +10 -25
- 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/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 +425 -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/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/mind-map.css +224 -0
- package/package.json +1 -34
- package/patches/quill@2.0.3.patch +33 -0
- package/scripts/apply-patches.cjs +248 -0
- 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/collaborative-editing/awareness/awareness.d.ts +2 -2
- package/types/modules/collaborative-editing/awareness/y-indexeddb.d.ts +3 -2
- package/types/modules/collaborative-editing/collaborative-editing.d.ts +4 -3
- package/types/modules/collaborative-editing/provider/providerRegistry.d.ts +2 -1
- package/types/modules/collaborative-editing/provider/webrtc.d.ts +5 -4
- package/types/modules/collaborative-editing/provider/websocket.d.ts +6 -5
- package/types/modules/collaborative-editing/types.d.ts +17 -1
- 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 +27 -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,23 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const Y = require("yjs");
|
|
4
|
-
function _interopNamespaceDefault(e) {
|
|
5
|
-
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
6
|
-
if (e) {
|
|
7
|
-
for (const k in e) {
|
|
8
|
-
if (k !== "default") {
|
|
9
|
-
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
10
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
11
|
-
enumerable: true,
|
|
12
|
-
get: () => e[k]
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
n.default = e;
|
|
18
|
-
return Object.freeze(n);
|
|
19
|
-
}
|
|
20
|
-
const Y__namespace = /* @__PURE__ */ _interopNamespaceDefault(Y);
|
|
21
3
|
function setupAwareness(options, defaultAwareness) {
|
|
22
4
|
if (!defaultAwareness) return null;
|
|
23
5
|
const awareness = defaultAwareness;
|
|
@@ -26,7 +8,7 @@ function setupAwareness(options, defaultAwareness) {
|
|
|
26
8
|
}
|
|
27
9
|
return awareness;
|
|
28
10
|
}
|
|
29
|
-
function bindAwarenessToCursors(awareness, cursorsModule, quill, yText) {
|
|
11
|
+
function bindAwarenessToCursors(awareness, cursorsModule, quill, yText, Yjs) {
|
|
30
12
|
if (!cursorsModule || !awareness) return;
|
|
31
13
|
const doc = yText.doc;
|
|
32
14
|
const updateCursor = (clientId, state) => {
|
|
@@ -36,8 +18,8 @@ function bindAwarenessToCursors(awareness, cursorsModule, quill, yText) {
|
|
|
36
18
|
const color = user.color || "#ff6b6b";
|
|
37
19
|
const name = user.name || `User ${clientId}`;
|
|
38
20
|
cursorsModule.createCursor(clientId.toString(), name, color);
|
|
39
|
-
const anchor =
|
|
40
|
-
const head =
|
|
21
|
+
const anchor = Yjs.createAbsolutePositionFromRelativePosition(Yjs.createRelativePositionFromJSON(state.cursor.anchor), doc);
|
|
22
|
+
const head = Yjs.createAbsolutePositionFromRelativePosition(Yjs.createRelativePositionFromJSON(state.cursor.head), doc);
|
|
41
23
|
if (anchor && head && anchor.type === yText && clientId) {
|
|
42
24
|
setTimeout(() => {
|
|
43
25
|
cursorsModule.moveCursor(clientId.toString(), {
|
|
@@ -57,10 +39,10 @@ function bindAwarenessToCursors(awareness, cursorsModule, quill, yText) {
|
|
|
57
39
|
setTimeout(() => {
|
|
58
40
|
var _a;
|
|
59
41
|
if (range) {
|
|
60
|
-
const anchor =
|
|
61
|
-
const head =
|
|
42
|
+
const anchor = Yjs.createRelativePositionFromTypeIndex(yText, range.index);
|
|
43
|
+
const head = Yjs.createRelativePositionFromTypeIndex(yText, range.index + range.length);
|
|
62
44
|
const currentState = awareness.getLocalState();
|
|
63
|
-
if (!(currentState == null ? void 0 : currentState.cursor) || !
|
|
45
|
+
if (!(currentState == null ? void 0 : currentState.cursor) || !Yjs.compareRelativePositions(anchor, currentState.cursor.anchor) || !Yjs.compareRelativePositions(head, currentState.cursor.head)) {
|
|
64
46
|
awareness.setLocalStateField("cursor", { anchor, head });
|
|
65
47
|
}
|
|
66
48
|
} else {
|
|
@@ -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
|
|
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 * as Y from 'yjs'\nimport type FluentEditor from '../../../core/fluent-editor'\n\nexport interface AwarenessState {\n name?: string\n color?: string\n}\n\nexport interface AwarenessEvents {\n change?: (changes: { added: number[], updated: number[], removed: number[] }, transactionOrigin: any) => void\n update?: ({ added, updated, removed }: { added: number[], updated: number[], removed: number[] }, origin: any) => void\n destroy?: () => void\n}\n\nexport interface AwarenessOptions {\n state?: AwarenessState\n events?: AwarenessEvents\n timeout?: number | undefined\n}\n\nexport function setupAwareness(options?: AwarenessOptions, defaultAwareness?: Awareness): Awareness | null {\n if (!defaultAwareness) return null\n\n const awareness = defaultAwareness\n\n if (options?.state) {\n awareness.setLocalStateField('user', options.state)\n }\n\n return awareness\n}\n\nexport function bindAwarenessToCursors(\n awareness: Awareness,\n cursorsModule: QuillCursors,\n quill: FluentEditor,\n yText: Y.Text,\n Yjs: typeof Y,\n): (() => void) | void {\n if (!cursorsModule || !awareness) return\n\n const doc = yText.doc!\n\n const updateCursor = (clientId: number, state: any) => {\n try {\n if (state?.cursor && clientId !== awareness.clientID) {\n const user = state.user || {}\n const color = user.color || '#ff6b6b'\n const name = user.name || `User ${clientId}`\n\n cursorsModule.createCursor(clientId.toString(), name, color)\n\n const anchor = Yjs.createAbsolutePositionFromRelativePosition(Yjs.createRelativePositionFromJSON(state.cursor.anchor), doc)\n const head = Yjs.createAbsolutePositionFromRelativePosition(Yjs.createRelativePositionFromJSON(state.cursor.head), doc)\n\n if (anchor && head && anchor.type === yText && clientId) {\n setTimeout(() => {\n cursorsModule.moveCursor(clientId.toString(), {\n index: anchor.index,\n length: head.index - anchor.index,\n })\n }, 0)\n }\n }\n else {\n cursorsModule.removeCursor(clientId.toString())\n }\n }\n catch (err) {\n console.error('Cursor update failed:', err)\n }\n }\n\n const selectionChangeHandler = (range: { index: number, length: number } | null) => {\n setTimeout(() => {\n if (range) {\n const anchor = Yjs.createRelativePositionFromTypeIndex(yText, range.index)\n const head = Yjs.createRelativePositionFromTypeIndex(yText, range.index + range.length)\n\n const currentState = awareness.getLocalState()\n if (!currentState?.cursor\n || !Yjs.compareRelativePositions(anchor, currentState.cursor.anchor)\n || !Yjs.compareRelativePositions(head, currentState.cursor.head)) {\n awareness.setLocalStateField('cursor', { anchor, head })\n }\n }\n else {\n if (awareness.getLocalState()?.cursor !== null) {\n awareness.setLocalStateField('cursor', null)\n }\n }\n }, 0)\n }\n\n const changeHandler = ({ added, updated, removed }: {\n added: number[]\n updated: number[]\n removed: number[]\n }) => {\n if (quill.composition.isComposing) return\n const states = awareness.getStates()\n\n added.forEach((id) => {\n updateCursor(id, states.get(id))\n })\n\n updated.forEach((id) => {\n updateCursor(id, states.get(id))\n })\n\n removed.forEach((id) => {\n cursorsModule.removeCursor(id.toString())\n })\n }\n\n awareness.on('change', changeHandler)\n quill.on('editor-change', (eventName, ...args) => {\n if (quill.composition.isComposing) return\n if (eventName === 'text-change') {\n if (args[2] === 'user') {\n const range = quill.getSelection()\n selectionChangeHandler(range)\n }\n }\n else if (eventName === 'selection-change') {\n if (args[2] === 'user') {\n selectionChangeHandler(args[0] as { index: number, length: number } | null)\n }\n }\n })\n\n awareness.getStates().forEach((state, clientId) => {\n updateCursor(clientId, state)\n })\n\n return () => {\n awareness.off('change', changeHandler)\n quill.off('editor-change', selectionChangeHandler)\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
function setupIndexedDB(doc, IndexeddbPersistenceClass) {
|
|
4
|
+
if (!IndexeddbPersistenceClass) {
|
|
5
|
+
console.warn("[yjs] IndexeddbPersistence not provided, offline support disabled");
|
|
6
|
+
return () => {
|
|
7
|
+
};
|
|
8
|
+
}
|
|
5
9
|
const fullDbName = `tiny-editor-${doc.guid}`;
|
|
6
|
-
new
|
|
10
|
+
new IndexeddbPersistenceClass(fullDbName, doc);
|
|
7
11
|
return () => {
|
|
8
12
|
indexedDB.deleteDatabase(fullDbName);
|
|
9
13
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"y-indexeddb.cjs.js","sources":["../../../../../src/modules/collaborative-editing/awareness/y-indexeddb.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"y-indexeddb.cjs.js","sources":["../../../../../src/modules/collaborative-editing/awareness/y-indexeddb.ts"],"sourcesContent":["import type { IndexeddbPersistence } from 'y-indexeddb'\nimport type * as Y from 'yjs'\n\nexport function setupIndexedDB(doc: Y.Doc, IndexeddbPersistenceClass?: typeof IndexeddbPersistence): () => void {\n if (!IndexeddbPersistenceClass) {\n console.warn('[yjs] IndexeddbPersistence not provided, offline support disabled')\n return () => {}\n }\n\n const fullDbName = `tiny-editor-${doc.guid}`\n\n new IndexeddbPersistenceClass(fullDbName, doc)\n\n return (): void => {\n indexedDB.deleteDatabase(fullDbName)\n }\n}\n"],"names":[],"mappings":";;AAGO,SAAS,eAAe,KAAY,2BAAqE;AAC9G,MAAI,CAAC,2BAA2B;AAC9B,YAAQ,KAAK,mEAAmE;AAChF,WAAO,MAAM;AAAA,IAAC;AAAA,EAChB;AAEA,QAAM,aAAa,eAAe,IAAI,IAAI;AAE1C,MAAI,0BAA0B,YAAY,GAAG;AAE7C,SAAO,MAAY;AACjB,cAAU,eAAe,UAAU;AAAA,EACrC;AACF;;"}
|
|
@@ -3,54 +3,41 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
-
const QuillCursors = require("quill-cursors");
|
|
7
|
-
const awareness$1 = require("y-protocols/awareness");
|
|
8
|
-
const yQuill = require("y-quill");
|
|
9
|
-
const Y = require("yjs");
|
|
10
6
|
require("./awareness/index.cjs.js");
|
|
11
7
|
const yIndexeddb = require("./awareness/y-indexeddb.cjs.js");
|
|
12
8
|
const providerRegistry = require("./provider/providerRegistry.cjs.js");
|
|
13
9
|
const awareness = require("./awareness/awareness.cjs.js");
|
|
14
|
-
function _interopNamespaceDefault(e) {
|
|
15
|
-
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
16
|
-
if (e) {
|
|
17
|
-
for (const k in e) {
|
|
18
|
-
if (k !== "default") {
|
|
19
|
-
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
20
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
21
|
-
enumerable: true,
|
|
22
|
-
get: () => e[k]
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
n.default = e;
|
|
28
|
-
return Object.freeze(n);
|
|
29
|
-
}
|
|
30
|
-
const Y__namespace = /* @__PURE__ */ _interopNamespaceDefault(Y);
|
|
31
10
|
class CollaborativeEditor {
|
|
32
11
|
constructor(quill, options) {
|
|
33
|
-
__publicField(this, "ydoc"
|
|
12
|
+
__publicField(this, "ydoc");
|
|
34
13
|
__publicField(this, "provider");
|
|
35
14
|
__publicField(this, "awareness");
|
|
36
15
|
__publicField(this, "cursors");
|
|
37
16
|
__publicField(this, "cleanupBindings", null);
|
|
38
17
|
__publicField(this, "clearIndexedDB", null);
|
|
18
|
+
__publicField(this, "deps");
|
|
39
19
|
this.quill = quill;
|
|
40
20
|
this.options = options;
|
|
41
|
-
this.
|
|
21
|
+
this.deps = this.options.deps || window;
|
|
22
|
+
const { Y, Awareness, QuillBinding, QuillCursors } = this.deps;
|
|
23
|
+
if (!Y || !Awareness || !QuillBinding || !QuillCursors) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
"Missing required dependencies for collaborative editing. Please provide Y, Awareness, QuillBinding, and QuillCursors in the deps option."
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
this.ydoc = this.options.ydoc || new Y.Doc();
|
|
42
29
|
if (this.options.cursors !== false) {
|
|
43
30
|
const cursorsOptions = typeof this.options.cursors === "object" ? this.options.cursors : {};
|
|
44
31
|
this.cursors = new QuillCursors(quill, cursorsOptions);
|
|
45
32
|
}
|
|
46
33
|
if (this.options.awareness) {
|
|
47
|
-
const awareness$
|
|
48
|
-
if (!awareness$
|
|
34
|
+
const awareness$1 = awareness.setupAwareness(this.options.awareness, new Awareness(this.ydoc));
|
|
35
|
+
if (!awareness$1) {
|
|
49
36
|
throw new Error("Failed to initialize awareness");
|
|
50
37
|
}
|
|
51
|
-
this.awareness = awareness$
|
|
38
|
+
this.awareness = awareness$1;
|
|
52
39
|
} else {
|
|
53
|
-
this.awareness = new
|
|
40
|
+
this.awareness = new Awareness(this.ydoc);
|
|
54
41
|
}
|
|
55
42
|
if (this.options.provider) {
|
|
56
43
|
const providerConfig = this.options.provider;
|
|
@@ -63,7 +50,8 @@ class CollaborativeEditor {
|
|
|
63
50
|
onConnect: this.options.onConnect,
|
|
64
51
|
onDisconnect: this.options.onDisconnect,
|
|
65
52
|
onError: this.options.onError,
|
|
66
|
-
onSyncChange: this.options.onSyncChange
|
|
53
|
+
onSyncChange: this.options.onSyncChange,
|
|
54
|
+
deps: this.deps
|
|
67
55
|
});
|
|
68
56
|
this.provider = provider;
|
|
69
57
|
} catch (error) {
|
|
@@ -75,8 +63,8 @@ class CollaborativeEditor {
|
|
|
75
63
|
}
|
|
76
64
|
if (this.provider) {
|
|
77
65
|
const ytext = this.ydoc.getText("tiny-editor");
|
|
78
|
-
this.cleanupBindings = awareness.bindAwarenessToCursors(this.awareness, this.cursors, quill, ytext) || null;
|
|
79
|
-
new
|
|
66
|
+
this.cleanupBindings = awareness.bindAwarenessToCursors(this.awareness, this.cursors, quill, ytext, Y) || null;
|
|
67
|
+
new QuillBinding(
|
|
80
68
|
ytext,
|
|
81
69
|
this.quill,
|
|
82
70
|
this.awareness
|
|
@@ -85,7 +73,7 @@ class CollaborativeEditor {
|
|
|
85
73
|
console.error("Failed to initialize collaborative editor: no valid provider configured");
|
|
86
74
|
}
|
|
87
75
|
if (this.options.offline !== false) {
|
|
88
|
-
this.clearIndexedDB = yIndexeddb.setupIndexedDB(this.ydoc);
|
|
76
|
+
this.clearIndexedDB = yIndexeddb.setupIndexedDB(this.ydoc, this.deps.IndexeddbPersistence);
|
|
89
77
|
}
|
|
90
78
|
}
|
|
91
79
|
getAwareness() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collaborative-editing.cjs.js","sources":["../../../../src/modules/collaborative-editing/collaborative-editing.ts"],"sourcesContent":["import type
|
|
1
|
+
{"version":3,"file":"collaborative-editing.cjs.js","sources":["../../../../src/modules/collaborative-editing/collaborative-editing.ts"],"sourcesContent":["import type QuillCursors from 'quill-cursors'\nimport type { Awareness } from 'y-protocols/awareness'\nimport type * as Y from 'yjs'\nimport type FluentEditor from '../../fluent-editor'\nimport type { UnifiedProvider } from './provider/providerRegistry'\nimport type { CollaborativeEditingDeps, YjsOptions } from './types'\nimport { bindAwarenessToCursors, setupAwareness } from './awareness'\nimport { setupIndexedDB } from './awareness/y-indexeddb'\nimport { createProvider } from './provider/providerRegistry'\n\nexport class CollaborativeEditor {\n private ydoc: Y.Doc\n private provider: UnifiedProvider\n private awareness: Awareness\n private cursors: QuillCursors | null\n private cleanupBindings: (() => void) | null = null\n private clearIndexedDB: (() => void) | null = null\n private deps: CollaborativeEditingDeps\n\n constructor(\n public quill: FluentEditor,\n public options: YjsOptions,\n ) {\n this.deps = this.options.deps || (window as any)\n const { Y, Awareness, QuillBinding, QuillCursors } = this.deps\n\n if (!Y || !Awareness || !QuillBinding || !QuillCursors) {\n throw new Error(\n 'Missing required dependencies for collaborative editing. '\n + 'Please provide Y, Awareness, QuillBinding, and QuillCursors in the deps option.',\n )\n }\n\n this.ydoc = this.options.ydoc || new Y.Doc()\n\n if (this.options.cursors !== false) {\n const cursorsOptions = typeof this.options.cursors === 'object' ? this.options.cursors : {}\n this.cursors = new QuillCursors(quill, cursorsOptions)\n }\n\n if (this.options.awareness) {\n const awareness = setupAwareness(this.options.awareness, new Awareness(this.ydoc))\n if (!awareness) {\n throw new Error('Failed to initialize awareness')\n }\n this.awareness = awareness\n }\n else {\n this.awareness = new Awareness(this.ydoc)\n }\n\n if (this.options.provider) {\n const providerConfig = this.options.provider\n try {\n const provider = createProvider({\n doc: this.ydoc,\n options: providerConfig.options,\n type: providerConfig.type,\n awareness: this.awareness,\n onConnect: this.options.onConnect,\n onDisconnect: this.options.onDisconnect,\n onError: this.options.onError,\n onSyncChange: this.options.onSyncChange,\n deps: this.deps,\n })\n this.provider = provider\n }\n catch (error) {\n console.warn(\n `[yjs] Error creating provider of type ${providerConfig.type}:`,\n error,\n )\n }\n }\n\n if (this.provider) {\n const ytext = this.ydoc.getText('tiny-editor')\n this.cleanupBindings = bindAwarenessToCursors(this.awareness, this.cursors, quill, ytext, Y) || null\n new QuillBinding(\n ytext,\n this.quill,\n this.awareness,\n )\n }\n else {\n console.error('Failed to initialize collaborative editor: no valid provider configured')\n }\n\n if (this.options.offline !== false) {\n this.clearIndexedDB = setupIndexedDB(this.ydoc, this.deps.IndexeddbPersistence)\n }\n }\n\n public getAwareness() {\n return this.awareness\n }\n\n public getProvider() {\n return this.provider\n }\n\n public getYDoc() {\n return this.ydoc\n }\n\n get isConnected() {\n return this.provider?.isConnected ?? false\n }\n\n get isSynced() {\n return this.provider?.isSynced ?? false\n }\n\n public getCursors() {\n return this.cursors\n }\n\n public async destroy() {\n this.cleanupBindings?.()\n this.provider?.destroy?.()\n this.cursors?.clearCursors()\n this.awareness?.destroy?.()\n this.clearIndexedDB?.()\n this.ydoc?.destroy?.()\n }\n}\n"],"names":["awareness","setupAwareness","createProvider","bindAwarenessToCursors","setupIndexedDB"],"mappings":";;;;;;;;;AAUO,MAAM,oBAAoB;AAAA,EAS/B,YACS,OACA,SACP;AAXM;AACA;AACA;AACA;AACA,2CAAuC;AACvC,0CAAsC;AACtC;AAGC,SAAA,QAAA;AACA,SAAA,UAAA;AAEP,SAAK,OAAO,KAAK,QAAQ,QAAS;AAClC,UAAM,EAAE,GAAG,WAAW,cAAc,aAAA,IAAiB,KAAK;AAE1D,QAAI,CAAC,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,cAAc;AACtD,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAGJ;AAEA,SAAK,OAAO,KAAK,QAAQ,QAAQ,IAAI,EAAE,IAAA;AAEvC,QAAI,KAAK,QAAQ,YAAY,OAAO;AAClC,YAAM,iBAAiB,OAAO,KAAK,QAAQ,YAAY,WAAW,KAAK,QAAQ,UAAU,CAAA;AACzF,WAAK,UAAU,IAAI,aAAa,OAAO,cAAc;AAAA,IACvD;AAEA,QAAI,KAAK,QAAQ,WAAW;AAC1B,YAAMA,cAAYC,yBAAe,KAAK,QAAQ,WAAW,IAAI,UAAU,KAAK,IAAI,CAAC;AACjF,UAAI,CAACD,aAAW;AACd,cAAM,IAAI,MAAM,gCAAgC;AAAA,MAClD;AACA,WAAK,YAAYA;AAAAA,IACnB,OACK;AACH,WAAK,YAAY,IAAI,UAAU,KAAK,IAAI;AAAA,IAC1C;AAEA,QAAI,KAAK,QAAQ,UAAU;AACzB,YAAM,iBAAiB,KAAK,QAAQ;AACpC,UAAI;AACF,cAAM,WAAWE,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,UAC3B,MAAM,KAAK;AAAA,QAAA,CACZ;AACD,aAAK,WAAW;AAAA,MAClB,SACO,OAAO;AACZ,gBAAQ;AAAA,UACN,yCAAyC,eAAe,IAAI;AAAA,UAC5D;AAAA,QAAA;AAAA,MAEJ;AAAA,IACF;AAEA,QAAI,KAAK,UAAU;AACjB,YAAM,QAAQ,KAAK,KAAK,QAAQ,aAAa;AAC7C,WAAK,kBAAkBC,iCAAuB,KAAK,WAAW,KAAK,SAAS,OAAO,OAAO,CAAC,KAAK;AAChG,UAAI;AAAA,QACF;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MAAA;AAAA,IAET,OACK;AACH,cAAQ,MAAM,yEAAyE;AAAA,IACzF;AAEA,QAAI,KAAK,QAAQ,YAAY,OAAO;AAClC,WAAK,iBAAiBC,0BAAe,KAAK,MAAM,KAAK,KAAK,oBAAoB;AAAA,IAChF;AAAA,EACF;AAAA,EAEO,eAAe;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,cAAc;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,UAAU;AACf,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,cAAc;;AAChB,aAAO,UAAK,aAAL,mBAAe,gBAAe;AAAA,EACvC;AAAA,EAEA,IAAI,WAAW;;AACb,aAAO,UAAK,aAAL,mBAAe,aAAY;AAAA,EACpC;AAAA,EAEO,aAAa;AAClB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAa,UAAU;;AACrB,eAAK,oBAAL;AACA,qBAAK,aAAL,mBAAe,YAAf;AACA,eAAK,YAAL,mBAAc;AACd,qBAAK,cAAL,mBAAgB,YAAhB;AACA,eAAK,mBAAL;AACA,qBAAK,SAAL,mBAAW,YAAX;AAAA,EACF;AACF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.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":";;;;
|
|
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 { CollaborativeEditingDeps, ProviderEventHandlers } from '../types'\nimport { WebRTCProviderWrapper } from './webrtc'\nimport { WebsocketProviderWrapper } from './websocket'\n\nexport type ProviderRegistry = Record<string, ProviderConstructor>\n\nexport type ProviderConstructor<T = any> = new (\n props: ProviderConstructorProps<T>\n) => UnifiedProvider\n\nexport type ProviderConstructorProps<T = any> = {\n options: T\n awareness?: Awareness\n doc?: Y.Doc\n deps?: CollaborativeEditingDeps\n} & ProviderEventHandlers\n\nexport interface UnifiedProvider extends ProviderEventHandlers {\n awareness: Awareness\n document: Y.Doc\n type: 'webrtc' | 'websocket' | string\n connect: () => void\n destroy: () => void\n disconnect: () => void\n isConnected: boolean\n isSynced: boolean\n}\n\nconst providerRegistry: ProviderRegistry = {\n websocket: WebsocketProviderWrapper,\n webrtc: WebRTCProviderWrapper,\n}\n\nexport function registerProviderType<T>(type: string, providerClass: ProviderConstructor<T>) {\n providerRegistry[type as string]\n = providerClass as ProviderConstructor\n}\n\nexport function getProviderClass(type: string): ProviderConstructor | undefined {\n return providerRegistry[type]\n}\n\nexport function createProvider({\n type,\n ...props\n}: ProviderConstructorProps & {\n type: string\n}) {\n const ProviderClass = getProviderClass(type)\n\n if (!ProviderClass) {\n throw new Error(`Provider type \"${type}\" not found in registry`)\n }\n\n return new ProviderClass(props)\n}\n"],"names":["WebsocketProviderWrapper","WebRTCProviderWrapper"],"mappings":";;;;AA8BA,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;;;;"}
|
|
@@ -3,25 +3,6 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
-
const yWebrtc = require("y-webrtc");
|
|
7
|
-
const Y = require("yjs");
|
|
8
|
-
function _interopNamespaceDefault(e) {
|
|
9
|
-
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
10
|
-
if (e) {
|
|
11
|
-
for (const k in e) {
|
|
12
|
-
if (k !== "default") {
|
|
13
|
-
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
-
enumerable: true,
|
|
16
|
-
get: () => e[k]
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
n.default = e;
|
|
22
|
-
return Object.freeze(n);
|
|
23
|
-
}
|
|
24
|
-
const Y__namespace = /* @__PURE__ */ _interopNamespaceDefault(Y);
|
|
25
6
|
class WebRTCProviderWrapper {
|
|
26
7
|
constructor({
|
|
27
8
|
awareness,
|
|
@@ -30,7 +11,8 @@ class WebRTCProviderWrapper {
|
|
|
30
11
|
onConnect,
|
|
31
12
|
onDisconnect,
|
|
32
13
|
onError,
|
|
33
|
-
onSyncChange
|
|
14
|
+
onSyncChange,
|
|
15
|
+
deps
|
|
34
16
|
}) {
|
|
35
17
|
__publicField(this, "provider");
|
|
36
18
|
__publicField(this, "_isConnected", false);
|
|
@@ -69,10 +51,15 @@ class WebRTCProviderWrapper {
|
|
|
69
51
|
this.onDisconnect = onDisconnect;
|
|
70
52
|
this.onError = onError;
|
|
71
53
|
this.onSyncChange = onSyncChange;
|
|
72
|
-
|
|
54
|
+
const { Y, Awareness, WebrtcProvider } = deps || window;
|
|
55
|
+
if (!WebrtcProvider) {
|
|
56
|
+
throw new Error("WebrtcProvider dependency not provided");
|
|
57
|
+
}
|
|
58
|
+
this.document = doc || new Y.Doc();
|
|
59
|
+
this.awareness = awareness ?? new Awareness(this.document);
|
|
73
60
|
try {
|
|
74
|
-
this.provider = new
|
|
75
|
-
awareness,
|
|
61
|
+
this.provider = new WebrtcProvider(options.roomName, this.document, {
|
|
62
|
+
awareness: this.awareness,
|
|
76
63
|
...options
|
|
77
64
|
});
|
|
78
65
|
this.provider.on("status", (status) => {
|
|
@@ -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 {
|
|
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 { WebrtcProvider } from 'y-webrtc'\nimport type * as Y from 'yjs'\nimport type { CollaborativeEditingDeps, ProviderEventHandlers } from '../types'\nimport type { UnifiedProvider } from './providerRegistry'\n\nexport interface WebRTCProviderOptions {\n roomName: string\n filterBcConns?: boolean\n maxConns?: number\n password?: string\n peerOpts?: Record<string, unknown>\n signaling?: string[]\n}\n\nexport class WebRTCProviderWrapper implements UnifiedProvider {\n private provider: WebrtcProvider\n private _isConnected = false\n private _isSynced = false\n\n onConnect?: () => void\n onDisconnect?: () => void\n onError?: (error: Error) => void\n onSyncChange?: (isSynced: boolean) => void\n\n document: Y.Doc\n awareness: Awareness\n type: 'webrtc'\n\n connect = () => {\n try {\n this.provider.connect()\n }\n catch (error) {\n console.warn('[yjs] Error connecting WebRTC provider:', error)\n }\n }\n\n destroy = () => {\n try {\n this.provider.destroy()\n }\n catch (error) {\n console.warn('[yjs] Error destroying WebRTC provider:', error)\n }\n }\n\n disconnect = () => {\n try {\n this.provider.disconnect()\n this._isConnected = false\n this._isSynced = false\n }\n catch (error) {\n console.warn('[yjs] Error disconnecting WebRTC provider:', error)\n }\n }\n\n constructor({\n awareness,\n doc,\n options,\n onConnect,\n onDisconnect,\n onError,\n onSyncChange,\n deps,\n }: {\n options: WebRTCProviderOptions\n awareness?: Awareness\n doc?: Y.Doc\n deps?: CollaborativeEditingDeps\n } & ProviderEventHandlers) {\n this.onConnect = onConnect\n this.onDisconnect = onDisconnect\n this.onError = onError\n this.onSyncChange = onSyncChange\n\n const { Y, Awareness, WebrtcProvider } = deps || (window as any)\n\n if (!WebrtcProvider) {\n throw new Error('WebrtcProvider dependency not provided')\n }\n\n this.document = doc || new Y.Doc()\n this.awareness = awareness ?? new Awareness(this.document)\n try {\n this.provider = new WebrtcProvider(options.roomName, this.document, {\n awareness: this.awareness,\n ...options,\n })\n\n this.provider.on('status', (status: { connected: boolean }) => {\n const wasConnected = this._isConnected\n this._isConnected = status.connected\n if (status.connected) {\n if (!wasConnected) {\n this.onConnect?.()\n }\n if (!this._isSynced) {\n this._isSynced = true\n this.onSyncChange?.(true)\n }\n }\n else {\n if (wasConnected) {\n this.onDisconnect?.()\n\n if (this._isSynced) {\n this._isSynced = false\n this.onSyncChange?.(false)\n }\n }\n }\n })\n }\n catch (error) {\n console.warn('[yjs] Error creating WebRTC provider:', error)\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n get isConnected() {\n return this._isConnected\n }\n\n get isSynced() {\n return this._isSynced\n }\n\n getProvider() {\n return this.provider\n }\n}\n"],"names":[],"mappings":";;;;;AAeO,MAAM,sBAAiD;AAAA,EA2C5D,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,GAMyB;AAxDnB;AACA,wCAAe;AACf,qCAAY;AAEpB;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA,mCAAU,MAAM;AACd,UAAI;AACF,aAAK,SAAS,QAAA;AAAA,MAChB,SACO,OAAO;AACZ,gBAAQ,KAAK,2CAA2C,KAAK;AAAA,MAC/D;AAAA,IACF;AAEA,mCAAU,MAAM;AACd,UAAI;AACF,aAAK,SAAS,QAAA;AAAA,MAChB,SACO,OAAO;AACZ,gBAAQ,KAAK,2CAA2C,KAAK;AAAA,MAC/D;AAAA,IACF;AAEA,sCAAa,MAAM;AACjB,UAAI;AACF,aAAK,SAAS,WAAA;AACd,aAAK,eAAe;AACpB,aAAK,YAAY;AAAA,MACnB,SACO,OAAO;AACZ,gBAAQ,KAAK,8CAA8C,KAAK;AAAA,MAClE;AAAA,IACF;AAiBE,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,UAAU;AACf,SAAK,eAAe;AAEpB,UAAM,EAAE,GAAG,WAAW,eAAA,IAAmB,QAAS;AAElD,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AAEA,SAAK,WAAW,OAAO,IAAI,EAAE,IAAA;AAC7B,SAAK,YAAY,aAAa,IAAI,UAAU,KAAK,QAAQ;AACzD,QAAI;AACF,WAAK,WAAW,IAAI,eAAe,QAAQ,UAAU,KAAK,UAAU;AAAA,QAClE,WAAW,KAAK;AAAA,QAChB,GAAG;AAAA,MAAA,CACJ;AAED,WAAK,SAAS,GAAG,UAAU,CAAC,WAAmC;;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;;"}
|