{"version":3,"sources":["../wysiwyg4all.ts"],"sourcesContent":["type EditorFontSize = {\n\tdesktop?: number | string;\n\ttablet?: number | string;\n\tphone?: number | string;\n\th1?: number | string;\n\th2?: number | string;\n\th3?: number | string;\n\th4?: number | string;\n\th5?: number | string;\n\th6?: number | string;\n\tsmall?: number | string;\n};\n\ntype ColorScheme = Record<string, string>;\n\ntype BuiltInCommand =\n\t| \"quote\"\n\t| \"unorderedList\"\n\t| \"orderedList\"\n\t| \"divider\"\n\t| \"image\"\n\t| \"alignLeft\"\n\t| \"alignCenter\"\n\t| \"alignRight\"\n\t| \"h1\"\n\t| \"h2\"\n\t| \"h3\"\n\t| \"h4\"\n\t| \"h5\"\n\t| \"h6\"\n\t| \"small\"\n\t| \"bold\"\n\t| \"italic\"\n\t| \"underline\"\n\t| \"strike\"\n\t| \"color\";\n\ntype InlineClassCommand =\n\t| \"h1\"\n\t| \"h2\"\n\t| \"h3\"\n\t| \"h4\"\n\t| \"h5\"\n\t| \"h6\"\n\t| \"small\"\n\t| \"bold\"\n\t| \"italic\"\n\t| \"underline\"\n\t| \"strike\"\n\t| \"color\"\n\t| \"backgroundColor\";\n\ntype AlignCommand = \"alignLeft\" | \"alignCenter\" | \"alignRight\";\n\ntype CommandObject = {\n\telement?: HTMLElement | string;\n\telementId?: string;\n\tstyle?: Partial<CSSStyleDeclaration> & Record<string, string>;\n\tinsert?: boolean;\n\tbackgroundColor?: string;\n\tcolor?: string;\n};\n\ntype CommandInput = BuiltInCommand | CommandObject | string;\n\ntype CommandTracker = {\n\t\"unorderedList\": boolean;\n\t\"orderedList\": boolean;\n\t\"alignLeft\": boolean;\n\t\"alignCenter\": boolean;\n\t\"alignRight\": boolean;\n\t\"h1\": boolean;\n\t\"h2\": boolean;\n\t\"h3\": boolean;\n\t\"h4\": boolean;\n\t\"h5\": boolean;\n\t\"h6\": boolean;\n\t\"small\": boolean;\n\t\"bold\": boolean;\n\t\"italic\": boolean;\n\t\"underline\": boolean;\n\t\"strike\": boolean;\n\t\"color\": string;\n\t\"backgroundColor\": string;\n};\n\ntype ImageData = {\n\telementId: string;\n\tsource: string;\n\tfilename?: string;\n\tfileType?: string;\n\tfileSize?: number;\n\tlastModified?: number;\n\tdimension?: { width: number; height: number };\n\telement?: HTMLImageElement;\n\tclass?: string[];\n\tstyle?: Record<string, string>;\n\tonclick?: (ev: MouseEvent) => void;\n};\n\ntype HashtagData = {\n\telementId: string;\n\ttag: string;\n\telement?: HTMLSpanElement;\n\tstyle?: Record<string, string>;\n\tonclick?: (ev: MouseEvent) => void;\n};\n\ntype UrlData = {\n\telementId: string;\n\turl: string;\n\telement?: HTMLSpanElement;\n\tstyle?: Record<string, string>;\n\tonclick?: (ev: MouseEvent) => void;\n};\n\ntype CustomData = {\n\telementId: string;\n\telement: HTMLElement;\n};\n\ntype CallbackPayload = {\n\tcommandTracker?: CommandTracker;\n\trange?: Range | null;\n\tcaratPosition?: DOMRect | null;\n\tloading?: boolean;\n\timage?: ImageData[];\n\thashtag?: HashtagData[];\n\turllink?: UrlData[];\n};\n\ntype ExportPayload = {\n\thtml: string;\n\ttitle: string;\n\ttext: string;\n\turllink?: UrlData[];\n\thashtag?: HashtagData[];\n\timage: ImageData[];\n\tcustom: CustomData[];\n};\n\ntype ExtensionApi = {\n\tregisterCommand: (name: string, handler: (editor: Wysiwyg4All, action: CommandInput) => void | Promise<void>) => void;\n\ton: (eventName: string, handler: (...args: unknown[]) => void) => () => void;\n\teditor: Wysiwyg4All;\n};\n\ntype ExtensionFactory = (api: ExtensionApi) => void;\n\ntype ExportSetup = {\n\tdom: HTMLElement;\n\turllink?: UrlData[];\n\thashtag?: HashtagData[];\n\timage: ImageData[];\n\tcustom: CustomData[];\n\ttitle?: string;\n};\n\nexport type Wysiwyg4AllOptions = {\n\telementId: string;\n\teditable?: boolean;\n\tplaceholder?: string;\n\tspellcheck?: boolean;\n\thighlightColor?: string | ColorScheme;\n\thtml?: string;\n\tcallback?: (payload: CallbackPayload) => CallbackPayload | Promise<CallbackPayload>;\n\tfontSize?: EditorFontSize | number;\n\t// lastLineBlank?: boolean;\n\thashtag?: boolean;\n\turllink?: boolean;\n\textensions?: ExtensionFactory[];\n};\n\nconst CLASS_BY_COMMAND: Record<InlineClassCommand, string> = {\n\th1: \"_h1\",\n\th2: \"_h2\",\n\th3: \"_h3\",\n\th4: \"_h4\",\n\th5: \"_h5\",\n\th6: \"_h6\",\n\tsmall: \"_small\",\n\tbold: \"_b\",\n\titalic: \"_i\",\n\tunderline: \"_u\",\n\tstrike: \"_del\",\n\tcolor: \"_color\",\n\tbackgroundColor: \"_backgroundColor\",\n};\n\nconst COUNTER_CLASSES: Partial<Record<InlineClassCommand, string[]>> = {\n\th1: [\"_small\", \"_h2\", \"_h3\", \"_h4\", \"_h5\", \"_h6\"],\n\th2: [\"_small\", \"_h1\", \"_h3\", \"_h4\", \"_h5\", \"_h6\"],\n\th3: [\"_small\", \"_h1\", \"_h2\", \"_h4\", \"_h5\", \"_h6\"],\n\th4: [\"_small\", \"_h1\", \"_h2\", \"_h3\", \"_h5\", \"_h6\"],\n\th5: [\"_small\", \"_h1\", \"_h2\", \"_h3\", \"_h4\", \"_h6\"],\n\th6: [\"_small\", \"_h1\", \"_h2\", \"_h3\", \"_h4\", \"_h5\"],\n\tsmall: [\"_h1\", \"_h2\", \"_h3\", \"_h4\", \"_h5\", \"_h6\", \"_b\"],\n\tbold: [\"_small\"],\n\tunderline: [\"_del\"],\n\tstrike: [\"_u\"],\n};\n\nconst ALIGN_CLASSES = [\"_alignCenter_\", \"_alignRight_\"];\n\nconst FONT_SIZE_CLASSES = [\"_h1\", \"_h2\", \"_h3\", \"_h4\", \"_h5\", \"_h6\", \"_small\"] as const;\nconst FONT_SIZE_CLASS_SET = new Set<string>(FONT_SIZE_CLASSES);\n\nconst BLOCK_TAGS = new Set([\"P\", \"LI\", \"BLOCKQUOTE\", \"UL\", \"OL\", \"HR\", \"DIV\"]);\n\n// Tokenize only after the user types a breakout whitespace.\nconst HASHTAG_REGEX = /(^|\\s)(#[\\p{L}\\p{N}_-]{1,80})(?=\\s)/gu;\nconst URL_REGEX = /(https?:\\/\\/[^\\s]+|www\\.[^\\s]+)(?=\\s)/gi;\n\nfunction clampNumber(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nfunction toPx(value: number | string | undefined, fallback: string): string {\n\tif (typeof value === \"number\") return `${value}px`;\n\tif (typeof value === \"string\" && value.trim()) return value;\n\treturn fallback;\n}\n\nfunction isHTMLElement(value: unknown): value is HTMLElement {\n\treturn value instanceof HTMLElement;\n}\n\nfunction isNode(value: unknown): value is Node {\n\treturn value instanceof Node;\n}\n\nfunction createUid(prefix: string): string {\n\tconst rand = Math.random().toString(36).slice(2, 8);\n\tconst ts = Date.now().toString().slice(-6);\n\treturn `${prefix}_${ts}${rand}`;\n}\n\nfunction tryNormalizeColor(input: string): string | null {\n\tconst test = document.createElement(\"span\");\n\ttest.style.color = \"\";\n\ttest.style.color = input;\n\tif (!test.style.color) return null;\n\tdocument.body.appendChild(test);\n\tconst computed = getComputedStyle(test).color;\n\ttest.remove();\n\tconst match = computed.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/i);\n\tif (!match) return null;\n\tconst [, r, g, b] = match;\n\tconst hex = [r, g, b]\n\t\t.map((v) => clampNumber(Number(v), 0, 255).toString(16).padStart(2, \"0\"))\n\t\t.join(\"\");\n\treturn `#${hex}`;\n}\n\nfunction buildDefaultScheme(highlightColor: string): ColorScheme {\n\tconst focus = tryNormalizeColor(highlightColor) || \"#0d9488\";\n\treturn {\n\t\t\"--content\": \"#ffffff\",\n\t\t\"--content-text\": \"#111827\",\n\t\t\"--content-focus\": focus,\n\t\t\"--focus\": `${focus}33`,\n\t\t\"--placeholder\": \"#9ca3af\",\n\t};\n}\n\nexport class Wysiwyg4All {\n\tprivate readonly option: Wysiwyg4AllOptions;\n\tprivate readonly element: HTMLElement;\n\tprivate readonly styleTagOfCommand: Record<InlineClassCommand, string>;\n\tprivate readonly customCommandHandlers = new Map<string, (editor: Wysiwyg4All, action: CommandInput) => void | Promise<void>>();\n\tprivate readonly eventBus = new Map<string, Set<(...args: unknown[]) => void>>();\n\tprivate readonly imageInput: HTMLInputElement;\n\tprivate observer: MutationObserver | null = null;\n\tprivate range: Range | null = null;\n\tprivate rangeBackup: Range | null = null;\n\tprivate callback: Wysiwyg4AllOptions[\"callback\"];\n\tprivate readonly hashtagEnabled: boolean;\n\tprivate readonly urlEnabled: boolean;\n\tprivate lastKey: string | null = null;\n\tprivate suspendSelectionCaptureForColorPicker = false;\n\tprivate colorCommandDebounceTimer: number | null = null;\n\tprivate pendingColorCommand: { color?: string; backgroundColor?: string } | null = null;\n\tprivate pendingColorSelectionSnapshot: { start: number; end: number } | null = null;\n\tprivate trackerUpdateInFlight = false;\n\tprivate trackerUpdateQueued = false;\n\tprivate livePickerColor: string | null = null;\n\tprivate livePickerBackgroundColor: string | null = null;\n\tprivate colorPickerInteractionUntil = 0;\n\n\tpublic highlightColor: string;\n\tpublic defaultFontColor = \"#111827\";\n\tpublic defaultBackgroundColor = \"#ffffff\";\n\tpublic image_array: ImageData[] = [];\n\tpublic hashtag_array: HashtagData[] = [];\n\tpublic urllink_array: UrlData[] = [];\n\tpublic custom_array: CustomData[] = [];\n\tpublic commandTracker: CommandTracker = {} as CommandTracker;\n\t// public lastLineBlank: boolean;\n\n\tconstructor(option: Wysiwyg4AllOptions) {\n\t\tif (!option || typeof option !== \"object\") {\n\t\t\tthrow new Error(\"Wysiwyg4All option is required\");\n\t\t}\n\t\tif (!option.elementId || typeof option.elementId !== \"string\") {\n\t\t\tthrow new Error(\"The wysiwyg element should have an ID\");\n\t\t}\n\n\t\tconst elementId = option.elementId.startsWith(\"#\")\n\t\t\t? option.elementId.slice(1)\n\t\t\t: option.elementId;\n\t\tconst element = document.getElementById(elementId);\n\t\tif (!element) {\n\t\t\tthrow new Error(`element #${elementId} is null`);\n\t\t}\n\n\t\tthis.option = { ...option, elementId };\n\t\tthis.element = element;\n\t\tthis.callback = option.callback;\n\t\tthis.hashtagEnabled = !!option.hashtag;\n\t\tthis.urlEnabled = !!option.urllink;\n\n\t\tthis.styleTagOfCommand = { ...CLASS_BY_COMMAND };\n\t\tthis.highlightColor = tryNormalizeColor(\n\t\t\ttypeof option.highlightColor === \"string\" ? option.highlightColor : \"#0d9488\"\n\t\t) || \"#0d9488\";\n\n\t\tthis.applyTheme(option.highlightColor);\n\t\tthis.applyFontSize(option.fontSize);\n\n\t\tthis.element.classList.add(\"_wysiwyg4all\");\n\t\tthis.element.innerHTML = \"\";\n\t\tthis.setPlaceholder(option.placeholder || \"\");\n\t\tthis.setSpellcheck(!!option.spellcheck);\n\n\t\tthis.imageInput = document.createElement(\"input\");\n\t\tthis.imageInput.type = \"file\";\n\t\tthis.imageInput.accept = \"image/gif,image/png,image/jpeg,image/webp\";\n\t\tthis.imageInput.multiple = true;\n\t\tthis.imageInput.hidden = true;\n\t\tthis.imageInput.addEventListener(\"change\", (ev) => {\n\t\t\tvoid this.onImageSelected(ev).catch((err) => console.error(err));\n\t\t});\n\n\t\tthis.initializeCommandTracker();\n\t\tthis.bindCoreEvents();\n\t\tthis.bootstrapExtensions(option.extensions || []);\n\n\t\tqueueMicrotask(() => {\n\t\t\tvoid this.loadHTML(option.html || \"\", option.editable ?? true).catch((err) => {\n\t\t\t\tconsole.error(err);\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate initializeCommandTracker(): void {\n\t\tconst baseKeys = [\n\t\t\t\"quote\",\n\t\t\t\"unorderedList\",\n\t\t\t\"orderedList\",\n\t\t\t\"alignLeft\",\n\t\t\t\"alignCenter\",\n\t\t\t\"alignRight\",\n\t\t\t...Object.keys(this.styleTagOfCommand),\n\t\t];\n\t\tfor (const key of baseKeys) {\n\t\t\tthis.commandTracker[key] = false;\n\t\t}\n\t}\n\n\tprivate applyTheme(highlightColor?: string | ColorScheme): void {\n\t\tconst scheme: ColorScheme =\n\t\t\ttypeof highlightColor === \"object\" && highlightColor\n\t\t\t\t? highlightColor\n\t\t\t\t: buildDefaultScheme(typeof highlightColor === \"string\" ? highlightColor : \"#0d9488\");\n\t\tfor (const [key, value] of Object.entries(scheme)) {\n\t\t\tthis.element.style.setProperty(key, value);\n\t\t}\n\t\tconst computed = getComputedStyle(this.element);\n\t\tconst contentText = computed.getPropertyValue(\"--content-text\").trim();\n\t\tconst contentBg = computed.getPropertyValue(\"--content\").trim();\n\t\tconst contentFocus = computed.getPropertyValue(\"--content-focus\").trim();\n\t\tthis.defaultFontColor = tryNormalizeColor(contentText) || \"#111827\";\n\t\tthis.defaultBackgroundColor = tryNormalizeColor(contentBg) || \"#ffffff\";\n\t\tthis.highlightColor = tryNormalizeColor(contentFocus) || this.highlightColor;\n\t}\n\n\tprivate applyFontSize(fontSize?: EditorFontSize | number): void {\n\t\tconst fs =\n\t\t\ttypeof fontSize === \"number\"\n\t\t\t\t? { desktop: fontSize, tablet: fontSize, phone: fontSize }\n\t\t\t\t: fontSize || {};\n\n\t\tconst desktop = toPx(fs.desktop, \"18px\");\n\t\tconst tablet = toPx(fs.tablet ?? fs.desktop, desktop);\n\t\tconst phone = toPx(fs.phone ?? fs.tablet ?? fs.desktop, tablet);\n\t\tthis.element.style.setProperty(\"--wysiwyg-font-desktop\", desktop);\n\t\tthis.element.style.setProperty(\"--wysiwyg-font-tablet\", tablet);\n\t\tthis.element.style.setProperty(\"--wysiwyg-font-phone\", phone);\n\n\t\tconst ratioDefaults: Record<string, string | number> = {\n\t\t\th1: 4.2,\n\t\t\th2: 3.56,\n\t\t\th3: 2.92,\n\t\t\th4: 2.28,\n\t\t\th5: 1.64,\n\t\t\th6: 1.15,\n\t\t\tsmall: 0.8,\n\t\t};\n\n\t\tfor (const [tag, fallback] of Object.entries(ratioDefaults)) {\n\t\t\tconst raw = (fs as EditorFontSize)[tag as keyof EditorFontSize] ?? fallback;\n\t\t\tif (typeof raw === \"number\") {\n\t\t\t\tthis.element.style.setProperty(`--wysiwyg-${tag}`, `calc(var(--wysiwyg-font) * ${raw})`);\n\t\t\t} else {\n\t\t\t\tconst normalized = raw.trim();\n\t\t\t\tif (normalized.endsWith(\"px\")) {\n\t\t\t\t\tthis.element.style.setProperty(`--wysiwyg-${tag}`, normalized);\n\t\t\t\t} else {\n\t\t\t\t\tconst parsed = Number.parseFloat(normalized);\n\t\t\t\t\tif (Number.isFinite(parsed) && parsed > 0) {\n\t\t\t\t\t\tthis.element.style.setProperty(`--wysiwyg-${tag}`, `calc(var(--wysiwyg-font) * ${parsed})`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate bindCoreEvents(): void {\n\t\tdocument.addEventListener(\"selectionchange\", this.onSelectionChange);\n\t\tthis.element.addEventListener(\"keydown\", this.onKeyDown);\n\t\tthis.element.addEventListener(\"paste\", this.onPaste);\n\t\twindow.addEventListener(\"mousedown\", this.onWindowMouseDown);\n\t}\n\n\tprivate unbindCoreEvents(): void {\n\t\tdocument.removeEventListener(\"selectionchange\", this.onSelectionChange);\n\t\tthis.element.removeEventListener(\"keydown\", this.onKeyDown);\n\t\tthis.element.removeEventListener(\"paste\", this.onPaste);\n\t\twindow.removeEventListener(\"mousedown\", this.onWindowMouseDown);\n\t}\n\n\tprivate bootstrapExtensions(extensions: ExtensionFactory[]): void {\n\t\tconst api: ExtensionApi = {\n\t\t\tregisterCommand: (name, handler) => {\n\t\t\t\tthis.customCommandHandlers.set(name, handler);\n\t\t\t},\n\t\t\ton: (eventName, handler) => {\n\t\t\t\tif (!this.eventBus.has(eventName)) this.eventBus.set(eventName, new Set());\n\t\t\t\tthis.eventBus.get(eventName)?.add(handler);\n\t\t\t\treturn () => {\n\t\t\t\t\tthis.eventBus.get(eventName)?.delete(handler);\n\t\t\t\t};\n\t\t\t},\n\t\t\teditor: this,\n\t\t};\n\n\t\tfor (const createExtension of extensions) {\n\t\t\ttry {\n\t\t\t\tcreateExtension(api);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"extension bootstrap failed\", err);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate emit(eventName: string, ...args: unknown[]): void {\n\t\tconst handlers = this.eventBus.get(eventName);\n\t\tif (!handlers) return;\n\t\tfor (const handler of handlers) {\n\t\t\ttry {\n\t\t\t\thandler(...args);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(err);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onWindowMouseDown = (ev: MouseEvent): void => {\n\t\tif (isNode(ev.target) && this.isUnSelectableElement(ev.target)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst target = ev.target;\n\t\tif (target instanceof HTMLInputElement && target.type === \"color\") {\n\t\t\tconst sel = window.getSelection();\n\t\t\tif (sel && sel.rangeCount > 0 && this.element.contains(sel.anchorNode) && this.element.contains(sel.focusNode)) {\n\t\t\t\tconst normalized = this.normalizeEditorRange(sel.getRangeAt(0));\n\t\t\t\tif (normalized) {\n\t\t\t\t\tthis.range = normalized;\n\t\t\t\t\tthis.backupCurrentRange(normalized, { bypassNormalize: true });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst active = document.activeElement;\n\t\tconst colorPickerActive = active instanceof HTMLInputElement && active.type === \"color\";\n\t\tif (colorPickerActive && isNode(ev.target) && this.element.contains(ev.target)) {\n\t\t\t// Clicking inside editor to close color picker can collapse the live\n\t\t\t// selection before color command runs. Keep backup during picker interaction,\n\t\t\t// then re-capture once the picker closes so commands use the new caret.\n\t\t\tthis.suspendSelectionCaptureForColorPicker = true;\n\t\t\twindow.setTimeout(() => {\n\t\t\t\tconst nextActive = document.activeElement;\n\t\t\t\tconst stillOnColorInput = nextActive instanceof HTMLInputElement && nextActive.type === \"color\";\n\t\t\t\tif (stillOnColorInput) return;\n\t\t\t\tthis.suspendSelectionCaptureForColorPicker = false;\n\t\t\t\t// this.captureRange();\n\t\t\t\t// this.updateCommandTracker();\n\t\t\t}, 0);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.suspendSelectionCaptureForColorPicker = false;\n\t};\n\n\tprivate onSelectionChange = (): void => {\n\t\tif (this.suspendSelectionCaptureForColorPicker) {\n\t\t\tconst active = document.activeElement;\n\t\t\tif (!(active instanceof HTMLInputElement && active.type === \"color\")) {\n\t\t\t\tthis.suspendSelectionCaptureForColorPicker = false;\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.captureRange();\n\t\tthis.updateCommandTracker();\n\t};\n\n\tprivate onKeyDown = (ev: KeyboardEvent): void => {\n\t\tthis.lastKey = ev.key.toUpperCase();\n\t\tthis.captureRange();\n\n\t\tif (!this.range) return;\n\n\t\tif ([\"BACKSPACE\", \"DELETE\"].includes(this.lastKey)) {\n\t\t\tif (!this.element.textContent?.trim() && this.element.childNodes.length <= 1) {\n\t\t\t\tev.preventDefault();\n\t\t\t\tthis.ensureRootHasSafeLine();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.handleDeleteFromTrailingEmptyLine()) {\n\t\t\t\tev.preventDefault();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (this.lastKey === \"TAB\") {\n\t\t\tev.preventDefault();\n\t\t\tthis.insertText(\"\\t\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.lastKey === \"ENTER\") {\n\t\t\tif (this.handleEnterFromQuoteTail()) {\n\t\t\t\tev.preventDefault();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tqueueMicrotask(() => this.ensureRootHasSafeLine());\n\t\t}\n\n\t\twindow.setTimeout(() => {\n\t\t\tthis.normalizeDocument();\n\t\t\tvoid this.scanSpecialTokens();\n\t\t}, 0);\n\t};\n\n\tprivate onPaste = (ev: ClipboardEvent): void => {\n\t\tev.preventDefault();\n\t\tconst text = ev.clipboardData?.getData(\"text/plain\") || \"\";\n\t\tthis.insertText(text.replace(/\\r\\n?/g, \"\\n\"));\n\t\tqueueMicrotask(() => {\n\t\t\tthis.normalizeDocument();\n\t\t\tvoid this.scanSpecialTokens();\n\t\t});\n\t};\n\n\tprivate ensureRootHasSafeLine(): void {\n\t\tif (this.element.childNodes.length === 0) {\n\t\t\tthis.element.append(this.createEmptyParagraph());\n\t\t\treturn;\n\t\t}\n\t\tif (this.element.childNodes.length === 1) {\n\t\t\tconst first = this.element.firstChild;\n\t\t\tif (first && first.nodeType === Node.TEXT_NODE && !first.textContent) {\n\t\t\t\tfirst.remove();\n\t\t\t\tthis.element.append(this.createEmptyParagraph());\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate createEmptyParagraph(seed?: string): HTMLParagraphElement {\n\t\tconst p = document.createElement(\"p\");\n\t\tif (seed && seed.length) p.append(document.createTextNode(seed));\n\t\telse p.append(document.createElement(\"br\"));\n\t\treturn p;\n\t}\n\n\tprivate setSelectionAtStart(node: Node): void {\n\t\tconst range = document.createRange();\n\t\trange.selectNodeContents(node);\n\t\trange.collapse(true);\n\t\tthis.restoreLastSelection(range);\n\t}\n\n\tprivate isLineVisuallyEmpty(line: HTMLElement): boolean {\n\t\tif (!this.isLineBlockElement(line)) return false;\n\t\tif (line.querySelector(\"img,video,audio,table,hr,._media_,._custom_\")) return false;\n\t\tconst text = (line.textContent || \"\").split(\"\\u200B\").join(\"\").trim();\n\t\treturn text.length === 0;\n\t}\n\n\tprivate isNonTextElement(el: HTMLElement): boolean {\n\t\tif (el.classList.contains(\"_media_\") || el.classList.contains(\"_custom_\")) return true;\n\t\treturn [\"HR\", \"BLOCKQUOTE\", \"UL\", \"OL\", \"TABLE\"].includes(el.tagName);\n\t}\n\n\tprivate getContainingQuote(node: Node): HTMLElement | null {\n\t\tconst el = node.nodeType === Node.TEXT_NODE ? node.parentElement : (node as Element | null);\n\t\tif (!el) return null;\n\t\tconst quote = el.closest(\"blockquote\");\n\t\treturn quote instanceof HTMLElement ? quote : null;\n\t}\n\n\tprivate unwrapQuote(quote: HTMLElement): void {\n\t\tconst parent = quote.parentNode;\n\t\tif (!parent) return;\n\n\t\tconst firstChild = quote.firstChild;\n\t\twhile (quote.firstChild) {\n\t\t\tparent.insertBefore(quote.firstChild, quote);\n\t\t}\n\t\tquote.remove();\n\n\t\tif (firstChild) {\n\t\t\tconst target = firstChild.nodeType === Node.TEXT_NODE ? firstChild.parentNode : firstChild;\n\t\t\tif (target) this.setSelectionAtStart(target as Node);\n\t\t}\n\n\t\tthis.ensureRootHasSafeLine();\n\t}\n\n\tprivate getQuoteLineBlocks(quote: HTMLElement): HTMLElement[] {\n\t\treturn Array.from(quote.querySelectorAll<HTMLElement>(\"p,li,td,th,tr\"));\n\t}\n\n\tprivate handleEnterFromQuoteTail(): boolean {\n\t\tif (!this.range || !this.range.collapsed) return false;\n\n\t\tconst quote = this.getContainingQuote(this.range.startContainer);\n\t\tif (!quote) return false;\n\n\t\tconst currentLine = this.getContainingLineBlock(this.range.startContainer);\n\t\tif (!currentLine || !quote.contains(currentLine)) return false;\n\t\tif (!this.isLineVisuallyEmpty(currentLine)) return false;\n\n\t\tconst lines = this.getQuoteLineBlocks(quote);\n\t\tif (lines.length === 0 || lines[lines.length - 1] !== currentLine) return false;\n\n\t\tcurrentLine.remove();\n\n\t\tconst remainingLines = this.getQuoteLineBlocks(quote);\n\t\tif (remainingLines.length === 0 && !(quote.textContent || \"\").trim()) {\n\t\t\tquote.remove();\n\t\t\tthis.ensureRootHasSafeLine();\n\t\t\tthis.setSelectionAtStart(this.element.lastElementChild || this.element);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst targetLine = this.ensureTrailingEditableLineAfter(quote);\n\t\tthis.setSelectionAtStart(targetLine);\n\t\treturn true;\n\t}\n\n\tprivate handleDeleteFromTrailingEmptyLine(): boolean {\n\t\tif (!this.range || !this.range.collapsed) return false;\n\n\t\tconst line = this.getContainingLineBlock(this.range.startContainer);\n\t\tif (!line) return false;\n\t\tif (line !== this.element.lastElementChild) return false;\n\t\tif (!this.isLineVisuallyEmpty(line)) return false;\n\n\t\tconst prev = line.previousElementSibling as HTMLElement | null;\n\t\tif (!prev || !this.isNonTextElement(prev)) return false;\n\n\t\tprev.remove();\n\t\tif (!line.isConnected) {\n\t\t\tthis.element.append(this.createEmptyParagraph());\n\t\t\tthis.setSelectionAtStart(this.element.lastElementChild as Node);\n\t\t\treturn true;\n\t\t}\n\n\t\tthis.setSelectionAtStart(line);\n\t\treturn true;\n\t}\n\n\tprivate captureRange(): void {\n\t\tconst sel = window.getSelection();\n\n\t\t// check if sel is within our editor\n\t\tif (!sel || !this.element.contains(sel.anchorNode)) {\n\t\t\t// this.range = null;\n\t\t\treturn;\n\t\t}\n\n\t\tif (!sel || sel.rangeCount === 0) {\n\t\t\tthis.range = null;\n\t\t\treturn;\n\t\t}\n\t\tconst normalizedRange = this.normalizeEditorRange(sel.getRangeAt(0));\n\t\tlet normalized = normalizedRange;\n\t\tif (!normalized) {\n\t\t\tthis.range = null;\n\t\t\treturn;\n\t\t}\n\n\t\tconst reanchored = this.reanchorCollapsedRangeToAdjacentStylePlaceholder(normalized);\n\t\tif (reanchored) {\n\t\t\tnormalized = reanchored;\n\t\t\tif (\n\t\t\t\tnormalizedRange &&\n\t\t\t\t(\n\t\t\t\t\tnormalized.startContainer !== normalizedRange.startContainer ||\n\t\t\t\t\tnormalized.startOffset !== normalizedRange.startOffset\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tsel.removeAllRanges();\n\t\t\t\tsel.addRange(normalized);\n\t\t\t}\n\t\t}\n\t\tthis.range = normalized;\n\t\tthis.backupCurrentRange(normalized, { bypassNormalize: true });\n\t}\n\n\tprivate isCollapsedStyleAnchorSpan(el: HTMLElement): boolean {\n\t\tif (el.tagName !== \"SPAN\") return false;\n\t\tif (this.isProtectedSpan(el)) return false;\n\t\tif (!this.isTextStyleWrapper(el, this.getKnownInlineStyleClassSet())) return false;\n\t\tif (el.querySelector(\"br,hr,img,video,audio,table,ul,ol,li,blockquote,div,._media_,._custom_\")) return false;\n\t\tconst textWithoutMarker = (el.textContent || \"\").split(\"\\u200B\").join(\"\").trim();\n\t\treturn textWithoutMarker.length === 0;\n\t}\n\n\tprivate reanchorCollapsedRangeToAdjacentStylePlaceholder(range: Range): Range | null {\n\t\tif (!range.collapsed) return null;\n\n\t\tconst buildRangeInsidePlaceholder = (node: Node | null): Range | null => {\n\t\t\tif (!(node instanceof HTMLElement)) return null;\n\t\t\tif (!this.isCollapsedStyleAnchorSpan(node)) return null;\n\t\t\tconst firstChild = node.firstChild;\n\t\t\tconst anchor: Text = firstChild instanceof Text\n\t\t\t\t? firstChild\n\t\t\t\t: document.createTextNode(\"\\u200B\");\n\t\t\tif (!(firstChild instanceof Text)) node.append(anchor);\n\t\t\tconst next = document.createRange();\n\t\t\tnext.setStart(anchor, anchor.length);\n\t\t\tnext.collapse(true);\n\t\t\treturn next;\n\t\t};\n\n\t\tconst tryFromContainer = (container: Node, offset: number): Range | null => {\n\t\t\tif (!(container instanceof Element)) return null;\n\t\t\tconst before = offset > 0 ? container.childNodes[offset - 1] : null;\n\t\t\tconst after = offset < container.childNodes.length ? container.childNodes[offset] : null;\n\t\t\tconst candidates = [before, after];\n\n\t\t\tfor (const node of candidates) {\n\t\t\t\tconst next = buildRangeInsidePlaceholder(node);\n\t\t\t\tif (next) return next;\n\t\t\t}\n\n\t\t\treturn null;\n\t\t};\n\n\t\tconst tryFromAncestorBoundary = (startNode: Node, preferNext: boolean): Range | null => {\n\t\t\tlet node: Node | null = startNode;\n\t\t\twhile (node && node !== this.element) {\n\t\t\t\tconst parent = node.parentNode;\n\t\t\t\tif (!parent || parent === this.element.parentNode) break;\n\t\t\t\tconst sibling = preferNext ? node.nextSibling : node.previousSibling;\n\t\t\t\tconst next = buildRangeInsidePlaceholder(sibling);\n\t\t\t\tif (next) return next;\n\t\t\t\tnode = parent;\n\t\t\t}\n\t\t\treturn null;\n\t\t};\n\n\t\tif (range.startContainer instanceof Element) {\n\t\t\tconst direct = tryFromContainer(range.startContainer, range.startOffset);\n\t\t\tif (direct) return direct;\n\t\t\tif (range.startOffset >= range.startContainer.childNodes.length) {\n\t\t\t\treturn tryFromAncestorBoundary(range.startContainer, true);\n\t\t\t}\n\t\t\tif (range.startOffset === 0) {\n\t\t\t\treturn tryFromAncestorBoundary(range.startContainer, false);\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\tconst textNode = range.startContainer;\n\t\tconst parent = textNode.parentElement;\n\t\tif (!parent) return null;\n\t\tconst siblings: Node[] = Array.from(parent.childNodes);\n\t\tconst idx = siblings.indexOf(textNode);\n\t\tif (idx < 0) return null;\n\n\t\tconst preferOffset = idx + (range.startOffset > 0 ? 1 : 0);\n\t\tconst direct = tryFromContainer(parent, preferOffset);\n\t\tif (direct) return direct;\n\n\t\tif (textNode instanceof Text) {\n\t\t\tif (range.startOffset >= textNode.length) {\n\t\t\t\treturn tryFromAncestorBoundary(parent, true);\n\t\t\t}\n\t\t\tif (range.startOffset === 0) {\n\t\t\t\treturn tryFromAncestorBoundary(parent, false);\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate backupCurrentRange(\n\t\tsource?: Selection | Range | null,\n\t\tparams?: { bypassNormalize?: boolean }\n\t): Range | null {\n\t\tconst bypassNormalize = params?.bypassNormalize ?? false;\n\t\tlet candidate: Range | null = null;\n\n\t\tif (source instanceof Range) {\n\t\t\tcandidate = source.cloneRange();\n\t\t} else {\n\t\t\tconst sel = source ?? window.getSelection();\n\t\t\tif (!sel || sel.rangeCount === 0) return null;\n\t\t\tif (!this.element.contains(sel.anchorNode)) return null;\n\t\t\tcandidate = sel.getRangeAt(0).cloneRange();\n\t\t}\n\n\t\tconst rangeBackup = bypassNormalize ? candidate : this.normalizeEditorRange(candidate);\n\t\tif (!rangeBackup) return null;\n\t\tthis.rangeBackup = rangeBackup.cloneRange();\n\t\treturn this.rangeBackup;\n\t}\n\n\tprivate getTextOffsetWithinEditor(container: Node, offset: number): number | null {\n\t\tif (container !== this.element && !this.element.contains(container)) return null;\n\n\t\tconst probe = document.createRange();\n\t\ttry {\n\t\t\tprobe.setStart(this.element, 0);\n\t\t\tprobe.setEnd(container, offset);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn probe.toString().length;\n\t}\n\n\tprivate resolveBoundaryFromTextOffset(charOffset: number): { container: Node; offset: number } | null {\n\t\tlet remaining = Math.max(0, charOffset);\n\t\tconst walker = document.createTreeWalker(this.element, NodeFilter.SHOW_TEXT);\n\t\tlet lastText: Text | null = null;\n\n\t\twhile (walker.nextNode()) {\n\t\t\tconst textNode = walker.currentNode as Text;\n\t\t\tconst len = textNode.length;\n\t\t\tlastText = textNode;\n\n\t\t\tif (remaining <= len) {\n\t\t\t\treturn { container: textNode, offset: remaining };\n\t\t\t}\n\n\t\t\tremaining -= len;\n\t\t}\n\n\t\tif (lastText) {\n\t\t\treturn { container: lastText, offset: lastText.length };\n\t\t}\n\n\t\tconst last = this.element.lastChild;\n\t\tif (!last) return null;\n\t\treturn this.getDeepBoundaryPoint(last, false);\n\t}\n\n\tprivate snapshotRangeToTextOffsets(range: Range): { start: number; end: number } | null {\n\t\tconst normalized = this.normalizeEditorRange(range);\n\t\tif (!normalized) return null;\n\n\t\tconst start = this.getTextOffsetWithinEditor(normalized.startContainer, normalized.startOffset);\n\t\tconst end = this.getTextOffsetWithinEditor(normalized.endContainer, normalized.endOffset);\n\t\tif (start === null || end === null) return null;\n\n\t\treturn { start, end };\n\t}\n\n\tprivate restoreRangeFromTextOffsets(snapshot: { start: number; end: number }): Range | null {\n\t\tconst start = this.resolveBoundaryFromTextOffset(snapshot.start);\n\t\tconst end = this.resolveBoundaryFromTextOffset(snapshot.end);\n\t\tif (!start || !end) return null;\n\n\t\tconst range = document.createRange();\n\t\ttry {\n\t\t\trange.setStart(start.container, start.offset);\n\t\t\trange.setEnd(end.container, end.offset);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn this.normalizeEditorRange(range);\n\t}\n\n\tprivate getDeepBoundaryPoint(node: Node, atStart: boolean): { container: Node; offset: number } {\n\t\tlet current = node;\n\t\twhile (current.nodeType !== Node.TEXT_NODE && current.childNodes.length > 0) {\n\t\t\tcurrent = atStart ? current.firstChild as Node : current.lastChild as Node;\n\t\t}\n\n\t\tif (current.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = current as Text;\n\t\t\treturn { container: text, offset: atStart ? 0 : text.length };\n\t\t}\n\n\t\treturn { container: current, offset: atStart ? 0 : current.childNodes.length };\n\t}\n\n\tprivate resolveRangeBoundaryPoint(\n\t\tcontainer: Node,\n\t\toffset: number,\n\t\tatStart: boolean\n\t): { container: Node; offset: number } | null {\n\t\tif (container === this.element) {\n\t\t\tconst { childNodes } = this.element;\n\t\t\tif (childNodes.length === 0) return null;\n\n\t\t\tif (atStart) {\n\t\t\t\tconst target = offset < childNodes.length ? childNodes[offset] : childNodes[childNodes.length - 1];\n\t\t\t\treturn this.getDeepBoundaryPoint(target, offset < childNodes.length);\n\t\t\t}\n\n\t\t\tconst target = offset > 0 ? childNodes[offset - 1] : childNodes[0];\n\t\t\treturn this.getDeepBoundaryPoint(target, offset === 0);\n\t\t}\n\n\t\tif (!this.element.contains(container)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn { container, offset };\n\t}\n\n\tprivate normalizeEditorRange(range: Range): Range | null {\n\t\tif (range.collapsed) {\n\t\t\tconst point = this.resolveRangeBoundaryPoint(range.startContainer, range.startOffset, true);\n\t\t\tif (!point) return null;\n\n\t\t\tconst normalizedCollapsed = range.cloneRange();\n\t\t\ttry {\n\t\t\t\tnormalizedCollapsed.setStart(point.container, point.offset);\n\t\t\t\tnormalizedCollapsed.setEnd(point.container, point.offset);\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn normalizedCollapsed;\n\t\t}\n\n\t\tconst start = this.resolveRangeBoundaryPoint(range.startContainer, range.startOffset, true);\n\t\tconst end = this.resolveRangeBoundaryPoint(range.endContainer, range.endOffset, false);\n\t\tif (!start || !end) return null;\n\n\t\tconst normalized = range.cloneRange();\n\t\ttry {\n\t\t\tnormalized.setStart(start.container, start.offset);\n\t\t\tnormalized.setEnd(end.container, end.offset);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn normalized;\n\t}\n\n\tprivate restoreLastSelection(range: Range | null = this.rangeBackup): void {\n\t\tif (!range) return;\n\t\tconst normalized = this.normalizeEditorRange(range);\n\t\tif (!normalized) return;\n\t\tconst sel = window.getSelection();\n\t\tif (!sel) return;\n\n\t\tthis.range = normalized;\n\t\tsel.removeAllRanges();\n\t\tsel.addRange(normalized);\n\t}\n\n\tpublic setPlaceholder(placeholder: string): void {\n\t\tif (placeholder && placeholder.trim()) {\n\t\t\tthis.element.setAttribute(\"placeholder\", placeholder);\n\t\t} else {\n\t\t\tthis.element.removeAttribute(\"placeholder\");\n\t\t}\n\t\tthis.updatePlaceholderVisibility();\n\t}\n\n\tpublic setSpellcheck(enabled: boolean): void {\n\t\tthis.element.setAttribute(\"spellcheck\", enabled ? \"true\" : \"false\");\n\t}\n\n\tpublic setEditable(enabled: boolean): void {\n\t\tthis.element.setAttribute(\"contenteditable\", enabled ? \"true\" : \"false\");\n\t\tthis.observeMutation(enabled);\n\t\tthis.updatePlaceholderVisibility();\n\t}\n\n\tprivate isEditorInPlaceholderState(): boolean {\n\t\tif (this.element.childNodes.length === 0) return true;\n\t\tif (this.element.childNodes.length !== 1) return false;\n\n\t\tconst only = this.element.firstChild;\n\t\tif (!only) return true;\n\t\tif (only.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = (only.textContent || \"\").split(\"\\u200B\").join(\"\").trim();\n\t\t\treturn text.length === 0;\n\t\t}\n\n\t\tif (!(only instanceof HTMLElement)) return false;\n\t\tif (only.tagName === \"BR\") return true;\n\t\tif (only.tagName === \"P\") return this.isLineVisuallyEmpty(only);\n\t\treturn false;\n\t}\n\n\tprivate updatePlaceholderVisibility(): void {\n\t\tconst hasPlaceholder = !!this.element.getAttribute(\"placeholder\")?.trim();\n\t\tconst editable = this.element.getAttribute(\"contenteditable\") === \"true\";\n\t\tconst shouldShow = hasPlaceholder && editable && this.isEditorInPlaceholderState();\n\t\tthis.element.classList.toggle(\"_placeholderVisible\", shouldShow);\n\t}\n\n\tpublic destroy(): void {\n\t\tthis.unbindCoreEvents();\n\t\tthis.observeMutation(false);\n\t\tif (this.colorCommandDebounceTimer !== null) {\n\t\t\twindow.clearTimeout(this.colorCommandDebounceTimer);\n\t\t\tthis.colorCommandDebounceTimer = null;\n\t\t}\n\t\tthis.imageInput.remove();\n\t\tthis.eventBus.clear();\n\t\tthis.customCommandHandlers.clear();\n\t}\n\n\tprivate observeMutation(track: boolean): void {\n\t\tif (this.observer) {\n\t\t\tthis.observer.disconnect();\n\t\t\tthis.observer = null;\n\t\t}\n\t\tif (!track) return;\n\n\t\tthis.observer = new MutationObserver((mutations) => {\n\t\t\tfor (const mutation of mutations) {\n\t\t\t\tif (mutation.type !== \"childList\") continue;\n\t\t\t\tconst target = mutation.target;\n\t\t\t\tif (!(target instanceof HTMLElement)) continue;\n\n\t\t\t\tif (target === this.element && target.childNodes.length === 0) {\n\t\t\t\t\ttarget.append(this.createEmptyParagraph());\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tthis.isCeilingElement(target) &&\n\t\t\t\t\ttarget !== this.element &&\n\t\t\t\t\ttarget.childNodes.length === 0\n\t\t\t\t) {\n\t\t\t\t\ttarget.remove();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tthis.isTextBlockElement(target) &&\n\t\t\t\t\ttarget.childNodes.length === 1 &&\n\t\t\t\t\tthis.isUnSelectableElement(target.firstChild)\n\t\t\t\t) {\n\t\t\t\t\ttarget.append(document.createTextNode(\"\"));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.updatePlaceholderVisibility();\n\t\t});\n\n\t\tthis.observer.observe(this.element, {\n\t\t\tattributes: true,\n\t\t\tchildList: true,\n\t\t\tcharacterData: true,\n\t\t\tsubtree: true,\n\t\t});\n\t}\n\n\tprivate isUnSelectableElement(node: Node | null): boolean {\n\t\tconst el = node?.nodeType === Node.TEXT_NODE ? node.parentElement : (node as Element | null);\n\t\tif (!el) return false;\n\t\treturn !!el.closest(\"._media_, ._hashtag_, ._urllink_, hr\");\n\t}\n\n\tprivate isTextBlockElement(node: Node | null): boolean {\n\t\tconst el = node?.nodeType === Node.TEXT_NODE ? node.parentElement : (node as Element | null);\n\t\tif (!el) return false;\n\t\treturn [\"P\", \"LI\", \"TD\", \"TH\", \"TR\"].includes(el.tagName);\n\t}\n\n\tprivate isCeilingElement(node: Node | null): boolean {\n\t\tconst el = node?.nodeType === Node.TEXT_NODE ? node.parentElement : (node as Element | null);\n\t\tif (!el) return false;\n\t\tif (el === this.element) return true;\n\t\treturn [\"UL\", \"OL\", \"LI\", \"BLOCKQUOTE\"].includes(el.tagName);\n\t}\n\n\tprivate cleanupZeroWidthSpaces(): void {\n\t\tconst textNodes: Text[] = [];\n\t\tconst walker = document.createTreeWalker(this.element, NodeFilter.SHOW_TEXT, {\n\t\t\tacceptNode: (node) => {\n\t\t\t\tconst parent = node.parentElement;\n\t\t\t\tif (!parent) return NodeFilter.FILTER_REJECT;\n\t\t\t\tif (parent.closest(\"._media_, ._custom_\")) return NodeFilter.FILTER_REJECT;\n\t\t\t\treturn (node.textContent || \"\").includes(\"\\u200B\")\n\t\t\t\t\t? NodeFilter.FILTER_ACCEPT\n\t\t\t\t\t: NodeFilter.FILTER_REJECT;\n\t\t\t},\n\t\t});\n\n\t\twhile (walker.nextNode()) {\n\t\t\ttextNodes.push(walker.currentNode as Text);\n\t\t}\n\n\t\tfor (const textNode of textNodes) {\n\t\t\t// Use deleteData() so the browser Selection tracks the mutation\n\t\t\t// and keeps the caret at the correct position (textContent= assignment loses it).\n\t\t\tlet i = textNode.length - 1;\n\t\t\twhile (i >= 0) {\n\t\t\t\tif (textNode.data[i] === \"\\u200B\") {\n\t\t\t\t\ttextNode.deleteData(i, 1);\n\t\t\t\t}\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif (textNode.length === 0) {\n\t\t\t\ttextNode.remove();\n\t\t\t}\n\t\t}\n\n\t\tthis.element.normalize();\n\t}\n\n\tprivate normalizeDocument(): void {\n\t\tconst sel = window.getSelection();\n\t\tconst hasLiveSelectionInEditor = !!(\n\t\t\tsel &&\n\t\t\tsel.rangeCount > 0 &&\n\t\t\tthis.element.contains(sel.anchorNode) &&\n\t\t\tthis.element.contains(sel.focusNode)\n\t\t);\n\t\tconst rangeSource = hasLiveSelectionInEditor\n\t\t\t? (this.range ?? this.rangeBackup)\n\t\t\t: (this.range ?? this.rangeBackup);\n\t\tconst rangeSnapshot = rangeSource\n\t\t\t? this.snapshotRangeToTextOffsets(rangeSource)\n\t\t\t: null;\n\n\t\tthis.cleanupZeroWidthSpaces();\n\t\tconst toRemove: HTMLElement[] = [];\n\t\tconst walker = document.createTreeWalker(this.element, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);\n\t\twhile (walker.nextNode()) {\n\t\t\tconst node = walker.currentNode;\n\n\t\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\tconst el = node as HTMLElement;\n\t\t\t\tif (el.classList.contains(\"_static_\")) continue;\n\n\t\t\t\tif (\n\t\t\t\t\t!el.classList.contains(\"_media_\") &&\n\t\t\t\t\t!el.classList.contains(\"_custom_\") &&\n\t\t\t\t\t!el.closest(\"._media_\") &&\n\t\t\t\t\t!el.closest(\"._custom_\") &&\n\t\t\t\t\t!this.isCeilingElement(el) &&\n\t\t\t\t\t!el.textContent &&\n\t\t\t\t\tel.childNodes.length === 0 &&\n\t\t\t\t\tel.tagName !== \"BR\" &&\n\t\t\t\t\tel.tagName !== \"HR\"\n\t\t\t\t) {\n\t\t\t\t\ttoRemove.push(el);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const node of toRemove) node.remove();\n\t\tthis.redistributeInlineStylesAcrossBlocks();\n\t\tthis.cleanupNestedFontSizeWrappers();\n\t\tthis.cleanupRedundantTextWrappers();\n\t\tthis.cleanupEmptyTextStyleElements();\n\t\tthis.ensureRootHasSafeLine();\n\n\t\tif (hasLiveSelectionInEditor) {\n\t\t\t// For live in-editor selection, browser already tracks caret through DOM\n\t\t\t// mutations more accurately than text-offset mapping in empty blocks.\n\t\t\tthis.captureRange();\n\t\t\treturn;\n\t\t}\n\n\t\tif (rangeSnapshot) {\n\t\t\tconst rebased = this.restoreRangeFromTextOffsets(rangeSnapshot);\n\t\t\tif (rebased) {\n\t\t\t\tthis.range = rebased;\n\t\t\t\tthis.rangeBackup = rebased.cloneRange();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isLineBlockElement(el: HTMLElement): boolean {\n\t\treturn [\"P\", \"LI\", \"TD\", \"TH\", \"TR\"].includes(el.tagName);\n\t}\n\n\tprivate cloneInlineStyleSpan(span: HTMLElement): HTMLSpanElement {\n\t\tconst clone = document.createElement(\"span\");\n\t\tclone.className = span.className;\n\t\tif (span.style.cssText.trim()) {\n\t\t\tclone.style.cssText = span.style.cssText;\n\t\t}\n\t\treturn clone;\n\t}\n\n\tprivate getContainingLineBlock(node: Node): HTMLElement | null {\n\t\tlet current: Node | null = node.nodeType === Node.TEXT_NODE ? node.parentNode : node;\n\t\twhile (current && current !== this.element) {\n\t\t\tif (current instanceof HTMLElement && this.isLineBlockElement(current)) {\n\t\t\t\treturn current;\n\t\t\t}\n\t\t\tcurrent = current.parentNode;\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate getLineBlocksBetween(startLine: HTMLElement, endLine: HTMLElement): HTMLElement[] {\n\t\tconst blocks = Array.from(this.element.querySelectorAll<HTMLElement>(\"p,li,td,th,tr\"));\n\t\tconst startIndex = blocks.indexOf(startLine);\n\t\tconst endIndex = blocks.indexOf(endLine);\n\t\tif (startIndex < 0 || endIndex < 0) return [];\n\t\tconst from = Math.min(startIndex, endIndex);\n\t\tconst to = Math.max(startIndex, endIndex);\n\t\treturn blocks.slice(from, to + 1);\n\t}\n\n\tprivate doesRangeIntersectElement(range: Range, el: HTMLElement): boolean {\n\t\tconst nodeRange = document.createRange();\n\t\tnodeRange.selectNodeContents(el);\n\t\tconst endsBefore = range.compareBoundaryPoints(Range.END_TO_START, nodeRange) <= 0;\n\t\tconst startsAfter = range.compareBoundaryPoints(Range.START_TO_END, nodeRange) >= 0;\n\t\treturn !endsBefore && !startsAfter;\n\t}\n\n\tprivate getSelectedLineBlocks(range: Range): HTMLElement[] {\n\t\tconst blocks = Array.from(this.element.querySelectorAll<HTMLElement>(\"p,li,td,th,tr\"));\n\t\treturn blocks.filter((block) => this.doesRangeIntersectElement(range, block));\n\t}\n\n\tprivate createLineIntersectionRange(selectionRange: Range, line: HTMLElement): Range {\n\t\tconst lineRange = document.createRange();\n\t\tlineRange.selectNodeContents(line);\n\n\t\tif (line.contains(selectionRange.startContainer)) {\n\t\t\tlineRange.setStart(selectionRange.startContainer, selectionRange.startOffset);\n\t\t}\n\n\t\tif (line.contains(selectionRange.endContainer)) {\n\t\t\tlineRange.setEnd(selectionRange.endContainer, selectionRange.endOffset);\n\t\t}\n\n\t\treturn this.splitRangeBoundaries(lineRange);\n\t}\n\n\tprivate applyStyleToRange(\n\t\trange: Range,\n\t\tclassName: string,\n\t\tcommand: InlineClassCommand,\n\t\tcssValue?: string\n\t): HTMLElement | null {\n\t\tif (range.collapsed) return null;\n\t\tconst fragment = range.extractContents();\n\t\tconst wrapper = document.createElement(\"span\");\n\t\twrapper.classList.add(className);\n\t\tif (command === \"color\" && cssValue) wrapper.style.setProperty(\"color\", cssValue);\n\t\tif (command === \"backgroundColor\" && cssValue) wrapper.style.setProperty(\"background-color\", cssValue);\n\t\twrapper.append(fragment);\n\t\tthis.stripSameStyleFromFragment(wrapper, className, command);\n\t\tthis.removeCounterClasses(wrapper, command);\n\t\trange.insertNode(wrapper);\n\t\treturn wrapper;\n\t}\n\n\tprivate wrapMultilineSelectionWithClass(\n\t\tselectionRange: Range,\n\t\tclassName: string,\n\t\tcommand: InlineClassCommand,\n\t\tcssValue?: string,\n\t\ttargetLines?: HTMLElement[]\n\t): boolean {\n\t\tconst lines = targetLines || this.getSelectedLineBlocks(selectionRange);\n\t\tif (lines.length <= 1) return false;\n\n\t\tconst ranges = lines\n\t\t\t.map((line) => this.createLineIntersectionRange(selectionRange, line))\n\t\t\t.filter((lineRange) => !lineRange.collapsed);\n\n\t\tif (ranges.length === 0) return false;\n\n\t\tlet lastWrapper: HTMLElement | null = null;\n\t\tfor (let i = ranges.length - 1; i >= 0; i--) {\n\t\t\tconst wrapper = this.applyStyleToRange(ranges[i], className, command, cssValue);\n\t\t\tif (wrapper && !lastWrapper) lastWrapper = wrapper;\n\t\t}\n\n\t\tif (lastWrapper) this.setSelectionAtEnd(lastWrapper);\n\t\tthis.normalizeDocument();\n\t\tthis.cleanupEmptyTextStyleElements();\n\t\treturn true;\n\t}\n\n\tprivate redistributeInlineStylesAcrossBlocks(): void {\n\t\tconst knownStyleClasses = this.getKnownInlineStyleClassSet();\n\t\tlet changed = true;\n\n\t\twhile (changed) {\n\t\t\tchanged = false;\n\t\t\tconst spans = Array.from(this.element.querySelectorAll<HTMLElement>(\"span\")).reverse();\n\n\t\t\tfor (const span of spans) {\n\t\t\t\tif (!span.isConnected) continue;\n\t\t\t\tif (!this.isTextStyleWrapper(span, knownStyleClasses)) continue;\n\t\t\t\tif (this.isProtectedSpan(span)) continue;\n\n\t\t\t\tconst children = Array.from(span.childNodes);\n\t\t\t\tconst hasBlockChild = children.some(\n\t\t\t\t\t(node) => node instanceof HTMLElement && this.isLineBlockElement(node)\n\t\t\t\t);\n\t\t\t\tif (!hasBlockChild) continue;\n\n\t\t\t\tconst parent = span.parentNode;\n\t\t\t\tif (!parent) continue;\n\n\t\t\t\tconst replacement = document.createDocumentFragment();\n\t\t\t\tlet pendingInlineNodes: Node[] = [];\n\n\t\t\t\tconst flushInlineNodes = () => {\n\t\t\t\t\tif (pendingInlineNodes.length === 0) return;\n\t\t\t\t\tconst inlineSpan = this.cloneInlineStyleSpan(span);\n\t\t\t\t\tfor (const node of pendingInlineNodes) {\n\t\t\t\t\t\tinlineSpan.append(node);\n\t\t\t\t\t}\n\t\t\t\t\treplacement.append(inlineSpan);\n\t\t\t\t\tpendingInlineNodes = [];\n\t\t\t\t};\n\n\t\t\t\tfor (const child of children) {\n\t\t\t\t\tspan.removeChild(child);\n\t\t\t\t\tif (child instanceof HTMLElement && this.isLineBlockElement(child)) {\n\t\t\t\t\t\tflushInlineNodes();\n\t\t\t\t\t\tconst line = child;\n\t\t\t\t\t\tconst lineSpan = this.cloneInlineStyleSpan(span);\n\t\t\t\t\t\twhile (line.firstChild) lineSpan.append(line.firstChild);\n\t\t\t\t\t\tline.append(lineSpan);\n\t\t\t\t\t\treplacement.append(line);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpendingInlineNodes.push(child);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tflushInlineNodes();\n\t\t\t\tparent.insertBefore(replacement, span);\n\t\t\t\tspan.remove();\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isFontSizeClassName(className: string): boolean {\n\t\treturn FONT_SIZE_CLASS_SET.has(className);\n\t}\n\n\tprivate getElementFontSizeClass(el: HTMLElement): string | null {\n\t\tfor (const cls of FONT_SIZE_CLASSES) {\n\t\t\tif (el.classList.contains(cls)) return cls;\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate findOutermostFontSizeAncestor(node: Node): HTMLElement | null {\n\t\tlet current: Node | null = node.nodeType === Node.TEXT_NODE ? node.parentNode : node;\n\t\tlet outermost: HTMLElement | null = null;\n\t\twhile (current && current !== this.element) {\n\t\t\tif (current instanceof HTMLElement && this.getElementFontSizeClass(current)) {\n\t\t\t\toutermost = current;\n\t\t\t}\n\t\t\tcurrent = current.parentNode;\n\t\t}\n\t\treturn outermost;\n\t}\n\n\tprivate cleanupNestedFontSizeWrappers(): void {\n\t\tlet changed = true;\n\t\twhile (changed) {\n\t\t\tchanged = false;\n\t\t\tconst spans = Array.from(this.element.querySelectorAll<HTMLElement>(\"span\")).reverse();\n\n\t\t\tfor (const span of spans) {\n\t\t\t\tif (!span.isConnected) continue;\n\t\t\t\tif (span.closest(\"._media_, ._custom_\")) continue;\n\t\t\t\tif (!this.getElementFontSizeClass(span)) continue;\n\n\t\t\t\tlet parent = span.parentElement;\n\t\t\t\tlet outerSizeAncestor: HTMLElement | null = null;\n\t\t\t\twhile (parent && parent !== this.element) {\n\t\t\t\t\tif (this.getElementFontSizeClass(parent)) {\n\t\t\t\t\t\touterSizeAncestor = parent;\n\t\t\t\t\t}\n\t\t\t\t\tparent = parent.parentElement;\n\t\t\t\t}\n\n\t\t\t\tif (!outerSizeAncestor) continue;\n\t\t\t\tthis.breakOutFromAncestor(span, outerSizeAncestor);\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate hasMeaningfulAttributes(el: HTMLElement): boolean {\n\t\tfor (const attr of Array.from(el.attributes)) {\n\t\t\tconst name = attr.name.toLowerCase();\n\t\t\tconst value = attr.value.trim();\n\t\t\tif (name === \"class\") {\n\t\t\t\tif (el.classList.length > 0) return true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (name === \"style\") {\n\t\t\t\tif (el.style.length > 0 || value.length > 0) return true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (name.startsWith(\"data-\")) return true;\n\t\t\tif (name === \"id\" && value.length > 0) return true;\n\t\t\tif (name === \"contenteditable\" && value.length > 0) return true;\n\t\t\tif (value.length > 0) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate hasNonClassStyleAttributes(el: HTMLElement): boolean {\n\t\tfor (const attr of Array.from(el.attributes)) {\n\t\t\tconst name = attr.name.toLowerCase();\n\t\t\tif (name === \"class\" || name === \"style\") continue;\n\t\t\tif (name.startsWith(\"data-\")) return true;\n\t\t\tif (attr.value.trim().length > 0) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate isProtectedSpan(el: HTMLElement): boolean {\n\t\tif (el.tagName !== \"SPAN\") return true;\n\t\tif (el.classList.contains(\"_hashtag_\") || el.classList.contains(\"_urllink_\")) return true;\n\t\tif (el.closest(\"._media_, ._custom_\")) return true;\n\t\treturn false;\n\t}\n\n\tprivate cleanupRedundantTextWrappers(): void {\n\t\tconst knownStyleClasses = this.getKnownInlineStyleClassSet();\n\t\tlet changed = true;\n\t\twhile (changed) {\n\t\t\tchanged = false;\n\t\t\tconst spans = Array.from(this.element.querySelectorAll<HTMLElement>(\"span\")).reverse();\n\n\t\t\tfor (const span of spans) {\n\t\t\t\tif (!span.isConnected) continue;\n\t\t\t\tif (this.isProtectedSpan(span)) continue;\n\n\t\t\t\tconst children = Array.from(span.childNodes);\n\t\t\t\tconst elementChildren = children.filter((n): n is HTMLElement => n instanceof HTMLElement);\n\n\t\t\t\tif (elementChildren.length === 1 && children.length === 1) {\n\t\t\t\t\tconst child = elementChildren[0];\n\t\t\t\t\tif (\n\t\t\t\t\t\tchild.tagName === \"SPAN\" &&\n\t\t\t\t\t\t!this.isProtectedSpan(child) &&\n\t\t\t\t\t\tspan.className.trim() === child.className.trim() &&\n\t\t\t\t\t\tspan.style.cssText.trim() === child.style.cssText.trim() &&\n\t\t\t\t\t\t!this.hasNonClassStyleAttributes(span) &&\n\t\t\t\t\t\t!this.hasNonClassStyleAttributes(child)\n\t\t\t\t\t) {\n\t\t\t\t\t\twhile (child.firstChild) span.insertBefore(child.firstChild, child);\n\t\t\t\t\t\tchild.remove();\n\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!this.hasMeaningfulAttributes(span) && !this.isTextStyleWrapper(span, knownStyleClasses)) {\n\t\t\t\t\tconst parent = span.parentNode;\n\t\t\t\t\tif (!parent) continue;\n\t\t\t\t\twhile (span.firstChild) parent.insertBefore(span.firstChild, span);\n\t\t\t\t\tspan.remove();\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isTextStyleWrapper(el: HTMLElement, knownStyleClasses: Set<string>): boolean {\n\t\tif (el.tagName !== \"SPAN\") return false;\n\t\tif (el.classList.contains(\"_hashtag_\") || el.classList.contains(\"_urllink_\")) return false;\n\t\tfor (const cls of Array.from(el.classList)) {\n\t\t\tif (knownStyleClasses.has(cls) || cls.endsWith(\"_stop\")) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate cleanupEmptyTextStyleElements(): void {\n\t\tconst knownStyleClasses = this.getKnownInlineStyleClassSet();\n\t\tconst protectedSelector = \"br,hr,img,video,audio,table,ul,ol,li,blockquote,div,._media_,._custom_\";\n\n\t\tlet changed = true;\n\t\twhile (changed) {\n\t\t\tchanged = false;\n\t\t\tconst spans = Array.from(this.element.querySelectorAll<HTMLElement>(\"span\")).reverse();\n\t\t\tfor (const span of spans) {\n\t\t\t\tif (!this.isTextStyleWrapper(span, knownStyleClasses)) continue;\n\t\t\t\tif (span.querySelector(protectedSelector)) continue;\n\t\t\t\tconst text = (span.textContent || \"\").split(\"\\u200B\").join(\"\").trim();\n\t\t\t\tif (text.length === 0) {\n\t\t\t\t\tspan.remove();\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate setSelectionAtEnd(node: Node): void {\n\t\tconst range = document.createRange();\n\t\trange.selectNodeContents(node);\n\t\trange.collapse(false);\n\t\tthis.restoreLastSelection(range);\n\t}\n\n\tprivate splitRangeBoundaries(range: Range): Range {\n\t\tif (range.startContainer.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = range.startContainer as Text;\n\t\t\tif (range.startOffset > 0 && range.startOffset < text.length) {\n\t\t\t\ttext.splitText(range.startOffset);\n\t\t\t\trange.setStart(text.nextSibling as Node, 0);\n\t\t\t}\n\t\t}\n\t\tif (range.endContainer.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = range.endContainer as Text;\n\t\t\tif (range.endOffset > 0 && range.endOffset < text.length) {\n\t\t\t\ttext.splitText(range.endOffset);\n\t\t\t}\n\t\t}\n\t\treturn range;\n\t}\n\n\tprivate getKnownInlineStyleClassSet(): Set<string> {\n\t\treturn new Set(Object.values(CLASS_BY_COMMAND));\n\t}\n\n\tprivate findClosestAncestorWithClass(node: Node, className: string): HTMLElement | null {\n\t\tlet current: Node | null = node.nodeType === Node.TEXT_NODE ? node.parentNode : node;\n\t\twhile (current && current !== this.element) {\n\t\t\tif (current instanceof HTMLElement && current.classList.contains(className)) {\n\t\t\t\treturn current;\n\t\t\t}\n\t\t\tcurrent = current.parentNode;\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate findOutermostAncestorWithClass(node: Node, className: string): HTMLElement | null {\n\t\tlet current: Node | null = node.nodeType === Node.TEXT_NODE ? node.parentNode : node;\n\t\tlet outermost: HTMLElement | null = null;\n\t\twhile (current && current !== this.element) {\n\t\t\tif (current instanceof HTMLElement && current.classList.contains(className)) {\n\t\t\t\toutermost = current;\n\t\t\t}\n\t\t\tcurrent = current.parentNode;\n\t\t}\n\t\treturn outermost;\n\t}\n\n\tprivate collectPreservedInlineStyles(ancestor: HTMLElement, excludeClass: string): {\n\t\tclasses: string[];\n\t\tcolor?: string;\n\t\tbackgroundColor?: string;\n\t} {\n\t\tconst known = this.getKnownInlineStyleClassSet();\n\t\tconst classes: string[] = [];\n\t\tfor (const cls of Array.from(ancestor.classList)) {\n\t\t\tif (!known.has(cls)) continue;\n\t\t\tif (cls === excludeClass || cls === `${excludeClass}_stop`) continue;\n\t\t\tclasses.push(cls);\n\t\t}\n\n\t\treturn {\n\t\t\tclasses,\n\t\t\tcolor: ancestor.style.color || undefined,\n\t\t\tbackgroundColor: ancestor.style.backgroundColor || undefined,\n\t\t};\n\t}\n\n\tprivate liftNodeOneLevel(node: HTMLElement): void {\n\t\tconst parent = node.parentElement;\n\t\tif (!parent) return;\n\t\tif (parent === this.element) return;\n\t\tconst grand = parent.parentNode;\n\t\tif (!grand) return;\n\t\tif (grand !== this.element && !(grand instanceof HTMLElement && this.element.contains(grand))) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rightClone = parent.cloneNode(false) as HTMLElement;\n\t\twhile (node.nextSibling) {\n\t\t\trightClone.append(node.nextSibling);\n\t\t}\n\n\t\tgrand.insertBefore(node, parent.nextSibling);\n\t\tif (rightClone.childNodes.length) {\n\t\t\tgrand.insertBefore(rightClone, node.nextSibling);\n\t\t}\n\n\t\tif (parent.childNodes.length === 0) {\n\t\t\tparent.remove();\n\t\t}\n\t}\n\n\tprivate breakOutFromAncestor(node: HTMLElement, ancestor: HTMLElement): void {\n\t\tif (!this.element.contains(node) || !this.element.contains(ancestor)) return;\n\n\t\twhile (node.parentElement && node.parentElement !== ancestor) {\n\t\t\tthis.liftNodeOneLevel(node);\n\t\t}\n\n\t\tif (node.parentElement === ancestor && ancestor.parentElement && this.element.contains(ancestor.parentElement)) {\n\t\t\tthis.liftNodeOneLevel(node);\n\t\t}\n\n\t\tif (ancestor.childNodes.length === 0) {\n\t\t\tancestor.remove();\n\t\t}\n\t}\n\n\tprivate stripSameStyleFromFragment(root: HTMLElement, className: string, command: InlineClassCommand): void {\n\t\tconst same = root.querySelectorAll<HTMLElement>(`.${className}`);\n\t\tfor (const el of Array.from(same)) {\n\t\t\tel.classList.remove(className);\n\t\t\tif (command === \"color\") el.style.removeProperty(\"color\");\n\t\t\tif (command === \"backgroundColor\") el.style.removeProperty(\"background-color\");\n\t\t}\n\t}\n\n\tprivate wrapSelectionWithClass(className: string, command: InlineClassCommand, cssValue?: string): void {\n\t\tthis.captureRange();\n\t\tif (!this.range) return;\n\t\tconst range = this.splitRangeBoundaries(this.range.cloneRange());\n\t\tif (!range.collapsed) {\n\t\t\tconst startLine = this.getContainingLineBlock(range.startContainer);\n\t\t\tconst endLine = this.getContainingLineBlock(range.endContainer);\n\t\t\tif (startLine && endLine && startLine !== endLine) {\n\t\t\t\tconst lines = this.getLineBlocksBetween(startLine, endLine);\n\t\t\t\tif (this.wrapMultilineSelectionWithClass(range, className, command, cssValue, lines)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.wrapMultilineSelectionWithClass(range, className, command, cssValue)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tconst isFontSizeCommand = this.isFontSizeClassName(className);\n\t\tconst breakoutStartAncestor = this.findClosestAncestorWithClass(range.startContainer, className);\n\t\tconst breakoutEndAncestor = this.findClosestAncestorWithClass(range.endContainer, className);\n\t\tconst shouldBreakout = !!breakoutStartAncestor && breakoutStartAncestor === breakoutEndAncestor;\n\t\tconst sameClassBreakoutAncestor = shouldBreakout ? breakoutStartAncestor : null;\n\t\tconst fontSizeStartAncestor = isFontSizeCommand ? this.findOutermostFontSizeAncestor(range.startContainer) : null;\n\t\tconst fontSizeEndAncestor = isFontSizeCommand ? this.findOutermostFontSizeAncestor(range.endContainer) : null;\n\t\tconst fontSizeBreakoutAncestor =\n\t\t\tisFontSizeCommand && fontSizeStartAncestor && fontSizeStartAncestor === fontSizeEndAncestor\n\t\t\t\t? fontSizeStartAncestor\n\t\t\t\t: null;\n\t\tconst breakoutAncestor = sameClassBreakoutAncestor ?? fontSizeBreakoutAncestor;\n\t\tconst inherited = sameClassBreakoutAncestor\n\t\t\t? this.collectPreservedInlineStyles(sameClassBreakoutAncestor, className)\n\t\t\t: { classes: [] as string[], color: undefined, backgroundColor: undefined };\n\n\t\tif (range.collapsed) {\n\t\t\tconst span = document.createElement(\"span\");\n\t\t\tspan.classList.add(className);\n\t\t\tfor (const cls of inherited.classes) span.classList.add(cls);\n\t\t\tif (command !== \"color\" && inherited.color) span.style.setProperty(\"color\", inherited.color);\n\t\t\tif (command !== \"backgroundColor\" && inherited.backgroundColor)\n\t\t\t\tspan.style.setProperty(\"background-color\", inherited.backgroundColor);\n\t\t\tif (command === \"color\" && cssValue) {\n\t\t\t\tspan.style.setProperty(\"color\", cssValue);\n\t\t\t}\n\t\t\tif (command === \"backgroundColor\" && cssValue) {\n\t\t\t\tspan.style.setProperty(\"background-color\", cssValue);\n\t\t\t}\n\t\t\tconst anchor = document.createTextNode(\"\\u200B\");\n\t\t\tspan.append(anchor);\n\t\t\trange.insertNode(span);\n\t\t\tif (breakoutAncestor) {\n\t\t\t\tthis.breakOutFromAncestor(span, breakoutAncestor);\n\t\t\t}\n\t\t\tconst after = document.createRange();\n\t\t\tafter.setStart(anchor, 1);\n\t\t\tafter.collapse(true);\n\t\t\tthis.restoreLastSelection(after);\n\t\t\tthis.backupCurrentRange(after, { bypassNormalize: true });\n\t\t\tthis.element.focus({ preventScroll: true });\n\t\t\treturn;\n\t\t}\n\n\t\tconst fragment = range.extractContents();\n\t\tconst wrapper = document.createElement(\"span\");\n\t\twrapper.classList.add(className);\n\t\tfor (const cls of inherited.classes) wrapper.classList.add(cls);\n\t\tif (command !== \"color\" && inherited.color) wrapper.style.setProperty(\"color\", inherited.color);\n\t\tif (command !== \"backgroundColor\" && inherited.backgroundColor)\n\t\t\twrapper.style.setProperty(\"background-color\", inherited.backgroundColor);\n\t\tif (command === \"color\" && cssValue) wrapper.style.setProperty(\"color\", cssValue);\n\t\tif (command === \"backgroundColor\" && cssValue) wrapper.style.setProperty(\"background-color\", cssValue);\n\t\twrapper.append(fragment);\n\t\tthis.stripSameStyleFromFragment(wrapper, className, command);\n\t\tthis.removeCounterClasses(wrapper, command);\n\t\trange.insertNode(wrapper);\n\n\t\tif (breakoutAncestor) {\n\t\t\tthis.breakOutFromAncestor(wrapper, breakoutAncestor);\n\t\t}\n\n\t\tthis.setSelectionAtEnd(wrapper);\n\t\tthis.normalizeDocument();\n\t\tthis.cleanupEmptyTextStyleElements();\n\t}\n\n\tprivate removeCounterClasses(root: HTMLElement, command: InlineClassCommand): void {\n\t\tconst counters = COUNTER_CLASSES[command] || [];\n\t\tfor (const c of counters) {\n\t\t\troot.querySelectorAll(`.${c}`).forEach((node) => node.classList.remove(c));\n\t\t}\n\t}\n\n\tprivate isStyleAppliedToSelection(className: string): boolean {\n\t\tthis.captureRange();\n\t\tif (!this.range) return false;\n\n\t\tconst focusNode = this.range.collapsed ? this.range.startContainer : this.range.commonAncestorContainer;\n\t\tconst element = focusNode.nodeType === Node.TEXT_NODE ? focusNode.parentElement : (focusNode as Element);\n\t\tif (!element || !this.element.contains(element)) return false;\n\n\t\treturn !!element.closest(`.${className}`);\n\t}\n\n\tprivate removeStyleFromSelection(className: string, command: InlineClassCommand): void {\n\t\tthis.captureRange();\n\t\tif (!this.range) return;\n\n\t\tconst range = this.splitRangeBoundaries(this.range.cloneRange());\n\n\t\tconst collapsedOutermostAncestor = range.collapsed\n\t\t\t? this.findOutermostAncestorWithClass(range.startContainer, className)\n\t\t\t: null;\n\t\tconst startAncestor = this.findClosestAncestorWithClass(range.startContainer, className);\n\t\tconst endAncestor = this.findClosestAncestorWithClass(range.endContainer, className);\n\t\tconst breakoutAncestor = range.collapsed\n\t\t\t? collapsedOutermostAncestor\n\t\t\t: (startAncestor && startAncestor === endAncestor ? startAncestor : null);\n\n\t\tif (range.collapsed) {\n\t\t\tif (breakoutAncestor) {\n\t\t\t\tconst stop = document.createElement(\"span\");\n\t\t\t\tstop.classList.add(`${className}_stop`);\n\t\t\t\tconst stopAnchor = document.createTextNode(\"\\u200B\");\n\t\t\t\tstop.append(stopAnchor);\n\n\t\t\t\tif (this.isCollapsedStyleAnchorSpan(breakoutAncestor)) {\n\t\t\t\t\tconst parent = breakoutAncestor.parentNode;\n\t\t\t\t\tif (!parent) return;\n\t\t\t\t\tconst nextSibling = breakoutAncestor.nextSibling;\n\t\t\t\t\tbreakoutAncestor.remove();\n\t\t\t\t\tparent.insertBefore(stop, nextSibling);\n\t\t\t\t\tconst after = document.createRange();\n\t\t\t\t\tafter.setStart(stopAnchor, 1);\n\t\t\t\t\tafter.collapse(true);\n\t\t\t\t\tthis.restoreLastSelection(after);\n\t\t\t\t\tthis.backupCurrentRange(after, { bypassNormalize: true });\n\t\t\t\t\tthis.element.focus({ preventScroll: true });\n\t\t\t\t\tthis.ensureRootHasSafeLine();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst parent = breakoutAncestor.parentNode;\n\t\t\t\tif (!parent) return;\n\t\t\t\tparent.insertBefore(stop, breakoutAncestor.nextSibling);\n\t\t\t\tconst after = document.createRange();\n\t\t\t\tafter.setStart(stopAnchor, 1);\n\t\t\t\tafter.collapse(true);\n\t\t\t\tthis.restoreLastSelection(after);\n\t\t\t\tthis.backupCurrentRange(after, { bypassNormalize: true });\n\t\t\t\tthis.element.focus({ preventScroll: true });\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst inherited = breakoutAncestor\n\t\t\t? this.collectPreservedInlineStyles(breakoutAncestor, className)\n\t\t\t: { classes: [] as string[], color: undefined, backgroundColor: undefined };\n\n\t\tconst fragment = range.extractContents();\n\t\tconst wrapper = document.createElement(\"span\");\n\t\tfor (const cls of inherited.classes) wrapper.classList.add(cls);\n\t\tif (command !== \"color\" && inherited.color) wrapper.style.setProperty(\"color\", inherited.color);\n\t\tif (command !== \"backgroundColor\" && inherited.backgroundColor)\n\t\t\twrapper.style.setProperty(\"background-color\", inherited.backgroundColor);\n\t\twrapper.append(fragment);\n\n\t\tthis.stripSameStyleFromFragment(wrapper, className, command);\n\t\twrapper.classList.remove(className);\n\t\tif (command === \"color\") wrapper.style.removeProperty(\"color\");\n\t\tif (command === \"backgroundColor\") wrapper.style.removeProperty(\"background-color\");\n\n\t\trange.insertNode(wrapper);\n\t\tif (breakoutAncestor) {\n\t\t\tthis.breakOutFromAncestor(wrapper, breakoutAncestor);\n\t\t}\n\n\t\tthis.setSelectionAtEnd(wrapper);\n\t\tthis.normalizeDocument();\n\t\tthis.cleanupEmptyTextStyleElements();\n\t}\n\n\tprivate applyAlignment(command: AlignCommand): void {\n\t\tthis.captureRange();\n\t\tif (!this.range) return;\n\n\t\tconst line = this.getClosestLine(this.range.startContainer);\n\t\tif (!line) return;\n\n\t\tfor (const cls of ALIGN_CLASSES) line.classList.remove(cls);\n\t\tif (command === \"alignCenter\") line.classList.add(\"_alignCenter_\");\n\t\tif (command === \"alignRight\") line.classList.add(\"_alignRight_\");\n\t}\n\n\tprivate getClosestLine(node: Node): HTMLElement | null {\n\t\tlet current: Node | null = node;\n\t\twhile (current && current !== this.element) {\n\t\t\tif (current instanceof HTMLElement && (BLOCK_TAGS.has(current.tagName) || current.classList.contains(\"_media_\"))) {\n\t\t\t\treturn current;\n\t\t\t}\n\t\t\tcurrent = current.parentNode;\n\t\t}\n\t\treturn this.element.lastElementChild as HTMLElement | null;\n\t}\n\n\tprivate insertNodeAtSelection(node: Node, appendOnNextLine = true): void {\n\t\tthis.captureRange();\n\t\tif (!this.range) {\n\t\t\tthis.element.append(node);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!appendOnNextLine) {\n\t\t\tthis.range.insertNode(node);\n\t\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\t\tthis.setSelectionAtEnd(node);\n\t\t\t} else {\n\t\t\t\tconst after = document.createRange();\n\t\t\t\tafter.setStartAfter(node);\n\t\t\t\tafter.collapse(true);\n\t\t\t\tthis.restoreLastSelection(after);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst line = this.getClosestLine(this.range.endContainer);\n\t\tif (!line || !line.parentNode) {\n\t\t\tthis.element.append(node);\n\t\t\treturn;\n\t\t}\n\n\t\tif (line.nextSibling) line.parentNode.insertBefore(node, line.nextSibling);\n\t\telse line.parentNode.append(node);\n\t\tthis.setSelectionAtEnd(node);\n\t}\n\n\tprivate ensureCaretAfterNonTextElement(inserted: HTMLElement): void {\n\t\tif (!inserted.isConnected) return;\n\t\tconst parent = inserted.parentElement;\n\t\tif (!parent) return;\n\n\t\tlet next: Element | null = inserted.nextElementSibling;\n\t\tlet targetLine: HTMLElement | null = null;\n\t\twhile (next) {\n\t\t\tif (this.isLineBlockElement(next as HTMLElement)) {\n\t\t\t\ttargetLine = next as HTMLElement;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tnext = next.nextElementSibling;\n\t\t}\n\n\t\tif (!targetLine) {\n\t\t\ttargetLine = this.createEmptyParagraph();\n\t\t\tparent.append(targetLine);\n\t\t}\n\n\t\tif (targetLine.childNodes.length === 0) {\n\t\t\ttargetLine.append(document.createElement(\"br\"));\n\t\t}\n\n\t\tthis.setSelectionAtStart(targetLine);\n\t}\n\n\tprivate ensureTrailingEditableLineAfter(inserted: HTMLElement): HTMLElement {\n\t\tconst parent = inserted.parentElement;\n\t\tif (!parent) return this.createEmptyParagraph();\n\n\t\tconst immediateNext = inserted.nextElementSibling as HTMLElement | null;\n\t\tif (immediateNext && this.isLineBlockElement(immediateNext)) {\n\t\t\tif (immediateNext.childNodes.length === 0) immediateNext.append(document.createElement(\"br\"));\n\t\t\treturn immediateNext;\n\t\t}\n\n\t\tif (immediateNext && !this.isLineBlockElement(immediateNext)) {\n\t\t\tconst created = this.createEmptyParagraph();\n\t\t\tparent.insertBefore(created, immediateNext);\n\t\t\treturn created;\n\t\t}\n\n\t\tconst created = this.createEmptyParagraph();\n\t\tparent.append(created);\n\t\treturn created;\n\t}\n\n\tprivate insertText(text: string): void {\n\t\tthis.captureRange();\n\t\tif (!this.range) return;\n\t\tthis.range.deleteContents();\n\t\tconst lines = text.split(\"\\n\");\n\t\tif (lines.length === 1) {\n\t\t\tconst node = document.createTextNode(lines[0]);\n\t\t\tthis.range.insertNode(node);\n\t\t\tconst next = document.createRange();\n\t\t\tnext.setStart(node, node.length);\n\t\t\tnext.collapse(true);\n\t\t\tthis.restoreLastSelection(next);\n\t\t\treturn;\n\t\t}\n\n\t\tconst frag = document.createDocumentFragment();\n\t\tfor (let idx = 0; idx < lines.length; idx++) {\n\t\t\tif (idx > 0) frag.append(document.createElement(\"br\"));\n\t\t\tfrag.append(document.createTextNode(lines[idx]));\n\t\t}\n\t\tthis.range.insertNode(frag);\n\t}\n\n\tprivate async onImageSelected(ev: Event): Promise<void> {\n\t\tconst target = ev.target as HTMLInputElement;\n\t\tconst files = target.files;\n\t\tif (!files || files.length === 0) return;\n\t\tawait this.safeCallback({ loading: true });\n\n\t\tconst imageData: ImageData[] = [];\n\t\tfor (const file of Array.from(files)) {\n\t\t\tconst source = await this.readFileAsDataUrl(file);\n\t\t\tconst dimension = await this.readImageDimension(source);\n\t\t\timageData.push({\n\t\t\t\telementId: createUid(\"img\"),\n\t\t\t\tsource,\n\t\t\t\tfilename: file.name,\n\t\t\t\tfileType: file.type,\n\t\t\t\tfileSize: file.size,\n\t\t\t\tlastModified: file.lastModified,\n\t\t\t\tdimension,\n\t\t\t});\n\t\t}\n\n\t\tawait this.safeCallback({ loading: false });\n\t\ttarget.value = \"\";\n\n\t\tconst callbackResult = await this.safeCallback({ image: imageData });\n\t\tconst images = callbackResult.image || imageData;\n\t\tlet lastWrapper: HTMLElement | null = null;\n\n\t\tfor (const data of images) {\n\t\t\tconst wrapper = document.createElement(\"div\");\n\t\t\twrapper.classList.add(\"_media_\");\n\t\t\twrapper.setAttribute(\"contenteditable\", \"false\");\n\n\t\t\tconst image = data.element instanceof HTMLImageElement\n\t\t\t\t? data.element\n\t\t\t\t: document.createElement(\"img\");\n\t\t\timage.id = data.elementId || createUid(\"img\");\n\t\t\timage.setAttribute(\"src\", data.source);\n\t\t\timage.classList.add(`_img_${data.source.slice(-64).replace(/[^a-zA-Z0-9_-]/g, \"\")}`);\n\t\t\tif (Array.isArray(data.class)) for (const cls of data.class) image.classList.add(cls);\n\t\t\tif (data.onclick) {\n\t\t\t\timage.addEventListener(\"click\", data.onclick);\n\t\t\t\timage.classList.add(\"_hover_\");\n\t\t\t}\n\t\t\twrapper.append(image);\n\n\t\t\tif (data.style) {\n\t\t\t\tfor (const [k, v] of Object.entries(data.style)) {\n\t\t\t\t\twrapper.style.setProperty(k, v);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.image_array.push({ ...data, element: image, elementId: image.id });\n\t\t\tthis.insertNodeAtSelection(wrapper, true);\n\t\t\tlastWrapper = wrapper;\n\t\t}\n\n\t\tif (lastWrapper) {\n\t\t\tthis.ensureCaretAfterNonTextElement(lastWrapper);\n\t\t}\n\t}\n\n\tprivate readFileAsDataUrl(file: File): Promise<string> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst reader = new FileReader();\n\t\t\treader.onload = () => resolve(String(reader.result || \"\"));\n\t\t\treader.onerror = () => reject(reader.error || new Error(\"file read failed\"));\n\t\t\treader.readAsDataURL(file);\n\t\t});\n\t}\n\n\tprivate readImageDimension(source: string): Promise<{ width: number; height: number }> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst img = new Image();\n\t\t\timg.onload = () => resolve({ width: img.width, height: img.height });\n\t\t\timg.onerror = () => reject(new Error(\"image decode failed\"));\n\t\t\timg.src = source;\n\t\t});\n\t}\n\n\tprivate async safeCallback(payload: CallbackPayload): Promise<CallbackPayload> {\n\t\tif (typeof this.callback !== \"function\") return payload;\n\t\tconst next = this.callback(payload);\n\t\tconst result = next instanceof Promise ? await next : next;\n\t\treturn result || payload;\n\t}\n\n\tprivate resolveSpanByData(data: { element?: HTMLSpanElement; elementId?: string }): HTMLSpanElement | null {\n\t\tif (data.element instanceof HTMLSpanElement) return data.element;\n\t\tif (!data.elementId) return null;\n\t\tconst el = document.getElementById(data.elementId);\n\t\treturn el instanceof HTMLSpanElement ? el : null;\n\t}\n\n\tprivate applySpanDecorators(\n\t\tspan: HTMLSpanElement,\n\t\tdecorators: { style?: Record<string, string>; onclick?: (ev: MouseEvent) => void }\n\t): void {\n\t\tif (decorators.style) {\n\t\t\tfor (const [k, v] of Object.entries(decorators.style)) {\n\t\t\t\tspan.style.setProperty(k, v);\n\t\t\t}\n\t\t}\n\n\t\tif (decorators.onclick) {\n\t\t\tspan.addEventListener(\"click\", decorators.onclick);\n\t\t\tspan.classList.add(\"_hover_\");\n\t\t}\n\t}\n\n\tprivate isTransparentComputedColor(color: string): boolean {\n\t\tconst normalized = color.replace(/\\s+/g, \"\").toLowerCase();\n\t\tif (normalized === \"transparent\") return true;\n\t\tconst rgba = normalized.match(/^rgba\\((\\d+),(\\d+),(\\d+),([^\\)]+)\\)$/);\n\t\tif (!rgba) return false;\n\t\treturn Number(rgba[4]) === 0;\n\t}\n\n\tprivate resolveTrackerTextColor(anchor: Element): string {\n\t\tconst color = tryNormalizeColor(window.getComputedStyle(anchor).color);\n\t\treturn color || this.defaultFontColor;\n\t}\n\n\tprivate resolveTrackerBackgroundColor(anchor: Element): string {\n\t\tlet current: Element | null = anchor;\n\t\twhile (current) {\n\t\t\tconst bg = window.getComputedStyle(current).backgroundColor;\n\t\t\tif (!this.isTransparentComputedColor(bg)) {\n\t\t\t\tconst normalized = tryNormalizeColor(bg);\n\t\t\t\tif (normalized) return normalized;\n\t\t\t}\n\n\t\t\tif (current === this.element) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcurrent = current.parentElement;\n\t\t}\n\n\t\treturn this.defaultBackgroundColor;\n\t}\n\n\tprivate updateCommandTracker(): void {\n\t\tthis.trackerUpdateQueued = true;\n\t\tif (this.trackerUpdateInFlight) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.trackerUpdateInFlight = true;\n\t\tvoid this.flushCommandTrackerUpdates();\n\t}\n\n\tprivate async flushCommandTrackerUpdates(): Promise<void> {\n\t\ttry {\n\t\t\twhile (this.trackerUpdateQueued) {\n\t\t\t\tthis.trackerUpdateQueued = false;\n\t\t\t\tawait this.runCommandTrackerUpdate();\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.trackerUpdateInFlight = false;\n\t\t\tif (this.trackerUpdateQueued) {\n\t\t\t\tthis.trackerUpdateInFlight = true;\n\t\t\t\tvoid this.flushCommandTrackerUpdates();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async runCommandTrackerUpdate(): Promise<void> {\n\t\tlet currentRange: Range | null = null;\n\t\tconst sel = window.getSelection();\n\t\tif (\n\t\t\tsel &&\n\t\t\tsel.rangeCount > 0 &&\n\t\t\tthis.element.contains(sel.anchorNode) &&\n\t\t\tthis.element.contains(sel.focusNode)\n\t\t) {\n\t\t\tcurrentRange = this.normalizeEditorRange(sel.getRangeAt(0));\n\t\t}\n\n\t\tif (!currentRange) {\n\t\t\tthis.captureRange();\n\t\t\tcurrentRange = this.range;\n\t\t}\n\t\tconst active = document.activeElement;\n\t\tconst isColorInputActive = active instanceof HTMLInputElement && active.type === \"color\";\n\t\tconst isColorPickerInteractionActive =\n\t\t\tisColorInputActive || Date.now() < this.colorPickerInteractionUntil;\n\t\tif (!isColorPickerInteractionActive) {\n\t\t\tthis.livePickerColor = null;\n\t\t\tthis.livePickerBackgroundColor = null;\n\t\t}\n\n\t\tconst tracker = {\n\t\t\t// quote: false,\n\t\t\tunorderedList: false,\n\t\t\torderedList: false,\n\t\t\talignLeft: false,\n\t\t\talignCenter: false,\n\t\t\talignRight: false,\n\t\t\th1: false,\n\t\t\th2: false,\n\t\t\th3: false,\n\t\t\th4: false,\n\t\t\th5: false,\n\t\t\th6: false,\n\t\t\tsmall: false,\n\t\t\tbold: false,\n\t\t\titalic: false,\n\t\t\tunderline: false,\n\t\t\tstrike: false,\n\t\t\tcolor: this.defaultFontColor,\n\t\t\tbackgroundColor: this.defaultBackgroundColor,\n\t\t} as CommandTracker;\n\t\tlet line: HTMLElement | null = null;\n\t\tif (currentRange) {\n\t\t\tconst focusNode = currentRange.collapsed ? currentRange.startContainer : currentRange.commonAncestorContainer;\n\t\t\tconst element = focusNode.nodeType === Node.TEXT_NODE ? focusNode.parentElement : (focusNode as Element);\n\t\t\tif (element && this.element.contains(element)) {\n\t\t\t\ttracker.color = this.resolveTrackerTextColor(element);\n\t\t\t\ttracker.backgroundColor = this.resolveTrackerBackgroundColor(element);\n\n\t\t\t\tfor (const [command, cls] of Object.entries(this.styleTagOfCommand)) {\n\t\t\t\t\tconst stopOwner = element.closest(`.${cls}_stop`) as HTMLElement | null;\n\t\t\t\t\tconst owner = element.closest(`.${cls}`) as HTMLElement | null;\n\t\t\t\t\tif (stopOwner && owner && owner.contains(stopOwner)) continue;\n\t\t\t\t\tif (stopOwner && !owner) continue;\n\t\t\t\t\tif (!owner) continue;\n\t\t\t\t\tif (command === \"color\" || command === \"backgroundColor\") continue;\n\t\t\t\t\t(tracker as any)[command] = true;\n\t\t\t\t}\n\n\t\t\t\tline = this.getClosestLine(currentRange.startContainer);\n\t\t\t}\n\t\t}\n\n\t\tif (isColorPickerInteractionActive) {\n\t\t\tif (this.livePickerColor) tracker.color = this.livePickerColor;\n\t\t\tif (this.livePickerBackgroundColor) tracker.backgroundColor = this.livePickerBackgroundColor;\n\t\t}\n\n\t\tif (line) {\n\t\t\ttracker.alignLeft = !line.classList.contains(\"_alignCenter_\") && !line.classList.contains(\"_alignRight_\");\n\t\t\ttracker.alignCenter = line.classList.contains(\"_alignCenter_\");\n\t\t\ttracker.alignRight = line.classList.contains(\"_alignRight_\");\n\t\t\t// tracker.quote = !!line.closest(\"blockquote\");\n\t\t\ttracker.unorderedList = !!line.closest(\"ul\");\n\t\t\ttracker.orderedList = !!line.closest(\"ol\");\n\t\t}\n\n\t\tthis.commandTracker = tracker;\n\t\tlet caretRect: DOMRect | null = null;\n\t\tif (currentRange) {\n\t\t\tconst caretNode = currentRange.collapsed ? currentRange.startContainer : currentRange.endContainer;\n\t\t\tif (caretNode.nodeType === Node.TEXT_NODE) caretRect = currentRange.getBoundingClientRect();\n\t\t\telse if (caretNode instanceof Element) caretRect = caretNode.getBoundingClientRect();\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.safeCallback({\n\t\t\t\tcommandTracker: tracker,\n\t\t\t\trange: currentRange,\n\t\t\t\tcaratPosition: caretRect,\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tconsole.error(err);\n\t\t}\n\t}\n\n\tprivate async scanSpecialTokens(): Promise<void> {\n\t\tif (!this.hashtagEnabled && !this.urlEnabled) return;\n\n\t\tconst sel = window.getSelection();\n\t\tconst liveRange =\n\t\t\tsel && sel.rangeCount > 0 && this.element.contains(sel.anchorNode)\n\t\t\t\t? this.normalizeEditorRange(sel.getRangeAt(0))\n\t\t\t\t: null;\n\t\tconst selectionSnapshot = liveRange\n\t\t\t? this.snapshotRangeToTextOffsets(liveRange)\n\t\t\t: null;\n\t\tlet didMutate = false;\n\n\t\tconst walker = document.createTreeWalker(this.element, NodeFilter.SHOW_TEXT, {\n\t\t\tacceptNode: (node) => {\n\t\t\t\tconst text = node.textContent || \"\";\n\t\t\t\tif (!text.trim()) return NodeFilter.FILTER_REJECT;\n\t\t\t\tconst parent = node.parentElement;\n\t\t\t\tif (!parent) return NodeFilter.FILTER_REJECT;\n\t\t\t\tif (parent.closest(\"._media_, ._custom_, ._hashtag_, ._urllink_\")) {\n\t\t\t\t\treturn NodeFilter.FILTER_REJECT;\n\t\t\t\t}\n\t\t\t\treturn NodeFilter.FILTER_ACCEPT;\n\t\t\t},\n\t\t});\n\n\t\tconst textNodes: Text[] = [];\n\t\twhile (walker.nextNode()) {\n\t\t\ttextNodes.push(walker.currentNode as Text);\n\t\t}\n\n\t\tconst hashtagItems: HashtagData[] = [];\n\t\tconst urlItems: UrlData[] = [];\n\n\t\tfor (const textNode of textNodes) {\n\t\t\tconst text = textNode.textContent || \"\";\n\t\t\tconst parent = textNode.parentNode;\n\t\t\tif (!parent) continue;\n\n\t\t\tconst chunks: Array<{ type: \"text\" | \"hashtag\" | \"url\"; value: string }> = [];\n\t\t\tlet lastIndex = 0;\n\t\t\tconst matches: Array<{ index: number; end: number; type: \"hashtag\" | \"url\"; value: string }> = [];\n\n\t\t\tif (this.hashtagEnabled) {\n\t\t\t\tfor (const m of text.matchAll(HASHTAG_REGEX)) {\n\t\t\t\t\tconst lead = m[1] || \"\";\n\t\t\t\t\tconst tag = m[2] || \"\";\n\t\t\t\t\tconst index = (m.index || 0) + lead.length;\n\t\t\t\t\tmatches.push({ index, end: index + tag.length, type: \"hashtag\", value: tag });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.urlEnabled) {\n\t\t\t\tfor (const m of text.matchAll(URL_REGEX)) {\n\t\t\t\t\tconst value = m[0] || \"\";\n\t\t\t\t\tconst index = m.index || 0;\n\t\t\t\t\tmatches.push({ index, end: index + value.length, type: \"url\", value });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmatches.sort((a, b) => a.index - b.index);\n\t\t\tconst filtered: typeof matches = [];\n\t\t\tlet occupiedEnd = -1;\n\t\t\tfor (const m of matches) {\n\t\t\t\tif (m.index < occupiedEnd) continue;\n\t\t\t\tfiltered.push(m);\n\t\t\t\toccupiedEnd = m.end;\n\t\t\t}\n\t\t\tif (filtered.length === 0) continue;\n\n\t\t\tfor (const m of filtered) {\n\t\t\t\tif (m.index > lastIndex) {\n\t\t\t\t\tchunks.push({ type: \"text\", value: text.slice(lastIndex, m.index) });\n\t\t\t\t}\n\t\t\t\tchunks.push({ type: m.type, value: m.value });\n\t\t\t\tlastIndex = m.end;\n\t\t\t}\n\t\t\tif (lastIndex < text.length) chunks.push({ type: \"text\", value: text.slice(lastIndex) });\n\n\t\t\tconst fragment = document.createDocumentFragment();\n\t\t\tfor (const chunk of chunks) {\n\t\t\t\tif (chunk.type === \"text\") {\n\t\t\t\t\tfragment.append(document.createTextNode(chunk.value));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst span = document.createElement(\"span\");\n\t\t\t\tspan.setAttribute(\"contenteditable\", \"false\");\n\t\t\t\tspan.textContent = chunk.value;\n\t\t\t\tif (chunk.type === \"hashtag\") {\n\t\t\t\t\tconst id = createUid(\"hashtag\");\n\t\t\t\t\tspan.id = id;\n\t\t\t\t\tspan.className = `_hashtag_ _hashtag_${chunk.value}`;\n\t\t\t\t\thashtagItems.push({ elementId: id, tag: chunk.value.replace(/^#/, \"\"), element: span });\n\t\t\t\t} else {\n\t\t\t\t\tconst id = createUid(\"urllink\");\n\t\t\t\t\tspan.id = id;\n\t\t\t\t\tspan.className = `_urllink_ _urllink_${chunk.value}`;\n\t\t\t\t\tspan.addEventListener(\"click\", () => {\n\t\t\t\t\t\tconst url = /^https?:\\/\\//i.test(chunk.value) ? chunk.value : `http://${chunk.value}`;\n\t\t\t\t\t\twindow.open(url, \"_blank\", \"noopener,noreferrer\");\n\t\t\t\t\t});\n\t\t\t\t\turlItems.push({ elementId: id, url: chunk.value, element: span });\n\t\t\t\t}\n\t\t\t\tfragment.append(span);\n\t\t\t}\n\n\t\t\tparent.replaceChild(fragment, textNode);\n\t\t\tdidMutate = true;\n\t\t}\n\n\t\tif (hashtagItems.length > 0) {\n\t\t\tconst fb = await this.safeCallback({ hashtag: hashtagItems });\n\t\t\tfor (const item of fb.hashtag || hashtagItems) {\n\t\t\t\tconst span = this.resolveSpanByData(item);\n\t\t\t\tif (!span) continue;\n\t\t\t\tthis.applySpanDecorators(span, item);\n\t\t\t\tthis.hashtag_array.push({ ...item, element: span, elementId: span.id || item.elementId });\n\t\t\t}\n\t\t}\n\t\tif (urlItems.length > 0) {\n\t\t\tconst fb = await this.safeCallback({ urllink: urlItems });\n\t\t\tfor (const item of fb.urllink || urlItems) {\n\t\t\t\tconst span = this.resolveSpanByData(item);\n\t\t\t\tif (!span) continue;\n\t\t\t\tthis.applySpanDecorators(span, item);\n\t\t\t\tthis.urllink_array.push({ ...item, element: span, elementId: span.id || item.elementId });\n\t\t\t}\n\t\t}\n\n\t\tif (didMutate && selectionSnapshot) {\n\t\t\tconst rebased = this.restoreRangeFromTextOffsets(selectionSnapshot);\n\t\t\tif (rebased) {\n\t\t\t\tthis.restoreLastSelection(rebased);\n\t\t\t\tthis.backupCurrentRange(rebased, { bypassNormalize: true });\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async command(action: CommandInput): Promise<void> {\n\t\tconst isColorObjectAction =\n\t\t\ttypeof action === \"object\" &&\n\t\t\t!!action &&\n\t\t\t[\"color\", \"backgroundColor\"].some((cmd) => cmd in action);\n\t\tconst activeElement = document.activeElement;\n\t\tconst activeColorInput =\n\t\t\tactiveElement instanceof HTMLInputElement && activeElement.type === \"color\";\n\n\t\tif (isColorObjectAction && typeof action === \"object\" && action) {\n\t\t\tthis.colorPickerInteractionUntil = Date.now() + 500;\n\t\t\tif (typeof action.color === \"string\") {\n\t\t\t\tthis.livePickerColor = tryNormalizeColor(action.color) || action.color;\n\t\t\t}\n\t\t\tif (typeof action.backgroundColor === \"string\") {\n\t\t\t\tthis.livePickerBackgroundColor = tryNormalizeColor(action.backgroundColor) || action.backgroundColor;\n\t\t\t}\n\t\t}\n\n\t\tif (isColorObjectAction && (this.suspendSelectionCaptureForColorPicker || activeColorInput)) {\n\t\t\tconst sel = window.getSelection();\n\t\t\tconst liveRange =\n\t\t\t\tsel &&\n\t\t\t\t\tsel.rangeCount > 0 &&\n\t\t\t\t\tthis.element.contains(sel.anchorNode) &&\n\t\t\t\t\tthis.element.contains(sel.focusNode)\n\t\t\t\t\t? this.normalizeEditorRange(sel.getRangeAt(0))\n\t\t\t\t\t: null;\n\n\t\t\tif (liveRange) {\n\t\t\t\tthis.range = liveRange;\n\t\t\t\tthis.backupCurrentRange(liveRange, { bypassNormalize: true });\n\t\t\t} else if (this.rangeBackup) {\n\t\t\t\tthis.restoreLastSelection(this.rangeBackup);\n\t\t\t\tthis.range = this.rangeBackup.cloneRange();\n\t\t\t} else {\n\t\t\t\tthis.captureRange();\n\t\t\t}\n\t\t} else {\n\t\t\tthis.captureRange();\n\t\t}\n\n\t\tif (!isColorObjectAction) {\n\t\t\tthis.suspendSelectionCaptureForColorPicker = false;\n\t\t}\n\n\t\tif (typeof action === \"string\") {\n\t\t\tconst stringCmdRangeWasCollapsed = !!(this.range && this.range.collapsed);\n\n\t\t\tif (this.customCommandHandlers.has(action)) {\n\t\t\t\tawait this.customCommandHandlers.get(action)?.(this, action);\n\t\t\t\t// return;\n\t\t\t}\n\n\t\t\telse if ((Object.keys(CLASS_BY_COMMAND) as InlineClassCommand[]).includes(action as InlineClassCommand)) {\n\t\t\t\tconst className = CLASS_BY_COMMAND[action as InlineClassCommand];\n\t\t\t\tif (action === \"color\") {\n\t\t\t\t\t// Color command behaves as a setter for highlightColor.\n\t\t\t\t\tthis.wrapSelectionWithClass(CLASS_BY_COMMAND.color, \"color\", this.highlightColor);\n\t\t\t\t} else {\n\t\t\t\t\tconst isApplied = this.isStyleAppliedToSelection(className);\n\t\t\t\t\tif (isApplied) {\n\t\t\t\t\t\tthis.removeStyleFromSelection(className, action as InlineClassCommand);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.wrapSelectionWithClass(className, action as InlineClassCommand);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\telse if ([\"alignLeft\", \"alignCenter\", \"alignRight\"].includes(action)) {\n\t\t\t\tthis.applyAlignment(action as AlignCommand);\n\t\t\t}\n\n\t\t\telse if (action === \"divider\") {\n\t\t\t\tconst hr = document.createElement(\"hr\");\n\t\t\t\tthis.insertNodeAtSelection(hr, true);\n\t\t\t\tthis.ensureCaretAfterNonTextElement(hr);\n\t\t\t\tthis.backupCurrentRange();\n\t\t\t}\n\n\t\t\telse if (action === \"quote\") {\n\t\t\t\tif (this.range) {\n\t\t\t\t\tconst quoteParent = this.getContainingQuote(this.range.startContainer);\n\t\t\t\t\tif (quoteParent) {\n\t\t\t\t\t\tthis.unwrapQuote(quoteParent);\n\t\t\t\t\t\tthis.normalizeDocument();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst quote = document.createElement(\"blockquote\");\n\t\t\t\tconst quoteLine = this.createEmptyParagraph();\n\t\t\t\tquote.append(quoteLine);\n\t\t\t\tthis.insertNodeAtSelection(quote, true);\n\t\t\t\tthis.ensureTrailingEditableLineAfter(quote);\n\t\t\t\tthis.setSelectionAtStart(quoteLine);\n\t\t\t\tthis.backupCurrentRange();\n\t\t\t}\n\n\t\t\telse if (action === \"unorderedList\" || action === \"orderedList\") {\n\t\t\t\tconst list = document.createElement(action === \"unorderedList\" ? \"ul\" : \"ol\");\n\t\t\t\tconst li = document.createElement(\"li\");\n\t\t\t\tli.append(document.createElement(\"br\"));\n\t\t\t\tlist.append(li);\n\t\t\t\tthis.insertNodeAtSelection(list, true);\n\t\t\t\tthis.ensureTrailingEditableLineAfter(list);\n\t\t\t\tthis.setSelectionAtStart(li);\n\t\t\t\tthis.backupCurrentRange();\n\t\t\t}\n\n\t\t\telse if (action === \"image\") {\n\t\t\t\tthis.imageInput.click();\n\t\t\t}\n\n\t\t\telse {\n\t\t\t\tconst maybeColor = tryNormalizeColor(action);\n\t\t\t\tif (maybeColor) {\n\t\t\t\t\tthis.wrapSelectionWithClass(CLASS_BY_COMMAND.color, \"color\", maybeColor);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For collapsed ranges, wrapSelectionWithClass already placed the caret inside the\n\t\t\t// new styled span — don't overwrite it with the stale backup.\n\t\t\tconst isInlineStyleCommand = (Object.keys(CLASS_BY_COMMAND) as string[]).includes(action) ||\n\t\t\t\t!!tryNormalizeColor(action);\n\t\t\tif (!stringCmdRangeWasCollapsed || !isInlineStyleCommand) {\n\t\t\t\tthis.restoreLastSelection();\n\t\t\t}\n\t\t\tthis.updateCommandTracker();\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof action === \"object\" && action) {\n\t\t\tconst trackIt = [\"color\", \"backgroundColor\"].some((cmd) => cmd in action);\n\t\t\tif (trackIt) {\n\t\t\t\tconst selectionSnapshot = this.range\n\t\t\t\t\t? this.snapshotRangeToTextOffsets(this.range)\n\t\t\t\t\t: null;\n\n\t\t\t\tconst rangeWasCollapsed = !!(this.range && this.range.collapsed);\n\n\t\t\t\tconst applyColorCommand = (\n\t\t\t\t\tnextAction: { color?: string; backgroundColor?: string },\n\t\t\t\t\tnextSnapshot: { start: number; end: number } | null\n\t\t\t\t): void => {\n\t\t\t\t\tif (nextAction.backgroundColor) {\n\t\t\t\t\t\tconst color = tryNormalizeColor(nextAction.backgroundColor) || nextAction.backgroundColor;\n\t\t\t\t\t\tthis.wrapSelectionWithClass(CLASS_BY_COMMAND.backgroundColor, \"backgroundColor\", color);\n\t\t\t\t\t}\n\t\t\t\t\telse if (nextAction.color) {\n\t\t\t\t\t\tconst color = tryNormalizeColor(nextAction.color) || nextAction.color;\n\t\t\t\t\t\tthis.wrapSelectionWithClass(CLASS_BY_COMMAND.color, \"color\", color);\n\t\t\t\t\t}\n\n\t\t\t\t\t// For collapsed ranges wrapSelectionWithClass already placed the caret\n\t\t\t\t\t// inside the new styled span — don't overwrite that with the pre-wrap offset.\n\t\t\t\t\tif (!rangeWasCollapsed) {\n\t\t\t\t\t\tif (nextSnapshot) {\n\t\t\t\t\t\t\tconst rebased = this.restoreRangeFromTextOffsets(nextSnapshot);\n\t\t\t\t\t\t\tif (rebased) {\n\t\t\t\t\t\t\t\tthis.restoreLastSelection(rebased);\n\t\t\t\t\t\t\t\tthis.backupCurrentRange(rebased, { bypassNormalize: true });\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.restoreLastSelection();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.restoreLastSelection();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.updateCommandTracker();\n\t\t\t\t\tthis.suspendSelectionCaptureForColorPicker =\n\t\t\t\t\t\tdocument.activeElement instanceof HTMLInputElement &&\n\t\t\t\t\t\tdocument.activeElement.type === \"color\";\n\t\t\t\t};\n\n\t\t\t\tif (activeColorInput) {\n\t\t\t\t\tapplyColorCommand(\n\t\t\t\t\t\t{ color: action.color, backgroundColor: action.backgroundColor },\n\t\t\t\t\t\tselectionSnapshot\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tapplyColorCommand(\n\t\t\t\t\t{ color: action.color, backgroundColor: action.backgroundColor },\n\t\t\t\t\tselectionSnapshot\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\telse if (action.element !== undefined) {\n\t\t\t\tlet node: Node | null = null;\n\t\t\t\tlet customElement: HTMLElement | null = null;\n\t\t\t\tif (typeof action.element === \"string\") {\n\t\t\t\t\tnode = document.createTextNode(action.element);\n\t\t\t\t} else if (isHTMLElement(action.element)) {\n\t\t\t\t\tnode = action.element;\n\t\t\t\t\tcustomElement = action.element;\n\t\t\t\t\tif (action.elementId) (node as HTMLElement).id = action.elementId;\n\t\t\t\t}\n\t\t\t\tif (!node) return;\n\n\t\t\t\tif (node instanceof HTMLElement && action.style) {\n\t\t\t\t\tfor (const [k, v] of Object.entries(action.style)) {\n\t\t\t\t\t\tif (typeof v === \"string\") node.style.setProperty(k, v);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (node instanceof HTMLElement) {\n\t\t\t\t\tnode.classList.add(\"_custom_\");\n\t\t\t\t\tthis.custom_array.push({ elementId: node.id || createUid(\"custom\"), element: node });\n\t\t\t\t}\n\n\t\t\t\tconst isTextNode = node.nodeType === Node.TEXT_NODE;\n\t\t\t\tthis.insertNodeAtSelection(node, !isTextNode);\n\t\t\t\tif (customElement) {\n\t\t\t\t\tthis.ensureCaretAfterNonTextElement(customElement);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.suspendSelectionCaptureForColorPicker = false;\n\t}\n\n\tpublic async loadHTML(html: string, editable = false): Promise<void> {\n\t\tif (typeof html !== \"string\") throw new Error(\"html should be a string\");\n\n\t\tthis.setEditable(false);\n\t\tthis.element.innerHTML = \"\";\n\t\tthis.image_array = [];\n\t\tthis.hashtag_array = [];\n\t\tthis.urllink_array = [];\n\t\tthis.custom_array = [];\n\n\t\tconst div = document.createElement(\"div\");\n\t\tdiv.innerHTML = html;\n\n\t\tfor (const node of Array.from(div.childNodes)) {\n\t\t\tthis.element.append(node);\n\t\t}\n\n\t\tconst imageEls = this.element.querySelectorAll<HTMLImageElement>(\"._media_ img\");\n\t\tfor (const img of Array.from(imageEls)) {\n\t\t\tconst elementId = img.id || createUid(\"img\");\n\t\t\timg.id = elementId;\n\t\t\tthis.image_array.push({ elementId, source: img.getAttribute(\"src\") || \"\", element: img });\n\t\t}\n\n\t\tconst hashtags = this.element.querySelectorAll(\"._hashtag_\");\n\t\tfor (const tag of Array.from(hashtags)) {\n\t\t\tconst elementId = tag.id || createUid(\"hashtag\");\n\t\t\ttag.id = elementId;\n\t\t\tthis.hashtag_array.push({\n\t\t\t\telementId,\n\t\t\t\ttag: (tag.textContent || \"\").replace(/^#/, \"\"),\n\t\t\t\telement: tag as HTMLSpanElement,\n\t\t\t});\n\t\t}\n\n\t\tconst urls = this.element.querySelectorAll(\"._urllink_\");\n\t\tfor (const u of Array.from(urls)) {\n\t\t\tconst elementId = u.id || createUid(\"urllink\");\n\t\t\tu.id = elementId;\n\t\t\tthis.urllink_array.push({\n\t\t\t\telementId,\n\t\t\t\turl: u.textContent || \"\",\n\t\t\t\telement: u as HTMLSpanElement,\n\t\t\t});\n\t\t}\n\n\t\tconst customs = this.element.querySelectorAll(\"._custom_\");\n\t\tfor (const c of Array.from(customs)) {\n\t\t\tconst elementId = c.id || createUid(\"custom\");\n\t\t\tc.id = elementId;\n\t\t\tthis.custom_array.push({ elementId, element: c as HTMLElement });\n\t\t}\n\n\t\tthis.normalizeDocument();\n\t\tif (editable) this.setEditable(true);\n\t\tif (this.element.childNodes.length === 0) this.element.append(this.createEmptyParagraph());\n\t\tthis.updateCommandTracker();\n\t\tthis.updatePlaceholderVisibility();\n\t}\n\n\tpublic async export(\n\t\tpre?: (setup: ExportSetup) => ExportSetup | Promise<ExportSetup>\n\t): Promise<ExportPayload> {\n\t\tthis.normalizeDocument();\n\t\tconst dom = this.element.cloneNode(true) as HTMLElement;\n\t\tlet setup: ExportSetup = {\n\t\t\tdom,\n\t\t\turllink: this.urlEnabled ? this.urllink_array : undefined,\n\t\t\thashtag: this.hashtagEnabled ? this.hashtag_array : undefined,\n\t\t\timage: this.image_array,\n\t\t\tcustom: this.custom_array,\n\t\t\ttitle: \"\",\n\t\t};\n\n\t\tif (pre) {\n\t\t\tconst out = pre(setup);\n\t\t\tsetup = (out instanceof Promise ? await out : out) || setup;\n\t\t}\n\n\t\tconst lines = Array.from(setup.dom.querySelectorAll(\":scope > *\"));\n\t\tlet title = setup.title || \"\";\n\t\tconst textParts: string[] = [];\n\n\t\tfor (const line of lines) {\n\t\t\tconst txt = (line.textContent || \"\").trim();\n\t\t\tif (!txt) continue;\n\t\t\tif (!title) {\n\t\t\t\ttitle = txt.slice(0, 200);\n\t\t\t\tif (txt.length > 200) textParts.push(txt.slice(200));\n\t\t\t} else {\n\t\t\t\ttextParts.push(txt);\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\thtml: setup.dom.innerHTML,\n\t\t\ttitle: title.trim(),\n\t\t\ttext: textParts.join(\"\\n\").trim(),\n\t\t\turllink: this.urlEnabled ? setup.urllink : undefined,\n\t\t\thashtag: this.hashtagEnabled ? setup.hashtag : undefined,\n\t\t\timage: setup.image,\n\t\t\tcustom: setup.custom,\n\t\t};\n\t}\n}\n\n"],"mappings":"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","names":["wysiwyg4all_exports","__export","Wysiwyg4All","__toCommonJS","CLASS_BY_COMMAND","COUNTER_CLASSES","ALIGN_CLASSES","FONT_SIZE_CLASSES","FONT_SIZE_CLASS_SET","BLOCK_TAGS","HASHTAG_REGEX","URL_REGEX","clampNumber","value","min","max","toPx","fallback","isHTMLElement","isNode","createUid","prefix","rand","ts","tryNormalizeColor","input","test","computed","match","g","b","v","buildDefaultScheme","highlightColor","focus","Wysiwyg4All","option","__publicField","ev","target","sel","normalized","active","nextActive","text","elementId","element","err","baseKeys","key","scheme","contentText","contentBg","contentFocus","fontSize","fs","desktop","tablet","phone","ratioDefaults","tag","raw","parsed","extensions","api","name","handler","eventName","createExtension","args","handlers","first","seed","p","node","range","line","el","quote","parent","firstChild","currentLine","lines","targetLine","prev","normalizedRange","reanchored","buildRangeInsidePlaceholder","anchor","next","tryFromContainer","container","offset","before","after","candidates","tryFromAncestorBoundary","startNode","preferNext","sibling","direct","textNode","idx","preferOffset","source","params","bypassNormalize","candidate","rangeBackup","probe","charOffset","remaining","walker","lastText","len","last","start","end","snapshot","atStart","current","childNodes","point","normalizedCollapsed","placeholder","enabled","only","hasPlaceholder","editable","shouldShow","track","mutations","mutation","textNodes","i","hasLiveSelectionInEditor","rangeSource","rangeSnapshot","toRemove","rebased","span","clone","startLine","endLine","blocks","startIndex","endIndex","from","to","nodeRange","endsBefore","startsAfter","block","selectionRange","lineRange","className","command","cssValue","fragment","wrapper","targetLines","ranges","lastWrapper","knownStyleClasses","changed","spans","children","replacement","pendingInlineNodes","flushInlineNodes","inlineSpan","child","lineSpan","cls","outermost","outerSizeAncestor","attr","elementChildren","n","protectedSelector","ancestor","excludeClass","known","classes","grand","rightClone","root","same","isFontSizeCommand","breakoutStartAncestor","breakoutEndAncestor","sameClassBreakoutAncestor","fontSizeStartAncestor","fontSizeEndAncestor","breakoutAncestor","inherited","counters","c","focusNode","collapsedOutermostAncestor","startAncestor","endAncestor","stop","stopAnchor","nextSibling","appendOnNextLine","inserted","immediateNext","created","frag","files","imageData","file","dimension","images","data","image","k","resolve","reject","reader","img","payload","decorators","color","rgba","bg","currentRange","isColorPickerInteractionActive","tracker","stopOwner","owner","caretRect","caretNode","liveRange","selectionSnapshot","didMutate","hashtagItems","urlItems","chunks","lastIndex","matches","m","lead","index","a","filtered","occupiedEnd","chunk","id","url","fb","item","action","isColorObjectAction","cmd","activeElement","activeColorInput","stringCmdRangeWasCollapsed","hr","quoteParent","quoteLine","list","li","maybeColor","isInlineStyleCommand","rangeWasCollapsed","applyColorCommand","nextAction","nextSnapshot","customElement","isTextNode","html","div","imageEls","hashtags","urls","u","customs","pre","setup","out","title","textParts","txt"]}