| 
          import { | 
        
        
           | 
            TextChangeHandler, | 
        
        
           | 
            SelectionChangeHandler, | 
        
        
           | 
            EditorChangeHandler, | 
        
        
           | 
            QuillOptionsStatic, | 
        
        
           | 
            RangeStatic, | 
        
        
           | 
            Sources, | 
        
        
           | 
            Module, | 
        
        
           | 
          } from 'quill' | 
        
        
           | 
          
 | 
        
        
           | 
          import { PropType, nextTick, defineComponent, onBeforeUnmount, onMounted, ref, watch, h } from "vue"; | 
        
        
           | 
          import Quill from "quill"; | 
        
        
           | 
          import Delta from "quill-delta"; | 
        
        
           | 
          import { toolbarOptions, ToolbarOptions } from "./options"; | 
        
        
           | 
          
 | 
        
        
           | 
          type ContentPropType = string | Delta | undefined | null | 
        
        
           | 
          
 | 
        
        
           | 
          export const Editor = defineComponent({ | 
        
        
           | 
            name: 'Editor', | 
        
        
           | 
            inheritAttrs: false, | 
        
        
           | 
            props: { | 
        
        
           | 
              content: { | 
        
        
           | 
                type: [String, Object] as PropType<ContentPropType>, | 
        
        
           | 
                default: null, | 
        
        
           | 
              }, | 
        
        
           | 
              contentType: { | 
        
        
           | 
                type: String as PropType<'delta' | 'html' | 'text'>, | 
        
        
           | 
                default: "delta", | 
        
        
           | 
                validator: (value: string) => { | 
        
        
           | 
                  return ["delta", "html", "text"].includes(value); | 
        
        
           | 
                }, | 
        
        
           | 
              }, | 
        
        
           | 
              enable: { | 
        
        
           | 
                type: Boolean, | 
        
        
           | 
                default: true, | 
        
        
           | 
              }, | 
        
        
           | 
              readOnly: { | 
        
        
           | 
                type: Boolean, | 
        
        
           | 
                default: false, | 
        
        
           | 
              }, | 
        
        
           | 
              placeholder: { | 
        
        
           | 
                type: String, | 
        
        
           | 
                required: false, | 
        
        
           | 
              }, | 
        
        
           | 
              theme: { | 
        
        
           | 
                type: String as PropType<'snow' | 'bubble' | ''>, | 
        
        
           | 
                default: "snow", | 
        
        
           | 
                validator: (value: string) => { | 
        
        
           | 
                  return ["snow", "bubble", ""].includes(value); | 
        
        
           | 
                }, | 
        
        
           | 
              }, | 
        
        
           | 
              toolbar: { | 
        
        
           | 
                type: [String, Array, Object], | 
        
        
           | 
                required: false, | 
        
        
           | 
                validator: (value: string | unknown) => { | 
        
        
           | 
                  if (typeof value === "string" && value !== "") { | 
        
        
           | 
                    return value.charAt(0) === "#" | 
        
        
           | 
                      ? true | 
        
        
           | 
                      : Object.keys(toolbarOptions).indexOf(value) !== -1; | 
        
        
           | 
                  } | 
        
        
           | 
                  return true | 
        
        
           | 
                }, | 
        
        
           | 
              }, | 
        
        
           | 
              modules: { | 
        
        
           | 
                type: Object as PropType<Module | Module[]>, | 
        
        
           | 
                required: false, | 
        
        
           | 
              }, | 
        
        
           | 
              options: { | 
        
        
           | 
                type: Object as PropType<QuillOptionsStatic>, | 
        
        
           | 
                required: false, | 
        
        
           | 
              }, | 
        
        
           | 
              globalOptions: { | 
        
        
           | 
                type: Object as PropType<QuillOptionsStatic>, | 
        
        
           | 
                required: false, | 
        
        
           | 
              }, | 
        
        
           | 
            }, | 
        
        
           | 
          
 | 
        
        
           | 
            emits: [ | 
        
        
           | 
                "textChange", | 
        
        
           | 
                "selectionChange", | 
        
        
           | 
                "editorChange", | 
        
        
           | 
                "update:content", | 
        
        
           | 
                "blur", | 
        
        
           | 
                "focus", | 
        
        
           | 
                "ready", | 
        
        
           | 
            ], | 
        
        
           | 
          
 | 
        
        
           | 
            setup: (props, ctx) => { | 
        
        
           | 
               | 
        
        
           | 
              onMounted(() => { | 
        
        
           | 
                initialize(); | 
        
        
           | 
              }); | 
        
        
           | 
               | 
        
        
           | 
              onBeforeUnmount(() => { | 
        
        
           | 
                quill = null; | 
        
        
           | 
              }); | 
        
        
           | 
               | 
        
        
           | 
          
 | 
        
        
           | 
              let quill: Quill | null; | 
        
        
           | 
              let options: QuillOptionsStatic; | 
        
        
           | 
              const editor = ref<HTMLElement>(); | 
        
        
           | 
          
 | 
        
        
           | 
              const registerModule = (moduleName: string, module: any) => { | 
        
        
           | 
                if (Quill?.imports && moduleName in Quill.imports) { | 
        
        
           | 
                  return | 
        
        
           | 
                } | 
        
        
           | 
                Quill.register(moduleName, module) | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              const initialize = () => { | 
        
        
           | 
                if (!editor.value) return | 
        
        
           | 
                options = composeOptions() | 
        
        
           | 
                // Register modules | 
        
        
           | 
                if (props.modules) { | 
        
        
           | 
                  if (Array.isArray(props.modules)) { | 
        
        
           | 
                    for (const module of props.modules) { | 
        
        
           | 
                      registerModule(`modules/${module.name}`, module.module) | 
        
        
           | 
                    } | 
        
        
           | 
                  } else { | 
        
        
           | 
                    registerModule(`modules/${props.modules.name}`, props.modules.module) | 
        
        
           | 
                  } | 
        
        
           | 
                } | 
        
        
           | 
                // Create new Quill instance | 
        
        
           | 
                quill = new Quill(editor.value, options) | 
        
        
           | 
                // Set editor content | 
        
        
           | 
                setContents(props.content) | 
        
        
           | 
                // Set event handlers | 
        
        
           | 
                quill.on('text-change', handleTextChange) | 
        
        
           | 
                quill.on('selection-change', handleSelectionChange) | 
        
        
           | 
                quill.on('editor-change', handleEditorChange) | 
        
        
           | 
                // Remove editor class when theme changes | 
        
        
           | 
                if (props.theme !== 'bubble') editor.value.classList.remove('ql-bubble') | 
        
        
           | 
                if (props.theme !== 'snow') editor.value.classList.remove('ql-snow') | 
        
        
           | 
                // Fix clicking the quill toolbar is detected as blur event | 
        
        
           | 
                quill | 
        
        
           | 
                  .getModule('toolbar')?.container.addEventListener('mousedown', (e: MouseEvent) => { | 
        
        
           | 
                    e.preventDefault() | 
        
        
           | 
                  }) | 
        
        
           | 
                // Emit ready event | 
        
        
           | 
                ctx.emit('ready', quill) | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              const composeOptions = (): QuillOptionsStatic => { | 
        
        
           | 
                const clientOptions: QuillOptionsStatic = {}; | 
        
        
           | 
                if (props.theme !== "") clientOptions.theme = props.theme; | 
        
        
           | 
                if (props.readOnly) clientOptions.readOnly = props.readOnly; | 
        
        
           | 
                if (props.placeholder) clientOptions.placeholder = props.placeholder; | 
        
        
           | 
                if (props.toolbar && props.toolbar !== "") { | 
        
        
           | 
                  clientOptions.modules = { | 
        
        
           | 
                    toolbar: (() => { | 
        
        
           | 
                      if (typeof props.toolbar === "object") { | 
        
        
           | 
                        return props.toolbar; | 
        
        
           | 
                      } else if (typeof props.toolbar === "string") { | 
        
        
           | 
                        const str = props.toolbar; | 
        
        
           | 
                        return str.charAt(0) === "#" | 
        
        
           | 
                          ? props.toolbar | 
        
        
           | 
                          : toolbarOptions[props.toolbar as keyof ToolbarOptions]; | 
        
        
           | 
                      } | 
        
        
           | 
                      return; | 
        
        
           | 
                    })(), | 
        
        
           | 
                  }; | 
        
        
           | 
                } | 
        
        
           | 
                if (props.modules) { | 
        
        
           | 
                  const modules = (() => { | 
        
        
           | 
                    const modulesOption = {}; | 
        
        
           | 
                    if (Array.isArray(props.modules)) { | 
        
        
           | 
                      for (const module of props.modules) { | 
        
        
           | 
                        modulesOption[module.name] = module.options ?? {}; | 
        
        
           | 
                      } | 
        
        
           | 
                    } else { | 
        
        
           | 
                      modulesOption[props.modules.name] = props.modules.options ?? {}; | 
        
        
           | 
                    } | 
        
        
           | 
                    return modulesOption; | 
        
        
           | 
                  })(); | 
        
        
           | 
                  clientOptions.modules = Object.assign({}, clientOptions.modules, modules); | 
        
        
           | 
                } | 
        
        
           | 
               | 
        
        
           | 
                return Object.assign({}, props.globalOptions, props.options, clientOptions); | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const maybeClone = (delta: ContentPropType) => { | 
        
        
           | 
                return typeof delta === "object" && delta ? delta.slice() : delta; | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const deltaHasValuesOtherThanRetain = (delta: Delta) => { | 
        
        
           | 
                return Object.values(delta.ops).some( | 
        
        
           | 
                  (v) => !v.retain || Object.keys(v).length !== 1 | 
        
        
           | 
                ); | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              let internalModel: typeof props.content; | 
        
        
           | 
               | 
        
        
           | 
              const internalModelEquals = (against: ContentPropType) => { | 
        
        
           | 
                if (typeof internalModel === typeof against) { | 
        
        
           | 
                  if (against === internalModel) { | 
        
        
           | 
                    return true; | 
        
        
           | 
                  } | 
        
        
           | 
                  // Ref/Proxy does not support instanceof, so do a loose check | 
        
        
           | 
                  if ( | 
        
        
           | 
                    typeof against === "object" && | 
        
        
           | 
                    against && | 
        
        
           | 
                    typeof internalModel === "object" && | 
        
        
           | 
                    internalModel | 
        
        
           | 
                  ) { | 
        
        
           | 
                    return !deltaHasValuesOtherThanRetain(internalModel.diff(against as Delta)); | 
        
        
           | 
                  } | 
        
        
           | 
                } | 
        
        
           | 
                return false; | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const handleTextChange = (delta: Delta, oldContents: Delta, source: Sources) => { | 
        
        
           | 
                internalModel = maybeClone(getContents() as string | Delta); | 
        
        
           | 
                // Update v-model:content when text changes | 
        
        
           | 
                if (!internalModelEquals(props.content)) { | 
        
        
           | 
                  ctx.emit("update:content", internalModel); | 
        
        
           | 
                } | 
        
        
           | 
                ctx.emit("textChange", { delta, oldContents, source }); | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const isEditorFocus = ref<Boolean>(); | 
        
        
           | 
              const handleSelectionChange = (range, oldRange, source) => { | 
        
        
           | 
                // Set isEditorFocus if quill.hasFocus() | 
        
        
           | 
                isEditorFocus.value = !!quill?.hasFocus(); | 
        
        
           | 
                ctx.emit("selectionChange", { range, oldRange, source }); | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              watch(isEditorFocus, (focus) => { | 
        
        
           | 
                if (focus) ctx.emit("focus", editor); | 
        
        
           | 
                else ctx.emit("blur", editor); | 
        
        
           | 
              }); | 
        
        
           | 
               | 
        
        
           | 
              const handleEditorChange = (...args: | 
        
        
           | 
                | [ | 
        
        
           | 
                    name: 'text-change', | 
        
        
           | 
                    delta: Delta, | 
        
        
           | 
                    oldContents: Delta, | 
        
        
           | 
                    source: Sources | 
        
        
           | 
                  ] | 
        
        
           | 
                | [ | 
        
        
           | 
                    name: 'selection-change', | 
        
        
           | 
                    range: RangeStatic, | 
        
        
           | 
                    oldRange: RangeStatic, | 
        
        
           | 
                    source: Sources | 
        
        
           | 
                  ]) => { | 
        
        
           | 
                if (args[0] === "text-change") | 
        
        
           | 
                  ctx.emit("editorChange", { | 
        
        
           | 
                    name: args[0], | 
        
        
           | 
                    delta: args[1], | 
        
        
           | 
                    oldContents: args[2], | 
        
        
           | 
                    source: args[3], | 
        
        
           | 
                  }); | 
        
        
           | 
                if (args[0] === "selection-change") | 
        
        
           | 
                  ctx.emit("editorChange", { | 
        
        
           | 
                    name: args[0], | 
        
        
           | 
                    range: args[1], | 
        
        
           | 
                    oldRange: args[2], | 
        
        
           | 
                    source: args[3], | 
        
        
           | 
                  }); | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const getEditor = (): HTMLElement => { | 
        
        
           | 
                return editor.value as HTMLElement; | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const getToolbar = (): HTMLElement => { | 
        
        
           | 
                return quill?.getModule("toolbar")?.container; | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const getQuill = (): Quill => { | 
        
        
           | 
                if (quill) return quill; | 
        
        
           | 
                else | 
        
        
           | 
                  throw `The quill editor hasn't been instantiated yet, | 
        
        
           | 
                                  make sure to call this method when the editor ready | 
        
        
           | 
                                  or use v-on:ready="onReady(quill)" event instead.`; | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const getContents = (index?: number, length?: number) => { | 
        
        
           | 
                if (props.contentType === "html") { | 
        
        
           | 
                  return getHTML(); | 
        
        
           | 
                } else if (props.contentType === "text") { | 
        
        
           | 
                  return getText(index, length); | 
        
        
           | 
                } | 
        
        
           | 
                return quill?.getContents(index, length); | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const setContents = (content: ContentPropType, source: Sources = 'api') => { | 
        
        
           | 
                const normalizedContent = !content | 
        
        
           | 
                  ? props.contentType === "delta" | 
        
        
           | 
                    ? new Delta() | 
        
        
           | 
                    : "" | 
        
        
           | 
                  : content; | 
        
        
           | 
                if (props.contentType === "html") { | 
        
        
           | 
                  setHTML(normalizedContent as string); | 
        
        
           | 
                } else if (props.contentType === "text") { | 
        
        
           | 
                  setText(normalizedContent as string, source); | 
        
        
           | 
                } else { | 
        
        
           | 
                  quill?.setContents(normalizedContent as Delta, source); | 
        
        
           | 
                } | 
        
        
           | 
                internalModel = maybeClone(normalizedContent); | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const getText = (index?: number, length?: number): string => { | 
        
        
           | 
                return quill?.getText(index, length) ?? ""; | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const setText = (text: string, source: Sources = "api") => { | 
        
        
           | 
                quill?.setText(text, source); | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const getHTML = (): string => { | 
        
        
           | 
                return quill?.root.innerHTML ?? ""; | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const setHTML = (html: string) => { | 
        
        
           | 
                if (quill) quill.root.innerHTML = html; | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const pasteHTML = (html: string, source: Sources = "api") => { | 
        
        
           | 
                const delta = quill?.clipboard.convert(html as {}); | 
        
        
           | 
                if (delta) quill?.setContents(delta, source); | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const focus = () => { | 
        
        
           | 
                quill?.focus(); | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              const reinit = () => { | 
        
        
           | 
                nextTick(() => { | 
        
        
           | 
                  if (!ctx.slots.toolbar && quill) | 
        
        
           | 
                    quill.getModule("toolbar")?.container.remove() | 
        
        
           | 
                  initialize(); | 
        
        
           | 
                }); | 
        
        
           | 
              }; | 
        
        
           | 
               | 
        
        
           | 
              watch( | 
        
        
           | 
                () => props.content, | 
        
        
           | 
                (newContent) => { | 
        
        
           | 
                  if (!quill || !newContent || internalModelEquals(newContent)) return; | 
        
        
           | 
               | 
        
        
           | 
                  // Restore the selection and cursor position after updating the content | 
        
        
           | 
                  const selection = quill.getSelection(); | 
        
        
           | 
                  if (selection) { | 
        
        
           | 
                    nextTick(() => quill?.setSelection(selection)); | 
        
        
           | 
                  } | 
        
        
           | 
                  setContents(newContent); | 
        
        
           | 
                }, | 
        
        
           | 
                { deep: true } | 
        
        
           | 
              ); | 
        
        
           | 
               | 
        
        
           | 
              watch( | 
        
        
           | 
                () => props.enable, | 
        
        
           | 
                (newValue) => { | 
        
        
           | 
                  if (quill) quill.enable(newValue); | 
        
        
           | 
                } | 
        
        
           | 
              ); | 
        
        
           | 
          
 | 
        
        
           | 
              return { | 
        
        
           | 
                editor, | 
        
        
           | 
                getEditor, | 
        
        
           | 
                getToolbar, | 
        
        
           | 
                getQuill, | 
        
        
           | 
                getContents, | 
        
        
           | 
                setContents, | 
        
        
           | 
                getHTML, | 
        
        
           | 
                setHTML, | 
        
        
           | 
                pasteHTML, | 
        
        
           | 
                focus, | 
        
        
           | 
                getText, | 
        
        
           | 
                setText, | 
        
        
           | 
                reinit, | 
        
        
           | 
              }; | 
        
        
           | 
          
 | 
        
        
           | 
          
 | 
        
        
           | 
            }, | 
        
        
           | 
          
 | 
        
        
           | 
            render() { | 
        
        
           | 
              return [ | 
        
        
           | 
                this.$slots.toolbar?.(), | 
        
        
           | 
                h('div', { ref: 'editor', ...this.$attrs}) | 
        
        
           | 
              ] | 
        
        
           | 
            }, | 
        
        
           | 
          }) | 
        
  
thanks Buddy!! you have made my day!!